fix(deps): update code dependencies (dev) #3

Merged
renovate Bot merged 1 commits from renovate/dev-code-dependencies into dev 2026-10-08 04:04:33 +00:00

This PR contains the following updates:

Package Change Age Confidence
@biomejs/biome (source) 2.5.2 → 2.5.13 age confidence
modernc.org/sqlite v1.59.0 → v1.60.1 age confidence
ultracite (source) 7.9.0 → 7.12.2 age confidence

Release Notes

biomejs/biome (@​biomejs/biome)

v2.5.13

Compare Source

Patch Changes

v2.5.12

Compare Source

Patch Changes
  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed Astro attribute expressions rejecting TypeScript and JSX syntax that is accepted in text expressions.

    <Component icon={<Icon />} count={total as number} onSelect={(e: Event) => e} />
    
  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed Astro attribute names being split on : and . inside an expression, such as {x && <button x-on:keyup.enter={go} client:load.foo />}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed a bare > in the children of an Astro expression being treated as markup, such as {x && <div>a > b</div>}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed HTML comments inside an Astro expression failing to parse. They are now read as trivia, wherever they appear among the children.

    {x && <div><!-- first -->text<!-- last --></div>}
    {cond && <a></a><!-- c --><b></b>}
    
  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed is:raw children inside an Astro expression being read as JSX, such as {x && <div is:raw>{not js} < & text</div>}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed an apostrophe or quote in the text of a JSX element inside an Astro expression ending the expression early, such as {items.map((i) => <li>it's {i}</li>)}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed the children of a <script> or <style> inside an Astro expression being read as JSX. Their contents are text, so braces and comparisons no longer have to be escaped.

    {cond && <style>a { color: red }</style>}
    {cond && <script>let x = {a: 1};</script>}
    
  • #​11440 b88f1ea Thanks @​Princesseuh! - Added support for template literal attribute values inside an Astro expression, such as {x && <C data-x=`t${x}` />}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed unquoted attribute values being rejected inside an Astro expression, such as {x && <a class=foo maxlength=255 href=/about>go</a>}.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed a template literal nested inside ${} breaking the rest of an Astro file, such as const href = `/blog${page === 0 ? '' : `/${page + 1}`}`;.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed a quote inside a regex character class breaking the rest of an Astro file, such as const unsafe = /[/"]/;.

  • #​11508 54f3a2e Thanks @​dyc3! - Added the nursery rule useFlatMathMinMax. Because Math.min() and Math.max() accept any number of arguments, the rule reports unnecessary nested calls to the same method:

    Math.max(Math.max(a, b), c);
    

    The fix flattens this expression to Math.max(a, b, c).

  • #​11585 c5c8315 Thanks @​Netail! - Fixed #​11475: noUnresolvedImports no longer reports Bun runtime built-in modules (bun, bun:bundle, bun:ffi, bun:jsc, bun:sqlite, bun:test).

  • #​11368 52a57b3 Thanks @​Austin1serb! - Fixed #​6830: Biome now reports a diagnostic for excessively deep syntax instead of overflowing the native stack while releasing the parsed tree.

  • #​11596 1fc42ed Thanks @​dyc3! - Added the nursery rule noThisOutsideOfClass. The rule reports this outside class members and TypeScript functions with an explicit this parameter.

    function Person(name) {
        this.name = name;
    }
    
  • #​11555 2516335 Thanks @​dyc3! - Fixed #​11529, where noFloatingPromises missed unhandled Promise chains when the imported function's module belonged to an import cycle. Cyclic modules now preserve types for exports that do not participate in recursive type dependencies.

  • #​11518 0fee70c Thanks @​HarperZ9! - Fixed #​11500: the formatter now prints the declare modifier before accessibility modifiers on class properties. private declare readonly name: string is now formatted as declare private readonly name: string, matching Prettier and TypeScript's canonical modifier order.

  • #​11580 1277af2 Thanks @​ematipico! - Fixed #​5091: Biome no longer moves comments next to the < of a generic, which causes invalid TypeScript syntax:

    - Generic<// a comment
    + Generic<
    +   // a comment
    
  • #​11577 42995d2 Thanks @​ematipico! - Fixed #​4592. Biome no longer crashes while parsing malformed delete expressions.

  • #​11590 67963b4 Thanks @​ematipico! - Fixed #​6427 so Grit plugins can use function = ... as a node argument.

  • #​11600 a689cb5 Thanks @​ematipico! - Fixed #​6644: noUnusedVariables now recognizes all interface declarations in a TypeScript declaration-merging group when the interface is referenced.

    The following snippet no longer triggers the rule.

    interface Things {
        foo: string;
    }
      interface Things {
        bar: string;
    }
      export type Key = keyof Things;
      interface Things {
        baz: string;
    }
    
  • #​11591 d4a0716 Thanks @​ematipico! - Fixed #​6615. noDuplicateProperties no longer reports declarations nested in block at-rules as duplicates of declarations in their parent block.

  • #​11492 f2a07aa Thanks @​santichausis! - Fixed #​11454: noMisplacedAssertion now recognises @fast-check/vitest's test.prop(...) (and .concurrent.prop, .skip.prop, etc.) as a test function, the same way it already recognises test.each. The JS formatter picks up the same recognition, so a curried test.prop(...)(...) call is now formatted with the regular breakable argument layout used for test.each/test.for, instead of the single-line-hugging layout used for plain it/test calls.

    For example, Biome no longer reports the assertion below as misplaced:

    import { fc, test } from "@fast-check/vitest";
      test.prop([fc.string()])("round-trips", (s) => {
      expect(s).toBe(s);
    });
    
  • #​11589 65742b3 Thanks @​ematipico! - Fixed #​4928: noUnusedVariables no longer reports a value declaration as unused when its merged namespace is referenced.

  • #​11559 472dbc2 Thanks @​levrik! - Fixed a false positive in noVueDuplicateKeys where a <script setup> variable initialized from props was reported as a duplicate of the prop it derives from. Biome now exempts any variable whose initializer references props, instead of only recognizing defineProps() and toRefs(props).

    For example, Biome no longer reports foo below as a duplicate key:

    <script setup>
    import { toRef } from 'vue';
    const props = defineProps(['foo']);
    const foo = toRef(props, 'foo');
    </script>
    
  • #​11594 6586ceb Thanks @​ematipico! - Fixed #​6640. Biome no longer crashes when linting malformed for...of statements.

  • #​11571 85b197d Thanks @​ematipico! - Fixed #​10838: useSortedAttributes no longer corrupts JSX attributes when nested JSX elements also require sorting.

  • #​11533 97e76c0 Thanks @​ematipico! - Fixed #​11520, where the Biome scanner would start analysing dependencies multiple times, leading to long and unresponsive sessions.

  • #​11564 18a0e1f Thanks @​Netail! - Fixed the diagnostic range of noInferrableTypes so it now highlights only the type instead of including the leading : colon, spaces and comments.

  • #​11540 124fdaa Thanks @​ematipico! - Fixed #11537: noShorthandPropertyOverrides now compares declarations only within the same block. The rule no longer reports @supports feature queries and correctly checks nested, @keyframes, and @page blocks.

  • #​11532 7ceb0ee Thanks @​dyc3! - Fixed #​11528: noFloatingPromises no longer reports statement-level await expressions that handle Promise values, including overloaded calls returning Promise aliases. Awaited values that resolve to arrays of Promises remain reported because their element Promises are not handled by await.

  • #​11474 3c6412e Thanks @​dyc3! - Fixed #​10241. Biome no longer reports unsupported text expression diagnostics for double-curly text in vanilla HTML, and the formatter preserves adjacent curly-brace text.

  • #​11593 6c7fd27 Thanks @​dyc3! - Added the nursery rule noVueDeprecatedScopedSlots. It reports deprecated $scopedSlots references in Vue templates and component objects, and offers an unsafe replacement with $slots. For example, Biome now reports this.$scopedSlots.default inside a Vue component.

  • #​11440 b88f1ea Thanks @​Princesseuh! - Fixed the formatter crashing on an Astro or Svelte expression spanning several lines in a file with CRLF line endings, such as <p>{a +\r\n b}</p>.

  • #​11581 f4e5ebb Thanks @​dyc3! - Added the nursery rule useModernMathApis. The rule reports legacy mathematical patterns that have direct modern Math equivalents.

    Math.sqrt(a * a + b * b);
    
  • #​11597 a20f44a Thanks @​Netail! - Added the nursery rule noBunModules, which forbids the use of Bun builtin modules (e.g. bun:sqlite, bun:ffi).

  • #​11545 7d54688 Thanks @​dyc3! - Fixed #​11542: Biome now reports HTML comments between Svelte tag attributes as parse errors.

  • #​11582 b6611dd Thanks @​ematipico! - Fixed #​3862. Biome now parses legacy Internet Explorer filter and -ms-filter values such as progid:DXImageTransform... and alpha(opacity=40).

  • #​11575 65da251 Thanks @​dyc3! - Improved the Tailwind parser's ability to recover from parsing failures. Whitespace now always allows the parser to recover and start parsing a new class.

  • #​11576 0f78499 Thanks @​ematipico! - Fixed #​3515 and #​10395, where Biome could corrupt Unicode characters while writing source received through standard input to standard output. Characters such as ⚠ and ✔ are now preserved.

  • #​11539 0fca643 Thanks @​ematipico! - Fixed #​11512, where style/noDescendingSpecificity missed lower-specificity selectors after a later higher-specificity selector with the same tail selector.

  • #​11544 040f867 Thanks @​dyc3! - Fixed #​11541: formatting a Svelte render tag followed by an HTML comment no longer duplicates the comment.

     <div>
       {@render children?.()}
       <!-- comment -->
    -  <!-- comment -->
     </div>
    
  • #​11565 ee69e0e Thanks @​ematipico! - Fixed #​11525. Now the configuration schema correctly provides auto-completion for linter domains.

  • #​11583 b19390c Thanks @​dyc3! - Fixed #​11352: useExplicitLengthCheck no longer reports length-like properties used as value-producing || fallbacks or optional chains, and it no longer offers fixes for value-producing && checks or unsafe negations.

  • #​11562 753e955 Thanks @​ematipico! - Fixed an issue where the Biome Language Server would start with logging level set to debug. This would cause logs to grow exponentially in long sessions.

  • #​11217 7d3ee9c Thanks @​dyc3! - Fixed handling of biome-ignore format suppression comments on TypeScript declared class properties with string literal names.

    class A {
    	declare /* biome-ignore format: exercise suppression checking */ 'a-b': 0;
    }
    
  • #​11497 f5d7896 Thanks @​dyc3! - Added the noInvalidFileInputAccept nursery rule. The rule reports invalid literal accept values on file inputs in JSX and HTML, and normalizes common mistakes.

    <input type="file" accept="image/jpg" />
    
  • #​11345 ac58958 Thanks @​jakeleventhal! - Improved type inference performance by avoiding resolution of unused members in object arguments.

  • #​11554 2d55931 Thanks @​Netail! - Added the new nursery rule useReactNamingConvention, which enforces naming conventions for React values assigned from createContext, useId, and useRef. A value from createContext must be a PascalCase component name ending with Context, a value from useId must be named id or end with Id, and a value from useRef must be named ref or end with Ref.

  • #​11491 1d6210b Thanks @​dyc3! - Added the nursery rule noUnmodifiedLoopCondition, which reports variables in loop conditions that are never modified in the loop.

    let node = getNode();
    while (node) {
        process(node);
    }
    

v2.5.11

Compare Source

Patch Changes
  • #​11499 9743d0c Thanks @​scs0209! - Fixed #​11496: useValidAnchor now treats Astro JSX shorthand attributes like <a {href}> as a valid href.

  • #​11437 88f805e Thanks @​Princesseuh! - Fixed #​9944: adjacent elements inside an Astro expression now parse as an implicit fragment instead of raising an error.

    {options.map(() =>
      <div />
      <div />
    )}
    
  • #​11437 88f805e Thanks @​Princesseuh! - Fixed Astro templates rejecting unclosed HTML void elements, such as {cond && <br>}.

  • #​11507 e2fc036 Thanks @​dyc3! - Fixed #​11157: noUnusedVariables no longer reports Vue <script setup> bindings used by CSS v-bind() as unused.

  • #​11398 afc4615 Thanks @​dyc3! - Fixed #​11389: Files passed through --stdin-file-path now use full HTML support for Astro, Svelte, and Vue when it is enabled.

  • #​11526 372cd68 Thanks @​dyc3! - Fixed noVueRefAsOperand to track Vue refs through declaration aliases and toRefs() properties, and to recognize useTemplateRef() results. The rule no longer reports false positives such as plain ref transfers, plain toRefs() property access, defineModel() modifiers, or the supported .effect member as operands.

    The refactor enabling these fixes also improves the performance of the rule.

  • #​11458 a7cd286 Thanks @​dyc3! - Fixed #​11436: GritQL snippets such as export { $specifiers } from $source now match named re-exports with aliases, inline type modifiers, and multiple specifiers.

  • #​11515 382b15d Thanks @​dyc3! - Fixed #​11390, where noFloatingPromises performed expensive full type inference for calls to non-Promise methods declared on third-party TypeScript classes. The rule now classifies those calls using targeted type information.

  • #​11516 6f40e82 Thanks @​levrik! - Fixed noVueRefAsOperand so it no longer reports a callback parameter (e.g. from .find(), .map()) as an unwrapped ref value just because it's nested inside a ref(), computed(), or similar call.

    const result = computed(() => list.find((item) => item.label === "a"));
    

    Previously, item here was incorrectly treated as a ref value because the rule attributed it to the outer computed() call.

  • #​11495 496268d Thanks @​Netail! - Fixed useGraphqlNamingConvention so it no longer reports GraphQL enum value definitions with comments & descriptions and now displays a more accurate diagnostic range.

  • #​11407 6ef52b0 Thanks @​1678092075! - Fixed #​11214: noUnusedVariables no longer reports type parameters declared by non-default function overload signatures that have an implementation.

  • #​11322 5c353e6 Thanks @​jp-knj! - Added a new nursery rule noAstroSetHtmlDirective, which disallows Astro's set:html directive because untrusted content can introduce cross-site scripting vulnerabilities.

    For example, the following snippet triggers the rule:

    <div set:html={content} />
    
  • #​11462 18883b7 Thanks @​dyc3! - Fixed #​10776: useVueHyphenatedAttributes no longer reports lowercase attribute names containing punctuation, such as pt:header:data-test-id and some_attr.

  • #​11476 3270ca4 Thanks @​dyc3! - Fixed #​10330: Vue interpolation delimiters now stay attached to whitespace-sensitive element boundaries and adjacent inline siblings, wrapping their expression when needed to fit the configured line width. Interpolations followed by text now also converge after one formatting pass.

    -<v-btn v-if="store.state.user" variant="text" to="/my-rooms"
    -  >{{ $t("nav.my-rooms") }}</v-btn
    ->
    +<v-btn v-if="store.state.user" variant="text" to="/my-rooms">{{
    +  $t("nav.my-rooms")
    +}}</v-btn>
    
  • #​11191 3e5367f Thanks @​ematipico! - Added the nursery rule noUndeclaredCustomProperties, which reports references to custom properties that are not defined in available CSS, static HTML-like style attributes, or JSX string style attributes.

    For example, the following snippet triggers the rule:

    a { color: var(--undefined-color); }
    
  • #​11435 7754894 Thanks @​levrik! - Fixed: Variables and imports used as custom Vue directives are no longer reported as unused.

    For example:

    <script setup>
    const vHighlight = {
      mounted: (element) => {
        element.style.color = "red";
      },
    };
    </script>
      <template>
      <p v-highlight>Hello</p>
    </template>
    
  • #​11501 e6acded Thanks @​aminya! - Improved the performance of useArraySortCompare by skipping type inference for calls to unrelated methods.

  • #​11467 66b282c Thanks @​dyc3! - Fixed #​11464: Biome now parses parenthesized object literals returned from arrow functions when they contain a conditional expression and a nested arrow function.

  • #​11456 db9aa2a Thanks @​dyc3! - Fixed #​10278: Marked the fix for noThisInStatic as unsafe by default.

  • #​11502 652aedb Thanks @​levrik! - noGlobalAssign no longer reports assignments to a Vue <script setup> binding from a template expression, when the binding's name happens to match a built-in global (e.g. open, parent, top).

    For example, this no longer triggers a diagnostic:

    <script setup>
    const open = defineModel();
    </script>
      <template>
      <button @click="open = !open">Toggle</button>
    </template>
    

v2.5.10

Compare Source

Patch Changes
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed Astro rejecting JavaScript comments between attributes.

    <div /* block comment */ class="something"></div>
    <Component /* c */ client:load />
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed a bare < in Astro text being treated as the start of a tag, such as <p>5 < 6 and 7 > 6</p>. As in HTML, a < that cannot open a tag is text and needs no escaping.

  • #​11438 3133ffa Thanks @​Princesseuh! - Fixed #​8294: an Astro expression holding only a comment is no longer reported as a parse error, which also stopped the whole file from being formatted.

    <div>{/* a note */}</div>
    <div class={/* a note */}>x</div>
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed #​9165: an empty Astro expression such as <div>{}</div> no longer fails to parse. Astro renders {} as nothing.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed Astro expressions containing a comment failing to parse.

    <div>{/* block comment */ x}</div>
    <div>{/* only a comment */}</div>
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Added support for Astro's fragment shorthand.

    <>
      <p>a</p>
    </>
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed an Astro frontmatter block being cut short by a closing tag inside a string or comment.

    ---
    const a = "</script>";
    // </script> in a comment
    ---
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed --- being read as an Astro frontmatter fence when markup precedes it. Astro only recognizes frontmatter at the very start of a file, so a file opening with a comment now has no frontmatter, and its --- lines are content.

    <!-- c -->
    ---
    this is text, not frontmatter
    ---
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed an Astro frontmatter block ending early on a line that merely starts with a dash.

    ---
    --count;
    ---
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed the children of an Astro element carrying is:raw being parsed as markup instead of raw text. This now also covers <script> and <style>, whose contents Astro emits verbatim rather than processing, so they are no longer linted as JavaScript or CSS.

    <article is:raw><% awesome %></article>
    <script is:raw>{{ mustache }}</script>
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed Astro rejecting attribute names that start with a colon, such as :href.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed the Astro parser failing to recover from a malformed closing tag such as <div></{<//, so that a later mistake is reported where it happens rather than cascading.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed { inside an Astro <math> element opening an expression. MathML is foreign content where Astro parses no expressions, so LaTeX such as R^{2x} now survives as text. <svg> is unaffected.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed {{ at the start of an Astro expression being read as an interpolation. Astro has no {{ }} syntax, so {{ a: 1 }} and <Comp a={{ b: 1 }} /> are object literals.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed expressions inside an Astro <pre> or <textarea> being read as raw text. Astro parses both as ordinary elements, so their markup and interpolations are now parsed, and a variable used only inside one is no longer reported as unused.

    <pre>{value}</pre>
    <textarea><div>{value}</div></textarea>
    
  • #​11403 8f7786f Thanks @​Princesseuh! - Added support for template literal attribute values in Astro, such as <div class=`a ${b} c`>.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed Astro rejecting HTML5 unquoted attribute values that contain `, =, ' or ", such as <a href=a=b> and <a href=a'b>.

  • #​11393 dec5a8f Thanks @​1678092075! - Fixed #​11207: useStrictMode no longer reports Vue event handlers such as @click="count++".

  • #​11431 c065f99 Thanks @​levrik! - Fixed #​11429: Variables and imports used by Vue same-name bindings such as :disabled or v-bind:disabled are no longer reported as unused.

  • #​11409 405dedb Thanks @​ematipico! - Fixed a memory leak in the LSP server where memory usage kept growing over long editor sessions.

  • #​11422 a51eff7 Thanks @​dyc3! - Fixed #​11416: Biome no longer crashes when parsing incomplete {let} or {const} declarations in Svelte files.

  • #​11378 34b715c Thanks @​Netail! - Added extra rule sources from @eslint/css. biome migrate eslint detects rules in your eslint configurations more reliably.

  • #​11403 8f7786f Thanks @​Princesseuh! - Fixed {#, {/, {: and {@ being read as Svelte block openings in every HTML-like file. They are now Svelte-only, so in HTML, Vue and Angular files a sequence such as {#if x} is ordinary text instead of a parse error.

  • #​11443 8d45229 Thanks @​ematipico! - Fixed #​11390: noFloatingPromises no longer performs unnecessary type inference on call arguments when checking methods of non-generic class instances created with new.

  • #​11425 9c2667b Thanks @​dyc3! - Fixed #​6426: GritQL plugins now match and rewrite metavariables embedded in quoted strings.

  • #​11441 00317c3 Thanks @​dyc3! - Improved performance of useNamedCaptureGroup, noMisplacedAssertion, noSkippedTests, noExportsInTest, noDuplicateTestHooks, noIdenticalTestTitle, useTestHooksInOrder, and useTestHooksOnTop.

v2.5.9

Compare Source

Patch Changes
  • #​11321 41386f3 Thanks @​dyc3! - Fixed #​11315: The CSS parser now recovers at declaration boundaries after bogus declarations, allowing subsequent valid declarations to be parsed.

  • #​11248 57b197e Thanks @​yanthomasdev! - Expanded the environment variable metadata used by biome rage to include BIOME_BINARY, BIOME_LOG_FILE, and RUST_BACKTRACE as well as reworded explanations for better readability.

  • #​11377 a8798ea Thanks @​Netail! - Added a new nursery rule useNamedLayer which disallows anonymous cascade layers.

    @layer {
      a {
        color: red;
      }
    }
    
  • #​11327 6771cf5 Thanks @​dyc3! - The HTML formatter now preserves meaningful blank lines in HTML, including spacing after elements with trailing spaces and blank lines between comment groups.

     <div>
       <!-- first group -->
    +
       <!-- second group -->
     </div>
    
  • #​10312 ba8aa18 Thanks @​dyc3! - Added the nursery rule useTailwindShorthandClasses, which suggests shorter Tailwind utility classes. For example, the rule suggests replacing w-4 h-4 with size-4.

  • #​11333 715e0cd Thanks @​kkkhs! - Fixed #​11328: lint/nursery/useExpect now recognizes Vitest Browser Mode expect.element() calls as assertions.

  • #​11343 9b98211 Thanks @​johncarmack1984! - Fixed #​11311: the CSS parser now accepts Tailwind container-query variant names in @variant, such as @xl and @max-xl. These previously produced a parse error and a noUnknownAtRules diagnostic.

    @variant @xl {
      div {
        background: red;
      }
    }
    
  • #​11220 3e8c488 Thanks @​santichausis! - Fixed #​9541: noUndeclaredVariables, noUnusedImports, and noUnusedVariables now correctly recognise exported variables and functions declared in one embedded <script> block as usable from a sibling <script> block, in Svelte's <script module>/<script> pair and Vue's non-setup <script> blocks.

    For example, Biome no longer reports greet as undeclared in the following Svelte component:

    <script module>
      export function greet() {
        console.log("Hello!");
      }
    </script>
    
    <script>
      greet();
    </script>
    
  • #​11300 36430eb Thanks @​dyc3! - Fixed the HTML formatter's whitespace handling for marquee, noscript, video, audio, and object elements.

    - <marquee behavior="alternate"> This text will bounce </marquee>
    + <marquee behavior="alternate">This text will bounce</marquee>
    
  • #​11299 6559e6c Thanks @​jp-knj! - Added the nursery rule useAstroClientOnlyDirectiveValue, which reports Astro client:only directives without an initializer.

    For example, <Component client:only /> triggers the rule.

  • #​11365 7529811 Thanks @​MHJahanbakhsh! - Fixed #​11229: The useGenericFontNames rule now treats math as a valid generic font family.

  • #​11346 674f5f4 Thanks @​Jayllyz! - Fixed #​11335: noComponentHookFactories now reports a use-prefixed variable only when a function is assigned to it directly.

    function factory() {
      const useColors = true; // no longer reported
      const useStore = createStore({ count: 0 }); // no longer reported
      const useData = () => useState(null); // still reported
      return useColors;
    }
    
  • #​11334 c87c46a Thanks @​zkasuran! - Fixed #​11317: noSvgWithoutTitle no longer reports an svg that uses the boolean shorthand aria-hidden (equivalent to aria-hidden={true} in React).

  • #​11364 13853b1 Thanks @​ematipico! - Fixed a bug where useJsxKeyInIterable incorrectly flagged Astro files.

  • #​11321 41386f3 Thanks @​dyc3! - Fixed #​11315: Invalid CSS declarations in HTML style attributes now produce parser diagnostics instead of causing a panic.

  • #​11325 67c3bf0 Thanks @​dyc3! - Fixed HTML text wrapping to account for the width of an adjacent closing tag, avoiding lines that exceed the configured width when the final word and tag must move together.

     <a-long-long-long-element
    -  >foo bar foo bar foo bar foo bar foo bar foo bar foo bar</a-long-long-long-element
    +  >foo bar foo bar foo bar foo bar foo bar foo
    +  bar</a-long-long-long-element
     >
    
  • #​11367 fe5b5d4 Thanks @​ematipico! - Fixed TypeScript compilerOptions.paths resolution when mapping targets omit ./. Biome now resolves these targets relative to their configured path base.

  • #​11316 17e48d6 Thanks @​wanxiankai! - Fixed #​11289: the safe fix for noExtraBooleanCast now preserves parentheses around nested conditional expressions.

  • #​11254 d25d113 Thanks @​dyc3! - Fixed #​11242: Biome no longer crashes with an access violation when analysing files on Windows ARM64.

  • #​11221 85aac73 Thanks @​freeatnet! - Added the nursery rule noUnsafeTypeAssertion, which disallows TypeScript type assertions while allowing const assertions.

    const value = input as SomeType;
    
  • #​11314 7ffb677 Thanks @​ematipico! - Fixed #​11310: Restored the performance of noMisusedPromises and noFloatingPromises when analyzed expressions share deep imported type paths.

  • #​11356 6cd3263 Thanks @​johncarmack1984! - The Tailwind parser now understands modifiers on bare utilities (@container/sidebar, shadow/50).

  • #​11318 76059e9 Thanks @​johncarmack1984! - The Tailwind parser now understands container-query variants (@sm:, @max-lg:, @min-[400px]:) and child and descendant variants (*:, **:).

  • #​11357 faa2074 Thanks @​johncarmack1984! - The Tailwind parser now accepts the legacy leading ! important marker (!flex, hover:!p-4).

  • #​11344 f34e15c Thanks @​johncarmack1984! - The Tailwind parser now understands combinator selectors in arbitrary variants (has-[>svg]:, has-[+p]:), modifiers on variants (group-hover/menu:, @sm/main:), and arbitrary container-query sizes (@[400px]:).

  • #​11324 2f5d452 Thanks @​dyc3! - Fixed HTML formatting that inserted rendered whitespace between an element and touching text when the line wrapped.

      <div>
    -   before<meter value=".5"></meter>
    -   after
    +   before<meter value=".5"></meter
    +   >after
      </div>
    
  • #​11312 e65f07e Thanks @​xosnos! - Added a new nursery rule useControlLabel for both HTML and JSX, which reports interactive control elements (button, menuitem) without an accessible label.

    <button />
    
  • #​11364 13853b1 Thanks @​ematipico! - Fixed SVG parsing for files with an XML declaration followed by a PUBLIC doctype, such as <?xml version="1.0"?><!DOCTYPE svg PUBLIC "a" "b">.

  • #​11301 610ee28 Thanks @​dyc3! - Fixed parent tag wrapping when an HTML element starts or ends with a block-like or hidden child such as source, track, or param.

    - <video src="brave.webm"><track kind="subtitles" src="brave.en.vtt"></video>
    + <video src="brave.webm">
    +   <track kind="subtitles" src="brave.en.vtt">
    + </video>
    

v2.5.8

Compare Source

Patch Changes

v2.5.7

Compare Source

Patch Changes
  • #​10822 c171b3b Thanks @​pkallos! - Added the option ignoreIfStatements to useNullishCoalescing. Biome now flags if statements that only assign to a nullish variable (such as if (!a) { a = b }) and can rewrite them to ??=. When enabled, Biome ignores those if statements.

  • #​11136 e63354c Thanks @​AkashNaickar! - Added a new nursery rule noExtendNative, which reports extending the prototype of a built-in object.

  • #​10094 e007143 Thanks @​THEjacob1000! - Added the nursery rule noTailwindArbitraryValue. Biome now reports Tailwind CSS arbitrary values such as w-[400px], including in HTML/JSX class attributes, configured utility functions, and tagged templates.

  • #​11184 135f476 Thanks @​subotac! - Fixed #​11176: noUnknownPseudoClass now recognizes Vue's :deep() pseudo-class inside .vue style blocks.

  • #​8239 a519f9d Thanks @​cormacrelf! - Fixed #​8233, where Biome CLI in
    stdin mode didn't work correctly when handling files in projects with nested
    configurations. For example, with the following structure,
    --stdin-file-path=subdirectory/... would not use the nested configuration in
    subdirectory/biome.json:

    ├── biome.json
    └── subdirectory
        ├── biome.json
        └── lib.js
    
    biome format --write --stdin-file-path=subdirectory/lib.js < subdirectory/lib.js
    

    Now, the nested configuration is correctly picked up and applied.

    In addition, Biome now shows a warning if --stdin-file-path is provided but
    that path is ignored and therefore not formatted or fixed.

  • #​11138 8c2c6bd Thanks @​ematipico! - Fixed noUnnecessaryConditions: Biome now chooses the same function overload as TypeScript when an argument is a callback, so conditions that were previously missed are reported.

    The following code is now invalid, because a parameter typed () => void accepts an async callback and schedule therefore returns string:

    declare function schedule(handler: () => void): string;
    declare function schedule(handler: () => Promise<void>): string | undefined;
    
    schedule(async () => {}) ?? "fallback";
    

    The following code is also now invalid, because map(() => 42) returns 42:

    type Mapper<T> = () => T;
    declare function map<T>(mapper: Mapper<T>): T;
    
    map(() => 42) || flag;
    
  • #​11138 8c2c6bd Thanks @​ematipico! - Fixed #​11087: noUnnecessaryConditions no longer reports optional chains and nullish coalescing whose receiver can be nullish.

    For example, the optional chain and fallback in the following code are no longer reported:

    declare const usage: { range: { startDate: string } } | null;
    const startDate = usage?.range.startDate ?? "N/A";
    
  • #​11118 9c16840 Thanks @​subotac! - Fixed #​11098: The HTML formatter now preserves the configured trailing newline when a file ends with a comment.

    -<!-- trailing comment -->
    \ No newline at end of file
    +<!-- trailing comment -->
    
  • #​11201 0e80610 Thanks @​Bishwas-py! - Fixed #​11182: suppression comments for noPositiveTabindex now suppress the rule in HTML files when the attributes of the element span multiple lines.

  • #​11079 607afd2 Thanks @​dyc3! - The HTML formatter now lays out the srcset attribute of <img> and <source> as the list of candidates it is. Runs of whitespace between candidates collapse, and once the list no longer fits on one line each candidate goes on its own line with the descriptors aligned:

    - <img srcset="/visual@0.5.png  400w, /visual.png 805w, /visual@2x.png 1610w, /visual@3x.png 2415w" />
    + <img
    +   srcset="
    +     /visual@0.5.png  400w,
    +     /visual.png      805w,
    +     /visual@2x.png  1610w,
    +     /visual@3x.png  2415w
    +   "
    + />
    
  • #​11156 fed72c7 Thanks @​saberoueslati! - Fixed #​11129: noUnusedVariables no longer reports Vue bindings as unused when they are assigned through automatically unwrapped template refs.

  • #​11124 d890b39 Thanks @​denbezrukov! - Fixed CSS formatting of line comments between a declaration colon and value to preserve their source indentation.

     .test {
       background:
    -  /////// foo
    -  // bar
    +        /////// foo
    +        // bar
         radial-gradient(circle, #&#8203;000, transparent);
     }
    
  • #​11113 3d8ab73 Thanks @​denbezrukov! - Fixed CSS formatting of long block comments between comma-separated property values:

     .foo {
       box-shadow:
    -    1000px /* long long long long long long long long long long long long comment */ 1000px /* long long long long long long long long long comment */ 2px color(srgb 0.555555555 0.555555555 0.555555555),
    +    1000px
    +      /* long long long long long long long long long long long long comment */
    +      1000px /* long long long long long long long long long comment */ 2px
    +      color(srgb 0.555555555 0.555555555 0.555555555),
         1px 1px black;
     }
    
  • #​11127 da5c1a5 Thanks @​dyc3! - The HTML formatter now picks the quote character for an attribute by counting the quotes in the value rather than looking only for a double quote. &apos; and &quot; count as the characters they stand for, and only the character that ends up as the delimiter stays escaped:

    - <div title='123 &apos;&quot; 456'></div>
    + <div title="123 '&quot; 456"></div>
    

    Entities that are not quotes, such as &amp; or &[#&#8203;39](https://github.com/biomejs/biome/issues/39);, are left exactly as written.

  • #​11193 77035bb Thanks @​dyc3! - Fixed the HTML formatter collapsing the blank line between an element and the text that follows it. A blank line before text is now kept, the way one before another element already was:

      <div>foo</div>
    -
      text
    
  • #​11106 ad80f57 Thanks @​dyc3! - The HTML formatter now writes the HTML5 doctype in lowercase, matching Prettier:

    - <!DOCTYPE html>
    + <!doctype html>
    

    This only applies to a plain .html file whose doctype stands alone. A doctype that names a DTD keeps the case it was written with, since the rest of the declaration is not lowercased either:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    

    A .vue, .svelte, or .astro file keeps whatever the author wrote.

  • #​11188 60679db Thanks @​dyc3! - Fixed the HTML formatter printing a comment twice when it ended the line of the last element in a document:

    - text<!-- a --><!-- a -->
    + text<!-- a -->
    
  • #​11077 4dcd0d9 Thanks @​dyc3! - Fixed a bug where the HTML formatter collapsed the whitespace inside <textarea>, <xmp> and <plaintext>, changing what the page renders.

    - <textarea>
    -  line one
    - line two </textarea>
    + <textarea>line one line two</textarea>
    

    Biome now prints the content of these elements exactly as it appears in the source, matching the existing behavior for <pre>.

  • #​11194 abfbb11 Thanks @​dyc3! - Fixed the HTML formatter refusing to format a Svelte file containing an array pattern that skips a position:

    {#each animals as [, value]}
    	<p>{value}</p>
    {/each}
    
  • #​10094 e007143 Thanks @​THEjacob1000! - Fixed useSortedClasses to correctly detect unsorted classes in static member expression tagged templates (e.g. tw.div\...``). Previously, these were silently skipped due to surrounding whitespace trivia not being stripped from the tag name.

  • #​11078 10da30e Thanks @​dyc3! - Fixed Vue single-file components failing to parse when they contain a custom block such as <i18n> or <docs>, or a <template> written in another language. Their content is no longer read as HTML, so a block may hold whatever its own tooling expects:

    <docs>
    This block is prose, and it may mention a `<my-component>` without closing it.
    </docs>
    
    <template lang="pug">
      .test
        #foo
    </template>
    

    Previously both blocks produced a parse error and the whole file was left unformatted. Biome now prints their content unchanged while still formatting the opening tag.

  • #​11231 4afd901 Thanks @​ematipico! - Improved the performance of the following lint rules:

  • #​11134 2fa0a62 Thanks @​yanthomasdev! - Clarified the warning emitted when using the experimental json and json-pretty reporters.

  • #​11198 ed88b13 Thanks @​saberoueslati! - Fixed #​11171: variables referenced only inside a Svelte attachment ({@attach ...}) are no longer reported as unused by noUnusedVariables and noUnusedImports.

  • #​11155 6ee17ea Thanks @​dyc3! - Improved performance when printing diagnostics to the console.

  • #​11160 217f8ad Thanks @​dyc3! - Improved the performance of noFloatingPromises by skipping type inference for assignment statements, which are always considered handled.

  • #​11159 26c23d9 Thanks @​saberoueslati! - Fixed #​11144: noFloatingPromises no longer reports already-awaited optional Promise values.

  • #​11138 8c2c6bd Thanks @​ematipico! - Fixed #​11121: noUnnecessaryConditions no longer reports conditions based on an inapplicable function overload.

    For example, the condition in the following code is no longer reported because query({}) selects the overload that returns boolean:

    declare function query(options: { initial: string }): { isPending: false };
    declare function query(options: { initial?: string }): { isPending: boolean };
    
    const { isPending } = query({});
    isPending || fallback;
    
  • #​11152 c4fc6a9 Thanks @​dyc3! - Improved the performance of collecting rule timings with --profile-rules in heavily multithreaded environments.

  • #​11128 4d3ff76 Thanks @​ematipico! - Fixed #​7635: noDeprecatedImports now detects deprecated ambient declarations that are exported separately.

  • #​11117 01f7ef5 Thanks @​subotac! - Fixed #​11014: noDelete no longer reports process.env["FOO"] style property deletions.

  • #​11168 9847e68 Thanks @​saberoueslati! - Added the nursery rule noNonScalableViewport, which reports viewport metadata that disables user scaling with user-scalable=no.

    For example:

    <meta name="viewport" content="width=device-width, user-scalable=no" />
    
  • #​11154 a1d6b1f Thanks @​dyc3! - Improved the performance of noImportCycles by skipping graph traversals for imports that cannot be part of a cycle.

  • #​11175 d96d6dd Thanks @​ematipico! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the syntax descriptor of @property rules.

v2.5.6

Compare Source

Patch Changes
  • #​11035 0e4b03b Thanks @​ematipico! - Fixed a performance regression in noMisusedPromises that caused type inference to run repeatedly while linting a file.

  • #​11043 22ec076 Thanks @​denbezrukov! - Fixed CSS formatting for multiline function arguments preceded by comments:

     .example {
       value: outer(
         1,
         /* comment */
         nested(
    -      first,
    -      second
    -    )
    +        first,
    +        second
    +      )
       );
     }
    
  • #​11007 c9acb25 Thanks @​BTF-Kabir-2020! - Fixed #​9195: useHookAtTopLevel no longer reports hooks in named forwardRef components that receive a ref parameter.

  • #​10152 50a9bd8 Thanks @​Zelys-DFKH! - Fixed #​10131: Biome now correctly parses curried arrow functions in ternary consequents when the inner arrow's parameters use a destructuring pattern, e.g. cond ? (x) => ({ a, b }) => body : alt.

  • #​11105 8ffe2b9 Thanks @​dadavidtseng! - Fixed #​11092: The noUselessTernary quick fix now preserves operator spacing when simplifying or inverting boolean ternary expressions.

  • #​10533 5809875 Thanks @​Mokto! - Fixed #​10515: biome check --write was not idempotent on Svelte files — multi-line template literals in <script> blocks and block comments in <style> blocks gained an extra indent level on every run.

  • #​11040 0abb620 Thanks @​Mokto! - Fixed an issue where the HTML formatter would duplicate a comment placed directly before a Svelte {@const ...} or {@debug ...} block. The duplication compounded on every subsequent --write, causing the file to grow exponentially.

  • #​10858 6d18204 Thanks @​ruidosujeira! - Fixed #​10839: Svelte {#each} array destructuring no longer includes spaces inside square brackets, and multiline bind function expressions now indent their getter, setter, and function body correctly.

  • #​11009 2c36626 Thanks @​ematipico! - Improved the accuracy of type-aware lint rules by resolving more inferred types. For example, noFloatingPromises now detects floating Promises returned by aliased callbacks and arrays of Promises created by async mapping callbacks.

    The following statements are now reported:

    type AsyncCallback = () => Promise<void>;
    declare const callback: AsyncCallback;
    callback();
    
    [1, 2, 3].map(async (value) => value);
    
  • #​10973 9cb044c Thanks @​ematipico! - Fixed false positives in noMisleadingReturnType when generic-constraint, normalization, substitution, or structural return-type comparison cannot complete. The rule now suppresses diagnostics rather than suggesting a return type derived from partial information. For example, this unresolved return type is no longer reported:

    function unresolvedReturnType(): MissingType {
      return "value" as const;
    }
    
  • #​11071 15047a2 Thanks @​dyc3! - The HTML parser now accepts mixed-case doctype declarations.

  • #​11030 cc90e65 Thanks @​marschattha! - The rdjson reporter now populates the severity field of each diagnostic (ERROR, WARNING, or INFO), so tools consuming Reviewdog Diagnostic Format output no longer need to assume a default severity.

  • #​11009 2c36626 Thanks @​ematipico! - Fixed a performance regression in type-aware JavaScript lint rules by inferring only requested types and memoizing export resolution.

  • #​11056 903b177 Thanks @​dyc3! - Added support for Svelte declaration tags using let and const. Biome can now parse, format, and lint bindings declared in these tags.

  • #​11045 89c27c6 Thanks @​ematipico! - Improved the performance of Biome formatter up to ~7% across the board.

  • #​9806 781d68d Thanks @​dyc3! - Added the nursery rule noJsRestrictedProperties, which ports ESLint's no-restricted-properties rule. Biome now flags restricted member access and object destructuring, and biome migrate eslint preserves the rule's options.

v2.5.5

Compare Source

Patch Changes
  • #​10972 ab8c21b Thanks @​ematipico! - Fixed useExhaustiveSwitchCases for unions of bigint literals. The rule now reports missing bigint cases and compares bigint literals by value, including binary, octal, hexadecimal, and separator-containing spellings. For example, this switch now reports the missing 2n case:

    declare const value: 1n | 2n;
    switch (value) {
      case 1n:
        break;
    }
    
  • #​10972 ab8c21b Thanks @​ematipico! - Fixed false positives in noBaseToString and useNullishCoalescing when member, stringification, or nullish inference cannot complete. These rules now suppress diagnostics instead of reporting from partial type information. For example, neither expression is reported when a recursive type cannot be fully resolved:

    type Recursive = Recursive;
    declare const value: Recursive;
    
    String(value);
    value || "fallback";
    
  • #​10977 0bf7486 Thanks @​ematipico! - Fixed #​10922: the action useSortedAttributes no longer triggers for HTML instructions.

  • #​10957 cf263c4 Thanks @​dyc3! - Fixed noThenProperty failing to detect Object.fromEntries, Object.defineProperty, and Reflect.defineProperty calls with comments between their tokens.

  • #​10983 edc0ed7 Thanks @​ayaangazali! - Fixed #​10980: useAriaPropsSupportedByRole no longer reports false positives when the attribute that determines an element's implicit ARIA role is written as a shorthand attribute, such as <a {href} aria-label="..."> in Astro and Svelte files.

    Shorthand attributes are now taken into account when computing the implicit role, so the anchor above correctly resolves to the link role instead of generic.

  • #​10889 89526e3 Thanks @​denbezrukov! - Fixed CSS formatter casing for syntax-owned names while preserving author-defined names, including scoped keyframes and container scroll-state queries.

    - A:HOVER { COLOR: INITIAL; }
    + A:hover { color: initial; }
    - @KEYFRAMES :GLOBAL KeepFrames { FROM { COLOR: RED; } }
    + @keyframes :GLOBAL KeepFrames { from { color: RED; } }
    - @CONTAINER scroll-state((SCROLLED: TOP) AND (STUCK)) { A:HOVER { COLOR: RED; } }
    + @container scroll-state((SCROLLED: TOP) AND (STUCK)) { A:hover { color: RED; } }
    
  • #​10964 794ccd0 Thanks @​denbezrukov! - Fixed CSS formatting for comments between declaration values and !important.

    -a { color: /* before */ /* after */ red !important; }
    +a { color: /* before */ red /* after */ !important; }
    
  • #​10993 b7a9694 Thanks @​denbezrukov! - Fixed the CSS formatter to preserve comments on the correct side of selector combinators and before declaration blocks.

    -.before > /* comment */ .after {}
    +.before /* comment */ > .after {}
    

    It now also keeps selectors with escaped newlines in attribute values inline when they fit.

    -div
    -  span[foo="bar\
    +div span[foo="bar\
     value"] {}
    
  • #​10978 8ebafe1 Thanks @​ematipico! - Fixed #​10870: noUnresolvedImports no longer reports false positives such as import type { NextRequest } from "next/server".

  • #​10901 68c10e6 Thanks @​Socialpranker! - Fixed #​10622: the HTML/Vue parser no longer panics on the argument-less v-bind shorthand (:="props").

    This syntax is valid Vue and equivalent to v-bind="props", so the parser now accepts it (along with the longhand v-bind:="props") instead of crashing while building a diagnostic for a missing argument.

  • #​10936 7df46f5 Thanks @​ematipico! - Improved generic tuple inference for useIncludes. The rule now recognizes specialised tuple element types returned through generic aliases.

  • #​10941 f787725 Thanks @​siketyan! - Fixed #10855: Biome now supports parsing and formatting CSS custom media queries declared with @custom-media.

  • #​10969 72d309b Thanks @​ematipico! - Fixed an issue where Biome logs became too verbose, dumping information not relevant to user's operations.

  • e62f6b6 Thanks @​ematipico! - Fixed #​10963: Biome no longer panics when a type-aware rule such as noFloatingPromises checks a call to a function with multiple call signatures imported from another module.

  • #​10931 899c60d Thanks @​ematipico! - Fixed check --write command. Now the command reports code frame of the formatted code, if the formatter is enabled.

  • #​10904 ceee4f4 Thanks @​qzwxsaedc! - Fixed #​10892: noUnnecessaryConditions no longer reports a false positive when checking a member of a discriminated union that is accessed through a default type-only namespace import. The following code is no longer flagged:

    import type Types from "./types";
    
    declare function parse(): Types.Result<string>;
    const result = parse();
    if (!result.success) {
    }
    
  • #​10962 f0a67f2 Thanks @​ematipico! - Biome no longer removes embedded styles and scripts in HTML files.

  • #​11000 5039a1e Thanks @​ematipico! - Fixed a bug where closing one editor stopped a shared Biome daemon used by other editors. LSP proxy processes now exit when either the editor or daemon disconnects.

  • #​10957 cf263c4 Thanks @​dyc3! - Improved the performance of the noThenProperty lint rule by about 50%.

  • #​10992 4bf9b21 Thanks @​ematipico! - Fixed noMisusedPromises: The rule now reports Promise-returning callbacks where a synchronous callback is expected when calls use tuple spreads or tuple rest parameters, including generic and deeply nested tuples, and when constructor signatures come from interface or object types. Recursive or excessively nested tuple spreads use a conservative fallback so analysis terminates.

    For example, the following callback is now reported.

    declare function consume(...args: [number, () => void]): void;
    const prefix: [number] = [1];
    
    consume(...prefix, async () => {});
    
  • #​10915 b3b12b3 Thanks @​Functionhx! - Added the rule noNegationInEqualityCheck. The rule flags negated expressions on the left side of strict equality checks like !foo === bar — due to operator precedence this evaluates as (!foo) === bar which is almost always a mistake for foo !== bar.

    The rule provides an unsafe fix that flips the operator.

    // Invalid
    !foo === bar;
    !foo !== bar;
    
    // Valid
    foo !== bar;
    foo === bar;
    
  • #​10970 bd1038b Thanks @​ematipico! - Improved overload selection for noMisusedPromises. Biome now handles overloaded calls, overloaded constructors, rest parameters, union arguments, and generic constraints without selecting an incompatible signature. For example, noMisusedPromises now reports the async callback passed to the synchronous overload:

    declare function consume(kind: "async", callback: () => Promise<void>): void;
    declare function consume(kind: "sync", callback: () => void): void;
    consume("sync", async () => {});
    
  • #​10933 48a4abb Thanks @​ematipico! - Fixed useArrayFind to recognize bigint zero indexes.

  • #​10931 899c60d Thanks @​ematipico! - Fixed an orchestration issue that could lead to deadlocks when type-aware rules are enabled.

  • #​10969 72d309b Thanks @​ematipico! - Hardened the Biome Language Server by improving its synchronisation logic.

  • #​10972 ab8c21b Thanks @​ematipico! - Fixed false positives in noMisusedPromises and useAwaitThenable when Promise or thenable inference cannot complete. These rules now suppress diagnostics instead of treating incomplete type information as a definite result. For example, useAwaitThenable no longer reports await value when the value's thenability is unknown:

    declare const value: unknown;
    
    async function consume() {
      await value;
    }
    

v2.5.4

Compare Source

Patch Changes
  • #​10665 55ff995 Thanks @​dyc3! - Improved the performance of the HTML parser slightly in our synthetic benchmarks.

  • #​10894 f4fb10e Thanks @​ematipico! - Fixed #​6392: On-type formatting no longer moves comments before an if statement into its body.

  • #​10939 f2799db Thanks @​Netail! - Fixed #​10930: noLabelWithoutControl now correctly detects text interpolation in Astro, Svelte & Vue as valid accessible content.

  • #​10945 ae15d98 Thanks @​Netail! - Fixed #​10942: Svelte directives don't throw an accidental debug log anymore.

  • #​10842 5e1abfe Thanks @​JamBalaya56562! - Fixed #​9196: biome check --write --unsafe no longer hangs forever when applying the noCommentText code fix.

    The rule's fix now wraps the comment in a real JSX expression container ({/* comment */}) instead of re-inserting the braces as plain JSX text, so the fixed code is no longer reported again by the same rule.

  • #​10891 ecca79e Thanks @​ematipico! - Fixed #10885: prevented a module-inference regression introduced by a housekeeping change.

  • #​10886 60c8043 Thanks @​dyc3! - Fixed #​10727: Biome now breaks the arguments of curried test.each, it.each, describe.each, and test.for calls when they exceed the configured line width.

    - test.each([[1, 2]])("a description that is long enough to push the hugged opening line beyond the print width", (a, b) => {
    -   expect(a).toBe(b);
    - });
    + test.each([[1, 2]])(
    +   "a description that is long enough to push the hugged opening line beyond the print width",
    +   (a, b) => {
    +     expect(a).toBe(b);
    +   },
    + );
    
  • #​10895 01a85f0 Thanks @​ematipico! - Biome will now remove stale Unix daemon sockets from older Biome versions when starting a newer daemon.

v2.5.3

Compare Source

Patch Changes
  • #​10815 86613d5 Thanks @​WaterWhisperer! - Fixed a parser panic reported in #​10708: Biome now recovers when unsupported CSS Modules @value rules or scoped @keyframes names end at EOF.

  • #​10534 da9b403 Thanks @​Mokto! - Fixed noUnusedVariables false positives in Svelte files: Svelte store subscriptions ($store references in templates now keep the underlying store binding from being flagged), and $bindable() props that are only written to in the script block (write-only is intentional for bindable props) are no longer reported as unused.

  • #​10827 098ba41 Thanks @​Aqu1bp! - Fixed #​10698: The noUnsafeOptionalChaining rule now reports unsafe optional chains wrapped in TypeScript as, satisfies, type assertion, and instantiation expressions, such as new (value?.constructor as Constructor)().

  • #​10773 3c6513d Thanks @​otkrickey! - Fixed #​10772: useVueValidVOn no longer reports a missing handler for v-on directives using a verb modifier (.stop / .prevent) without an expression, e.g. <div @click.stop></div>. The rule also accepts the arg-less object syntax <div v-on="$listeners"></div> instead of reporting a missing event name.

  • #​10721 d83c66b Thanks @​minseong0324! - Improved type-aware lint rule inference for built-in globals and indexed function calls. Biome now resolves Error(...), new Error(...), optional Error#stack, and calls through indexed function values such as handlers[0]() more accurately.

  • #​10865 6450276 Thanks @​ematipico! - Fixed #​10845. Biome Language Server no longer goes in deadlock when the scanner is enabled.

  • #​10853 93d8e53 Thanks @​Netail! - Fixed #​10840: Astro shorthand attribute syntax is now correctly being parsed from embedded nodes.

  • #​10820 bba3092 Thanks @​JamBalaya56562! - Fixed #​10619: noProcessEnv now also reports computed (bracket) member access. Previously only dot access was checked, so process["env"] and env["NODE_ENV"] (where env is imported from node:process) were missed. Both static and computed accesses are now reported.

  • #​10835 3447b2f Thanks @​dyc3! - Fixed #​10824: useDomQuerySelector now supports an ignore option for receiver identifiers that should not be reported.

  • #​10875 b12e486 Thanks @​dyc3! - Fixed #​10795: --profile-rules now reports timings for each plugin separately as plugin/<pluginName>, matching the naming used by plugin suppressions, instead of aggregating all plugins under a single plugin/plugin entry.

  • #​10877 d6bc447 Thanks @​ematipico! - Fixed biome-zed#164: Biome no longer inserts stray whitespace when format-on-type runs after closing delimiters such as ), ], and }.

  • #​10867 a21463e Thanks @​dyc3! - Fixed #​10864: Biome no longer crashes when checking or linting HTML files with unquoted attribute values such as <textarea rows=4></textarea>.

cznic/sqlite (modernc.org/sqlite)

v1.60.1

Compare Source

v1.60.0

Compare Source

haydenbleasel/ultracite (ultracite)

v7.12.2

Compare Source

Patch Changes
  • 0f192a7: ultracite init no longer wipes an existing Biome config it can't read. Previously a biome.json or biome.jsonc with a syntax error, or a nested monorepo config with "extends": "//", was treated as empty and replaced with just the Ultracite extends, losing every other setting. Now:

    • A config with a syntax error is left unchanged, with a warning asking you to fix it and re-run init.
    • A nested config that extends the root config ("extends": "//") is left unchanged, since the Ultracite presets belong in the root config.
    • A string extends is turned into a list that also includes the Ultracite presets.
    • Updates edit the file in place, so comments and formatting in biome.jsonc are preserved.

    ultracite doctor and the check/fix resolution check now follow a nested config that extends "//" to the root config, instead of warning that the nested config doesn't extend ultracite/biome/core.

  • c68ba48: ultracite check and ultracite fix handle their arguments and missing tools more reliably:

    • check now treats explicit files the way fix does. Oxlint only gets files it can lint, Prettier runs with --ignore-unknown, and oxfmt with --no-error-on-unmatched-pattern. Before, ultracite check README.md or ultracite check Dockerfile src/index.ts failed even though nothing was wrong.
    • Linter flags that take a value keep it, even when the value looks like a file: --tsconfig tsconfig.json, -c .oxlintrc.json, --config-path biome.json, --only lint/suspicious/noDebugger, --since origin/main and similar. Before, the value was treated as a lint target, so ultracite fix --tsconfig tsconfig.json skipped Oxlint entirely and only formatted tsconfig.json. Ultracite's own --claude, --codex, --hook and --unsafe never take a value, so the next argument is always a target.
    • ultracite fix --unsafe with the ESLint toolchain no longer fails with ESLint's "Invalid option '--unsafe'". ESLint has no unsafe fixes, so the flag is dropped with a warning.
    • A linter that isn't installed is reported with a plain message instead of a stack trace. The other tools still run first. Stylelint is optional in the ESLint toolchain, as ultracite doctor already said, so a project without it now skips CSS linting with a warning instead of failing. "No linter configuration found" is also printed without a stack trace.
    • Linters installed in the project's node_modules/.bin are found even when Ultracite isn't run through a package manager script, npx or bunx, for example ./node_modules/.bin/ultracite check.
  • f61f393: ultracite init now looks for existing ESLint, Prettier and Stylelint configs in the same order the tools do, so when a project has more than one, init updates the one the tool actually loads. For example, Prettier reads .prettierrc.json before prettier.config.mjs, and ESLint reads eslint.config.js before eslint.config.mjs. Before, init could update a config the tool ignored and leave the active one in place. Stylelint's .stylelintrc.ts and stylelint.config.ts are now recognised too.

  • 242cd2a: ultracite init now updates an existing .vscode/settings.json or .zed/settings.json in place, so your comments and formatting are kept. Before, the file was re-serialised as plain JSON, which stripped every comment. A settings file with a syntax error is now left unchanged with a warning. Before, it was rewritten with whatever part the parser could recover, which dropped the rest.

    For the ESLint toolchain, init now also installs the Prettier VS Code extension (esbenp.prettier-vscode), since the settings it writes make Prettier the default formatter. Before, only the ESLint extension was installed, so format-on-save did nothing until you added Prettier yourself.

  • c273393: ultracite init now checks every flag value before it changes anything in the project. An unknown value for --linter, --pm, --frameworks, --editors, --agents, --hooks, --integrations or --js-plugins stops init with a message listing the valid values. Previously a misspelled --linter (for example --linter Biome) deleted every existing Biome, ESLint, Prettier, Stylelint, Oxlint and oxfmt config file and then crashed.

    When --linter is not passed and init runs without prompts (because of --quiet, CI, or flags such as --agents or --pm), it now keeps the linter the project is already set up with and only falls back to Oxlint when there is none. Running ultracite init --agents universal on a Biome project no longer migrates it to Oxlint. The interactive linter prompt also preselects the detected linter.

  • 3cb2e71: Clearer wording in the CLI:

    • ultracite init --help now lists the valid values for --pm, --linter, --frameworks, --hooks and --integrations, and explains what --type-aware does for Biome and for Oxlint.
    • The agent rules file says "Oxlint + Oxfmt will catch most mechanical issues automatically" instead of "Oxlint + Oxfmt's linter will catch…".
    • init and upgrade say "Using pnpm (detected from the project)" instead of "Detected lockfile", since the package manager can also come from packageManager.
    • ultracite doctor spells "unrecognized" consistently, formats commands as code, and describes warnings as "Some checks have warnings" instead of "optional improvements".
  • 6ae8be8: The ESLint nestjs preset imports @darraghor/eslint-plugin-nestjs-typed, but ultracite init --linter eslint --frameworks nestjs never installed it, so ESLint failed to load the config with "Cannot find package". init now installs the plugin with the preset, and ultracite upgrade installs the plugins of every framework preset your eslint.config.* imports, so existing NestJS projects pick it up on their next upgrade.

  • a8e83bb: ultracite init now migrates an existing .oxlintrc.json, .oxfmtrc.json or .oxfmtrc.jsonc when it sets up Oxlint. Oxlint and oxfmt refuse to load any config when a JSON config sits next to oxlint.config.ts or oxfmt.config.ts, and init used to write the TS configs beside the JSON ones, so ultracite check and ultracite fix stopped working. Init now moves the JSON config's settings into the TS config and deletes the JSON file:

    • rules, overrides, env, plugins and other options become properties of the generated config.
    • ignorePatterns, settings and jsPlugins are added to the ones Ultracite generates instead of replacing them.
    • Ultracite extends entries become presets. Other extends paths can't be referenced from a TS config, so init names them in a warning.

    A JSON config that doesn't parse is left in place, and neither file is written.

    Re-running ultracite init also keeps what you added to oxlint.config.ts and oxfmt.config.ts: custom rules, overrides, ignorePatterns, settings and other properties, extra extends entries, your own imports and statements, and comments are carried over while the Ultracite parts are regenerated. Before, both files were regenerated from scratch. A config that doesn't parse is now left unchanged with a warning instead of being overwritten.

    ultracite doctor now fails when a JSON config and a TS config for Oxlint or oxfmt sit side by side, and suggests running init to migrate a lone .oxfmtrc.json.

  • 981ef2f: ultracite init --linter oxlint no longer adds "type": "module" to package.json. That field changes how Node loads every .js file in the package, so CommonJS files such as a next.config.js, postcss.config.js or jest.config.js using module.exports stopped working after init.

    Instead, init writes the Oxlint and oxfmt configs as oxlint.config.mts and oxfmt.config.mts when the package isn't an ES module package (no "type" or "type": "commonjs"). A .mts file always loads as an ES module, with no MODULE_TYPELESS_PACKAGE_JSON warning on every run, and it works under "type": "commonjs". ES module packages ("type": "module") still get oxlint.config.ts and oxfmt.config.ts.

    Re-running init updates an existing config under the name it already has. The one exception is a .ts config in a "type": "commonjs" package, which Node can't load: init renames it to .mts and says so. ultracite doctor, linter detection and the stale-config cleanup all recognise the .mts names. doctor fails a .ts config in a CommonJS package, and fails when a .ts and an .mts config sit side by side.

    Requires oxfmt >= 0.59.0, the first release that finds oxfmt.config.mts on its own.

  • 9a9beb0: ultracite init is gentler with package.json:

    • It keeps the file's key order, indentation and line endings. Before, every write moved devDependencies to the top and pushed keys like private, main and exports to the end.
    • It no longer overwrites a check or fix script the project already has (for example "check": "tsc --noEmit"). It prints a warning instead, and it only adds the scripts that are missing. Existing scripts that already run Ultracite with extra flags are left as they are.
    • When switching linters, it only removes the previous linter's packages from devDependencies. Packages in dependencies and peerDependencies stay, such as prettier used at runtime or eslint as the peer of a published plugin.
    • With --skip-install, the final message now says the dependencies were added to package.json instead of claiming they were installed.
  • c3027a5: Re-running ultracite init no longer silently discards changes to an ESLint, Prettier or Stylelint config that builds on Ultracite's:

    • eslint.config.*: the framework presets it already spreads are kept alongside any newly selected ones, together with your own config objects, imports and a defineConfig(...) wrapper. Before, the file was regenerated from the selected frameworks only, dropping earlier presets and every custom rule.
    • prettier.config.*: your options, imports and extra plugins are kept. Framework plugins are added, and prettier-plugin-tailwindcss stays last.
    • Stylelint: a config that already uses ultracite/stylelint, including one in package.json, is left as it is.

    A config that doesn't use Ultracite's presets is still replaced, but init now prints a warning naming the file (or the package.json key) it replaced. A config that doesn't parse is left unchanged with a warning. With the ESLint toolchain, a "prettier" or "stylelint" key in package.json is now handled by these updates (and reported when replaced) instead of being deleted silently during migration.

  • 44d6997: ultracite init no longer creates directories for agent rule files or agent hook configs (such as .claude/ or .cursor/) before checking that the path stays inside the project. When one of those directories was a symlink to somewhere outside the project, init created the missing directories there before it refused to write the file.

  • 33a1ccd: ultracite init --integrations husky --skip-install no longer replaces an existing prepare script in package.json. It adds husky to the script, as the installing path already did (for example "prepare": "svelte-kit sync && husky"). The Lefthook setup messages now name the config file init actually updates or creates, such as .lefthook.yaml, instead of always saying lefthook.yml.

  • 923667b: ultracite init no longer overrides a tsconfig that turns strictNullChecks off. It leaves an explicit "strictNullChecks": false, whether set in the file or in a config it extends, as it is and prints a warning. It also follows extends, whether a relative path or a package such as @tsconfig/strictest, so a tsconfig that already inherits strict or strictNullChecks is no longer given a redundant "strictNullChecks": true.

  • 199974c: ultracite init and ultracite upgrade now work in Yarn 2+ monorepos. The root install used to pass Yarn 1's -W flag, which Yarn 2+ rejects with "Unsupported option name", whenever the Yarn version wasn't named in package.json's packageManager field. That happened with --pm yarn, with lockfile-only detection, and always in the second half of upgrade, which re-ran the new CLI with a bare --pm yarn. Ultracite now tells Yarn 2+ apart from Yarn 1 by .yarnrc.yml or the lockfile format. upgrade only forwards --pm to the newly installed CLI when you passed it.

    ultracite doctor (and the check at the end of upgrade) no longer fails in Yarn Plug'n'Play projects just because it can't find Ultracite or the tools in node_modules. It warns that it can't verify them there instead.

  • c33158d: Agent hooks set up by ultracite init --hooks work in more places and no longer double up.

    • GitHub Copilot: .github/hooks/ultracite.json is now written in the format the Copilot CLI and Copilot cloud agent read: "version": 1 and a camelCase postToolUse event. VS Code reads this format too. The previous file, with a PascalCase PostToolUse and no version, was only picked up by VS Code. Re-running init moves an existing Ultracite hook to the new format instead of keeping both.
    • fix --hook with Copilot: the file path is now read from Copilot payloads: toolArgs.path from the Copilot CLI (including when toolArgs is a JSON string), tool_input.filePath from VS Code's edit tools, every file of a multi_replace_string_in_file edit, and the file headers of an apply_patch. So only the edited files are fixed, not the whole project. These hosts run the hook after every tool, so tools that edit nothing (such as read_file, view or bash) now skip the fix instead of fixing the whole project.
    • Re-running init no longer adds a second hook next to one generated by Ultracite 7.8.2 or earlier: pnpm fix …, bun fix …, yarn fix …, or npm run fix --skip=…. That older hook is updated in place, so it stops running a whole-project fix after every edit.
    • A hook is now added even when the settings file mentions ultracite somewhere else, such as a Claude Code permission rule like Bash(npx ultracite check). Only existing hook commands are checked.
    • fix --hook now fixes a file at the project root whose name starts with .., instead of treating it as outside the project.
    • Zed: the includePackageJsonAutoImports preference is now set for vtsls, Zed's default TypeScript and JavaScript language server (lsp.vtsls.settings), for both TypeScript and JavaScript. It was previously set under typescript-language-server, which Zed doesn't use by default.
  • dc5e18e: Re-running ultracite init now updates the Ultracite rules in AGENTS.md, .claude/CLAUDE.md, GEMINI.md and the other shared rule files in place, instead of appending another full copy.

    • Previously a copy was appended whenever the linter, the package manager or the rules text changed. For example, switching from Biome to Oxlint left instructions for both engines side by side. Duplicate copies written by earlier versions are now removed, and your own content before and after the block is kept.
    • Files with CRLF line endings keep them, and are no longer duplicated on every run.
    • The commands in the rules now run the project's installed CLI (npx ultracite fix, yarn ultracite fix, pnpm exec ultracite fix, bunx ultracite fix) instead of a dlx runner. For Deno they read deno run -A npm:ultracite fix; previously the broken deno run -A npm: ultracite fix was written.
    • Firebender: rules are now written to .firebender/rules/ultracite.mdc with alwaysApply: true, where Firebender reads project rules. They were previously written as Markdown into firebender.json, which made that file invalid JSON and overwrote an existing Firebender config. A firebender.json that still holds only those Markdown rules is reset to {}.
  • 2ad7704: Fixes for ultracite fix --claude and ultracite fix --codex:

    • On a terminal, the ✓/✗ result for every issue is now kept once a file is done. Previously a file with more issues than the terminal had rows kept only the last screenful of results.
    • In CI logs and other piped output, lint messages are no longer cut off at 80 columns.
    • The prompt is now sent to the agent CLI on stdin (claude -p, codex exec -) instead of as a command-line argument. On Windows, an npm-installed CLI runs through a .cmd shim, which can cut an argument off at its first newline, so the agent received only the prompt's first line and never saw the file or its issues.
    • --codex now passes --skip-git-repo-check, so it also works in a project that isn't a git repository. Previously codex exec refused to run there and every file failed.
  • 0b0775e: The Husky pre-commit hook written by ultracite init --integrations husky is more robust.

    • The hook now runs the project's installed tools (npx, yarn, pnpm exec, bunx) instead of yarn dlx / pnpm dlx. yarn dlx does not exist in Yarn 1, so every commit failed with "Ultracite found issues that could not be auto-fixed", and pnpm dlx downloaded the latest release instead of the version the project pins. Husky itself is also initialised with the installed binary.
    • Installing Husky now chains husky onto an existing prepare script (for example SvelteKit's svelte-kit sync || echo '') instead of replacing it. Choosing Husky and lefthook together no longer leaves only one of them in prepare.
    • When nothing is staged, the hook no longer exits early, so commands you keep after the Ultracite section still run.
    • Re-running init replaces the Ultracite section of a hook saved with CRLF line endings instead of appending a second one. It also no longer drops the last line of a hook that only mentions "# ultracite" in a comment. Commands after a lint-staged section written by an older version are kept.
  • 3862221: ultracite init --integrations lint-staged no longer damages or shadows an existing lint-staged config.

    • An extension-less .lintstagedrc written in YAML (which is how lint-staged reads it) is now edited as YAML. Previously it was overwritten with a JSON file holding only the Ultracite task, deleting the user's own tasks, and single-quoted YAML was silently skipped.
    • YAML configs are edited through the yaml Document API, so comments and the rest of the file are kept.
    • TypeScript configs (.lintstagedrc.ts, .mts, .cts and lint-staged.config.ts, .mts, .cts) and the lint-staged key of package.yaml are now recognised. Previously init created a .lintstagedrc.json next to them, and because lint-staged uses only the first config in a directory, the user's config silently stopped running.
    • When a config can't be edited automatically (a function-based entry, a CommonJS module that can't be loaded, a syntax error), init now leaves it untouched and prints the command to add, instead of writing a second config file that would replace it.
    • When both exist, the dedicated config file is updated rather than the package.json key, matching the file lint-staged actually uses.
    • A single command already mapped to the same glob is kept alongside ultracite fix instead of being replaced.
    • The task now runs the project's installed Ultracite (npx, yarn, pnpm exec, bunx) instead of yarn dlx / pnpm dlx, which don't exist in Yarn 1 or download the latest release instead of the pinned one. Re-running init upgrades a dlx command written by an earlier version.
  • bffb8dd: Corrected the bundled Ultracite agent skill (skills/ultracite/SKILL.md):

    • It said Oxlint has github and sonarjs presets that init includes by default. Neither exists. The GitHub, SonarJS and React Doctor rules live in the ultracite/oxlint/js-plugins preset (plus next/js-plugins and tanstack/js-plugins), next to the anti-slop and shadcn presets, and all of them are opt-in.
    • The --js-plugins init flag is now documented.
    • The skill now tells agents to run the project's installed CLI (npx, pnpm exec, yarn, bunx) rather than pnpx or yarn dlx.
  • da2934a: Installing the Ultracite skill from ultracite init now works when init runs in a normal terminal.

    Init runs skills add haydenbleasel/ultracite without a terminal attached. When the skills CLI needed to ask which agents to install to, or whether to install into the project or globally, it could not show the prompt:

    • In some cases it cancelled the prompt and exited successfully with nothing installed, so init said "Ultracite skill installed." when the skill wasn't there.
    • In others it failed, so the install never happened.

    Init now passes --yes and names the agents to install for, so skills installs without asking. The skill always goes to the shared .agents/skills directory, which Codex, Cursor, GitHub Copilot, Gemini CLI, Amp, Cline, OpenCode and other agents read. It also goes to the skills directory of any agent whose project folder exists (for example .claude, .windsurf, .codebuddy or .roo, which init creates when you choose those agents).

    Init names the agents because otherwise, in a project where skills detects no agent, --yes would install for every agent it knows. That also created a .claude/skills link and a second copy in a top-level agent/ directory (for the Eve framework). The "install it later" hint still shows the interactive skills add haydenbleasel/ultracite command.

  • 4941883: ultracite init now edits .pre-commit-config.yaml and lefthook configs through the yaml Document API instead of splicing text, so the result is always valid YAML and comments are kept.

    • pre-commit: a repos: list written flush with its key (- repo:, the style pre-commit sample-config generates) or with four-space indentation no longer turns into invalid YAML that breaks every commit. The file's sequence style is kept.
    • lefthook: a four-space indented pre-commit: block, a compact jobs: list, or a column-0 comment inside the block no longer produce invalid YAML or a duplicate jobs: key. A hook that uses commands: gets a jobs: list next to it.
    • lefthook: init now finds an existing .lefthook.yml, lefthook.yaml, .config/lefthook.yml (and the other names lefthook reads) and edits it. Previously it created lefthook.yml, which lefthook picks first, so the user's own config silently stopped running. A JSON or TOML config is left alone with instructions.
    • lefthook: the job's globs are now *.js, *.ts, and so on. With lefthook's default matcher, the previous **/*.js form skipped root-level files such as package.json or index.ts. Projects that set glob_matcher: doublestar get **/*.js.
    • lefthook: re-running init with a different package manager updates the existing job instead of adding a second one.
    • Both now run the project's installed Ultracite (npx, yarn, pnpm exec, bunx) instead of yarn dlx / pnpm dlx. Re-running init upgrades a hook or job written by an earlier version.
    • lefthook install runs the project's installed lefthook, and the prepare script is chained onto an existing one (e.g. svelte-kit sync || echo '' && lefthook install) instead of replacing it.
  • 9c30c15: Raise the oxlint peer dependency to ^1.82.0. The core Oxlint preset configures no-unmodified-loop-condition with checkConditionalExpressions, an option Oxlint 1.79 to 1.81 reject, so those releases failed with "Failed to parse oxlint configuration file" even though the old ^1.79.0 range allowed them. ultracite doctor and your package manager now flag the too-old version instead.

    Requires oxlint >= 1.82.0

  • 47303f4: The Biome jest preset now declares Jest's globals (describe, it, test, expect, jest, beforeEach and the rest of globals.jest) for test files. Jest injects them without imports, so noUndeclaredVariables from the core preset reported every one of them in idiomatic Jest tests. The ESLint jest preset already declared them.

    The route-file exemptions in the Biome remix and tanstack presets (useFilenamingConvention off in routes/) now cover .js and .jsx route files as well as .ts and .tsx.

  • 8f236ee: The ESLint core preset now lints .jsx, .tsx, .mts and .cts files. Its main block previously matched only .js, .mjs, .cjs, .ts, .json and .html, so ESLint skipped .mts and .cts files entirely ("File ignored because no matching configuration was supplied"), and .jsx and .tsx files received only the framework preset's rules. .tsx files were also parsed by espree, so any TypeScript syntax in them was a parse error. Every TypeScript extension now uses @typescript-eslint/parser with type information, and the core rules apply to all of them.

    Type information now comes from the TypeScript project service (parserOptions.projectService: true) instead of a fixed project: "./tsconfig.json". Solution-style tsconfigs ("files": [] plus references, as in the Vite templates) and monorepo packages now resolve their own tsconfig, where previously every file failed to parse. A file that no tsconfig includes still has to be added to one; typescript-eslint reports it as "not found by the project service" (see https://typescript-eslint.io/troubleshooting/typed-linting/#i-get-errors-telling-me-was-not-found-by-the-project-service-consider-either-including-it-in-the-tsconfigjson-or-including-it-in-allowdefaultproject).

    The JavaScript block no longer matches **/*.json. espree cannot parse JSON, so every package.json and tsconfig.json failed with Parsing error: Unexpected token :. The ESLint preset does not lint JSON, matching the Oxlint preset.

  • 94722fa: The eslint.config.mjs that ultracite init writes no longer fails its own lint. Every ESLint preset exported a default named config, so import core from "ultracite/eslint/core" (and each framework import) tripped import-x/no-rename-default twice per preset. Each preset's default export is now named after the identifier the generated config imports it as (core, react, tanstack, …).

  • d9803a6: Fix ESLint presets that crashed the whole run or never reached the files they target.

    • TanStack: @tanstack/start/no-async-client-component and @tanstack/start/no-client-code-in-server-component need type information and aborted ESLint ("You have used a rule which requires type information") on the first .jsx or .tsx file. They now run only on TypeScript files. The Query, Router and Start rules also apply to plain .ts/.js modules, where query and mutation options are usually declared, instead of only to .jsx and .tsx. sort-keys is off, and no-use-before-define and unicorn/filename-case are off in routes/ directories, matching the Oxlint and Biome TanStack presets (alphabetical option keys break TanStack's type inference, and file routes are mutually recursive and encode the URL in the filename).
    • Qwik: qwik/valid-lexical-scope needs type information and crashed ESLint on .jsx files. It now runs only on .tsx files.
    • Jest: jest/no-deprecated-functions threw "Unable to detect Jest version" and crashed ESLint when the jest package was not resolvable from the plugin, for example in bun:test projects. The preset now reads the Jest version from the project and falls back to the latest major.
    • Cypress: the block used globals.cypress, which does not exist in the globals package, so cy, Cypress, describe and it were reported by no-undef. It now uses eslint-plugin-cypress's own globals config. It also matched only *.cy.js, and now covers *.cy.* for every JS and TS extension plus files under cypress/.
    • Storybook: the block matched only *.stories.js and *.stories.ts. It now covers *.stories.* and *.story.* for every JS and TS extension, including .tsx and .jsx.
  • d6ee272: The ESLint vue, svelte and astro presets now parse their files. They registered only the plugin and its rules, never a parser, so ESLint read every .vue, .svelte and .astro file with espree and reported a parse error (Unexpected token <) instead of linting it.

    Each preset now starts from its plugin's own base config (flat/base in eslint-plugin-vue, eslint-plugin-svelte and eslint-plugin-astro), which registers vue-eslint-parser, svelte-eslint-parser or astro-eslint-parser from the plugin's dependencies, and parses <script lang="ts"> blocks with @typescript-eslint/parser. The Svelte preset also covers .svelte.js and .svelte.ts rune modules. In Astro files, client-side <script> tags are linted without type information, because those in-memory virtual files cannot be type-checked.

  • f7599ef: The ESLint core preset no longer re-enables formatting rules that eslint-config-prettier turns off. The unicorn rule set was spread after eslint-config-prettier, which switched unicorn/number-literal-case, unicorn/template-indent and unicorn/empty-brace-spaces back on. unicorn/number-literal-case demands 0xABCD while Prettier prints 0xabcd, so prettier/prettier and the unicorn rule reported every hex literal and eslint --fix could not satisfy both. eslint-config-prettier now applies after every plugin, so unicorn/number-literal-case and unicorn/template-indent are off. unicorn/empty-brace-spaces stays on (Prettier prints empty braces as {} too), matching the Oxlint preset.

  • efa80e8: The ESLint core preset no longer reports the same problem two or three times on TypeScript files, and no longer flags ambient type-only globals.

    • no-undef and sonarjs/no-reference-error are off for .ts, .tsx, .mts and .cts files. TypeScript already reports unresolved identifiers, and both rules flagged valid ambient types such as NodeJS.Timeout (see the typescript-eslint FAQ).
    • The base class-methods-use-this, consistent-return, no-unused-private-class-members, prefer-destructuring and prefer-promise-reject-errors rules are off for TypeScript files, because their @typescript-eslint extension rules are enabled there. The base rules duplicated every report and ignored the extensions' TypeScript-aware options.
    • unused-imports/no-unused-vars is off. It is a copy of no-unused-vars / @typescript-eslint/no-unused-vars, which stay on as in the Oxlint preset, so every unused variable was reported twice. unused-imports/no-unused-imports stays on for its autofix.
    • @typescript-eslint/max-params is off, matching max-params being off in the core presets. It was on with its default limit of 3 parameters for TypeScript files only.
  • 9ae95d1: Fix false positives in the ESLint vue, svelte and astro presets that appeared once their files were actually parsed.

    • vue/block-lang and svelte/block-lang rejected every <script lang="ts">, because with no options they only allow blocks without a lang attribute. They now allow TypeScript scripts, and less and scss styles, as well as blocks without lang.
    • Astro's client-side <script> tags are linted as virtual files named 1_1.ts, 2_1.js and so on, which github/filenames-match-regex reported on every page with a script tag. Filename rules are now off for those virtual files.
    • The Astro preset passes @typescript-eslint/parser for the frontmatter explicitly. ESLint's config merge dropped the copy in eslint-plugin-astro's base config, so frontmatter TypeScript parsed only when @typescript-eslint/parser happened to resolve from the working directory, and failed with The keyword 'interface' is reserved otherwise.
    • ultracite init now installs eslint-plugin-jsx-a11y for Astro projects using ESLint. The preset enables eslint-plugin-astro's astro/jsx-a11y/* rules, which load that package and reported "you need to install eslint-plugin-jsx-a11y" on every .astro file when it was missing.
  • e88e76d: The Prettier preset now sets tailwindFunctions to clsx, cva, tw, twMerge, cn, twJoin and tv, so prettier-plugin-tailwindcss sorts Tailwind classes passed to those helpers anywhere in a file, for example const button = cva("p-4 flex"). Previously only class strings inside class/className attributes were sorted with Prettier, while the Oxfmt (sortTailwindcss.functions) and Biome (useSortedClasses) presets already sorted these helpers. See https://github.com/tailwindlabs/prettier-plugin-tailwindcss#sorting-classes-in-function-calls.

  • 3a5885e: github/filenames-match-regex now accepts file-based routing filenames in the ESLint preset too, and Next.js's special pages in both presets.

    • The page-route regex (Oxlint js-plugins and now ESLint core) allows a leading underscore, so the Next.js pages-router files _app, _document and _error, which cannot be renamed, are no longer reported. Other names in pages/ (BadPage.ts) and camelCase route params ([postId], which unicorn/filename-case rejects too) are still reported.
    • The ESLint core preset now carries the same route exemptions as the Oxlint js-plugins preset (#​799, #​804). Previously it applied the plain kebab-case regex everywhere and reported SvelteKit's +page.ts and +server.ts, TanStack Router and React Router files such as posts.$postId.ts, and page routes such as [slug].json.ts and [...auth].ts.
    • The route-directory exemptions (github/filenames-match-regex in Oxlint js-plugins and ESLint core, plus unicorn/filename-case and no-use-before-define in the Oxlint and ESLint tanstack presets) now cover .js and .jsx route files as well as .ts and .tsx.
  • ad2adb0: The Stylelint preset now handles Tailwind CSS v4, SCSS and Less, and skips build output.

    • Tailwind CSS v4: @theme, @utility, @variant, @custom-variant, @slot, @plugin and @config are allowed by at-rule-no-unknown, alongside the Tailwind v3 at-rules and @source and @reference. at-rule-prelude-no-invalid no longer rejects every @apply (or the other Tailwind at-rules' preludes). custom-property-pattern accepts theme namespace resets (--color-*: initial) and sub-properties (--text-xl--line-height). declaration-property-value-no-unknown and function-no-unknown accept --spacing(), --alpha(), --value(), --modifier() and theme(). media-query-no-invalid accepts theme() breakpoints, and nesting-selector-no-missing-scoping-root allows & inside @custom-variant, @variant and @utility. See https://tailwindcss.com/docs/functions-and-directives.
    • import-notation is now "string". stylelint-config-standard's "url" autofix rewrote @import "tailwindcss" to @import url("tailwindcss").
    • SCSS and Less: .scss files are parsed with postcss-scss and .less files with postcss-less. Previously every SCSS and Less file failed with CssSyntaxError (for example on // comments or mixin calls). The CSS-only rules that cannot understand preprocessor syntax (unknown at-rules such as @use, @include and @mixin, $variable and @variable values, Sass and Less built-in functions, // comments) are relaxed for those files. ultracite init now installs postcss-scss and postcss-less with the ESLint toolchain.
    • .sass: the indented Sass syntax has no maintained PostCSS parser, so ultracite check and ultracite fix no longer pass .sass files to Stylelint, where every one failed to parse.
    • Ignores: ignoreFiles now uses the shared ignore list (dist, build, .next, coverage, storybook-static and so on). Stylelint does not read .gitignore, so it previously linted generated CSS.
    • Prettier: prettier/prettier is now enabled. The preset loaded stylelint-prettier but never turned its rule on.
    • ultracite check and ultracite fix now escape glob characters in directory arguments before passing them to Stylelint. A directory such as app/(marketing) previously matched no files.
  • 89989df: Test-file overrides in every preset now match .mts, .cts, .mjs and .cjs test files as well as .ts, .tsx, .js and .jsx. The globs were **/*.{test,spec,test-d,spec-d}.{ts,tsx,js,jsx} and **/__tests__/**/*.{ts,tsx,js,jsx}, so a sum.test.mts file got none of the test-file relaxations and none of the Jest or Vitest rules. For example, test.only in a .test.mts file was not reported by vitest/no-focused-tests or jest/no-focused-tests. This covers the Oxlint core, js-plugins, jest and vitest presets, the Biome core preset, and the ESLint core, jest and vitest presets.

  • 4d28cf9: The Oxlint vue preset now lists every non-nursery Vue rule Oxlint implements, like the other framework presets. It previously enabled 18 of them. Among the 27 newly enabled rules are vue/valid-define-props, vue/valid-define-emits, vue/no-export-in-script-setup, vue/no-lifecycle-after-await, vue/no-arrow-functions-in-watch, vue/no-side-effects-in-computed-properties, vue/require-typed-ref, vue/define-props-destructuring and the vue/no-deprecated-* rules. vue/max-props is off in both the Oxlint and ESLint presets, because its default allows a single prop per component.

    The Oxlint vitest preset now enables vitest/consistent-test-it, the one Vitest rule it was missing (the ESLint preset already had it).

    Vue files whose names Nuxt and file-based Vue Router require (pages/**, layouts/**, error.vue and app.vue) are exempt from useVueMultiWordComponentNames in the Biome preset and from vue/multi-word-component-names in the ESLint preset. Previously pages/index.vue, layouts/default.vue and error.vue were always reported.

v7.12.1

Compare Source

Patch Changes
  • 00dd547: Agent hooks now fix only the file the agent edited. The generated hook command passes a new --hook flag, and ultracite fix --hook reads the agent's payload from stdin: Claude Code and CodeBuddy (tool_input.file_path), Cursor (file_path) and Windsurf (tool_info.file_path). A file outside the project, one that no longer exists, or one the project's linters do not handle is skipped. A payload with no readable file path keeps the previous whole-project run. Re-running ultracite init rewrites a hook from an earlier init to the new command, including one generated before this change or for a different package manager or linter.

  • 300a814: Update @biomejs/biome to 2.5.14. Releases 2.5.13 and 2.5.14 add only nursery rules (14 of them, including noReturnInFinally, noSvelteAtHtmlTags and useValidTestTitle), with no stable-group additions, removals or promotions. The Biome presets deliberately leave nursery rules off, so they are unchanged.

  • b8b183b: Update dependencies (@clack/prompts 1.8, empathic 2.1, magicast, nypm, string-width 8.3, yaml and zod 4.6).

  • b59b8aa: Update oxfmt to 0.70.0 and re-target the markdown ::: fence patch. Releases 0.68 through 0.70 change no options; they fix suppression-comment handling, comment placement around operators and as/satisfies, and several YAML and CSS edge cases. oxfmt 0.69 also ships a native markdown formatter, but .md files still go through the Prettier-based path, so the fence patch still applies.

  • 548c8b0: Update oxlint to 1.85.0. Releases 1.83 through 1.85 add and remove no rules and change no options, so the presets are unchanged. Note that jest/prefer-strict-equal, vitest/prefer-strict-equal, vitest/prefer-to-be-truthy and vitest/prefer-to-be-falsy now offer suggestions instead of fixes, so ultracite fix reports them rather than rewriting them. unicorn/consistent-function-scoping also now catches functions that only capture variables from an outer ancestor scope.

  • 0bc6cd6: Update the ESLint family: eslint 10.11, eslint-plugin-unicorn 76, @typescript-eslint/* 8.70.1, eslint-plugin-jsdoc 64.5, eslint-plugin-astro 3.2, eslint-plugin-n 18.4, eslint-plugin-vue 10.11.1, @tanstack/eslint-plugin-query 5.104, @next/eslint-plugin-next 16.3.6, @darraghor/eslint-plugin-nestjs-typed 7.5.6, eslint-plugin-qwik 1.20.1, eslint-plugin-html 8.2.1 and eslint-plugin-react-doctor / oxlint-plugin-react-doctor 0.9.14.

    The ESLint core preset picks up unicorn's ten new JavaScript rules automatically: no-async-iterator-callback, no-unused-builtin-method-return (which replaces the now-deprecated no-unused-array-method-return), no-unused-iterator-helper, no-useless-set-construction, no-using-resource-escape, prefer-combined-guards, prefer-iterator-zip, prefer-json-import, prefer-temporal-conversion and prefer-uint8array-hex. The CSS-only unicorn rules added in v75 stay off for JavaScript files. unicorn 76 makes no-immediate-mutation skip conditional mutations and no-break-in-nested-loop skip continue by default; the preset keeps those defaults because oxlint's no-immediate-mutation behaves the same way and checking continue would contradict prefer-continue.

  • 0bcb2c6: Update prettier-plugin-astro to 1.1.0 (the version ultracite init installs for Astro projects with Prettier) and refresh the transitive Prettier lock to 3.9.9. Prettier 3.9.7 through 3.9.9 are formatting fixes with no option changes, so the Prettier preset is unchanged. prettier-plugin-astro 1.1 makes astroAllowShorthand tri-state. When it is unset, which is how Ultracite's generated config leaves it, attributes now stay as written instead of {value} being expanded to value={value}. Set astroAllowShorthand: false in your Prettier config to keep the 1.0 behaviour.

  • 8b39375: Update @shadcn/lint to 0.2.0 (the version ultracite init installs for the opt-in ultracite/oxlint/shadcn preset). The release adds Vue and Svelte support and fixes theme, barrel and class-site discovery; the rules and their options are unchanged, so the preset is too. Under Oxlint the plugin reads only the <script> blocks of .vue and .svelte files, not their templates.

  • 0bc6cd6: Update eslint-plugin-sonarjs to 4.2.1. The ESLint preset adopts its 16 new rules automatically (Vue, Cypress, Playwright, Testing Library, Vitest, Lodash, jQuery and Axios checks). The ultracite/oxlint/js-plugins preset now enables every sonarjs rule that does not need type information, adding 35 rules. These include the 15 new non-type-aware rules and nine test rules that older versions of oxlint's JS plugin bridge could not load. sonarjs 4.2.1 also raised the no-nested-functions default threshold from 4 to 5; both presets pin threshold: 4 to keep the previous strictness.

v7.12.0

Compare Source

Minor Changes
  • 1f427d7: Add an opt-in ultracite/oxlint/shadcn preset for @shadcn/lint, shadcn's agent-first linter for Tailwind v4 design systems. All six rules (no-restyle, no-raw-colors, no-arbitrary-values, no-inline-styles, no-unknown-classes, require-static-classes) run at error with the upstream allow: ["layout"] policy, and the component-authoring rules are relaxed inside **/components/ui/**. Enable it with ultracite init --linter oxlint --js-plugins @shadcn/lint, or extend it alongside ultracite/oxlint/core after installing @shadcn/lint.
Patch Changes
  • 600e991: Accept file-based page route filenames in github/filenames-match-regex. Files under pages/ (Astro, Next.js pages router) now match a bracket-aware pattern, so dynamic, rest and optional parameters such as [slug].astro, [...slug].ts and [[...slug]].tsx pass while non-route names like BadPage.ts are still rejected.
  • 66f97bb: Allow top-level return in Astro frontmatter. The core preset now turns off unicorn/prefer-module for **/*.astro files (the rule cannot be configured to allow only return), and keeps require(), module.exports, __dirname and __filename flagged there via import/no-commonjs and no-restricted-globals.

v7.11.1

Compare Source

Patch Changes
  • 24b2797: Update oxfmt to 0.67.0 and re-target the markdown ::: fence patch to the new dist chunk. The release changes no options; it fixes CSS/SCSS/Less comment preservation and a few JSDoc-cast edge cases in member chains.
  • 24b2797: Update oxlint to 1.82.0. The release adds and removes no rules, so the presets are unchanged apart from one new option: no-unmodified-loop-condition now runs with checkConditionalExpressions: true in the oxlint and ESLint core presets, so each branch of a ternary in a loop condition must be modified inside the loop rather than only the expression as a whole.
  • 24b2797: Update the ESLint family: @angular-eslint/eslint-plugin 22.5, @typescript-eslint/* 8.70, eslint-plugin-solid 0.18, eslint-plugin-vue 10.11, eslint-plugin-jsdoc 64.3.8, eslint-plugin-cypress 7.0.2, @darraghor/eslint-plugin-nestjs-typed 7.5.2 and prettier-plugin-astro 1.0. The dynamic presets pick up the seven new rules automatically: @typescript-eslint/no-generated-empty-object-type, @angular-eslint/reactive-context-must-read-signal, vue/no-shadow-native-events, and Solid's no-boolean-enumerated-attribute, no-store-mutation-outside-setter, no-unused-signal and no-write-in-pure-computation. Note that prettier-plugin-astro 1.0 is a rewrite on the Astro 7 Rust compiler (Node 22.12+); expect whitespace diffs on first run and mirror any custom compressHTML via its new astroCompressHTML option.
  • 24b2797: Refresh the stylelint lock to 17.15.0 and enable its new selector-no-unmatchable rule, which flags selectors that can never match (for example label:checked, ::before:first-child or :is(::before)).
  • a71dda4: Stop sorting object keys across the whole TanStack presets, not just route files. TanStack Query mutation options are order-sensitive too: TypeScript infers the onMutate context from context-sensitive callbacks in source order, so moving onError/onSettled above onMutate turns the context into {} and ultracite fix broke type-correct code (TS2339: Property '...' does not exist on type '{}'). Mutation and query options live anywhere (hooks, components, colocated files), so the route-file exemption could not cover them. ultracite/oxlint/tanstack now sets sort-keys to off and ultracite/biome/tanstack now sets useSortedKeys to off for all files.
  • a9db61c: Disable github/filenames-match-regex for file-based route directories (**/routes/**) in the oxlint js-plugins preset, matching the existing unicorn/filename-case exemption in the TanStack preset. TanStack Router filenames such as __root.tsx, $.tsx, and posts.$postId.tsx no longer fail the GitHub filename rule. Resolves #​799.

v7.11.0

Compare Source

Minor Changes
  • d5d241f: Add ultracite upgrade, and make version drift between Ultracite and its linter visible instead of a crash. Bumping ultracite without bumping the linter fails on the next check/fix with Biome's Found an unknown key error (and the equivalent for ESLint and Oxlint), because each release enables rules from a specific linter version.

    • ultracite upgrade installs the latest ultracite, prints a release-notes link for the versions you crossed, then hands off to the freshly installed CLI to reinstall your toolchain at the versions that release was verified with: Biome; ESLint, Prettier, Stylelint and the plugins the preset imports; or Oxlint and Oxfmt. Optional extras already in your package.json (framework plugins, Oxlint JS plugins, oxlint-tsgolint) are bumped as well. Config files are never rewritten, and the run ends with the same diagnostics as doctor.
    • ultracite doctor now checks the installed Biome, ESLint, Prettier, Stylelint, Oxlint and Oxfmt versions against the range this release supports. Too old fails the check and points at ultracite upgrade; newer than the verified range only warns.
    • The supported ranges are declared as optional peer dependencies so package managers warn when they drift: @biomejs/biome ^2.5.0, eslint ^10.0.0, prettier ^3.0.0, stylelint ^17.0.0, oxlint ^1.79.0, oxfmt >=0.40.0. ultracite init now installs Prettier and Stylelint from those ranges instead of latest.

    Requires Biome >= 2.5.0, ESLint >= 10.0.0, Prettier >= 3.0.0, Stylelint >= 17.0.0, Oxlint >= 1.79.0 and Oxfmt >= 0.40.0.

Patch Changes
  • 27d06f2: Update dependencies (@clack/prompts, semver, zod, ESLint plugins).
  • d322691: Default ultracite init to Oxlint + Oxfmt when --linter is omitted in quiet or non-interactive mode
  • c677cf5: Recommend Oxlint + Oxfmt in the ultracite init linter prompt and list it first
  • c5be848: Disable no-use-before-define in TanStack Router route files for the oxlint tanstack preset. File routes are mutually recursive (Route references the component, and the component calls Route.useParams()), so no declaration order could satisfy the rule.

v7.10.8

Compare Source

Patch Changes
  • 2a43fdd: Turn off unicorn/prefer-reflect-apply in the ultracite/oxlint/anti-slop preset. When extended after ultracite/oxlint/core, the core rule recommended rewriting Function#apply() to Reflect.apply(), which anti-slop's no-reflect-apply then rejected, leaving no way to satisfy both. Direct-call guidance for .apply() still comes from eslint/prefer-spread and eslint/no-useless-call.

  • 03196df: Update @biomejs/biome to 2.5.12. Releases 2.5.10 through 2.5.12 only add nursery rules, which the Biome presets exclude, so the presets are unchanged. The releases also carry linter and formatter fixes, including fewer noUnusedVariables false positives on merged interfaces, namespaces, and overload type parameters, an unsafe-by-default fix for noThisInStatic, and a large batch of Astro expression parsing fixes.

  • 031b867: Update oxfmt to 0.66.0. The 0.65 and 0.66 releases are formatter fixes only, mainly around comment placement between a statement head and its body, suppressed statements (decorators, typecast parens, semicolons), custom side-effect groups in sortImports, CommonMark list interruption in JSDoc, and trailing whitespace in YAML block scalars. The ::: container-directive fence patch is re-targeted to the new markdown bundle; the patched code itself is unchanged.

  • 54affee: Update oxlint to 1.81.0. The 1.80 and 1.81 releases add no rules and remove none, so the presets are unchanged and the peer range stays at ^1.79.0. Notable fixes carried in: no-use-before-define now runs on JS and JSX files, object-shorthand preserves __proto__ semantics, unicorn/prefer-math-min-max no longer applies an unsafe autofix, and JS plugin diagnostics with invalid or reversed locations are clamped instead of crashing.

  • 0b058d1: Fix ultracite fix --codex failing on recent Codex CLI releases. The Codex adapter invoked codex exec --full-auto, a flag Codex has since removed, so every attempt failed at argument parsing. It now runs codex exec --sandbox workspace-write, the equivalent non-interactive, workspace-scoped mode, which is also accepted by older Codex versions. Resolves #​794.

  • e2346bb: Update the ESLint family to latest: eslint 10.9.1, typescript-eslint 8.69.0, eslint-plugin-unicorn 74, eslint-plugin-solid 0.17, eslint-plugin-jsdoc 64.3.5, eslint-plugin-react-doctor and oxlint-plugin-react-doctor 0.9.13, globals 17.12, and the angular, nestjs-typed, next, tanstack-query, cypress, html, jest and storybook plugins. The dynamic presets pick up the new rules automatically: the solid preset gains the eleven rules added in eslint-plugin-solid 0.16 and 0.17 (removed-api, no-single-arg-create-effect, no-accessor-as-prop, valid-use-server, require-async-server-function, no-invalid-server-capture, no-browser-globals-in-server-function, no-module-scope-reactive-primitive, no-restated-default-options, prefer-onSettled-for-side-effects, prefer-structured-class), which only report Solid 2.0 issues when settings.solid.version is set to 2 and stay silent on Solid 1.x code; the nestjs preset gains forward-ref-injection-should-use-wrapper-type, swagger-file-upload-should-be-documented and uploaded-file-should-be-validated. The curated jsdoc and react-doctor lists are unchanged. No enabled rule was removed or deprecated, and the ESLint/oxlint parity check still passes.

  • 7b0456e: ultracite fix now runs lint fixes before the formatter: oxlint before oxfmt, and ESLint then Stylelint before Prettier. A fixer can insert unformatted code, such as the braces curly adds, the imports consistent-type-specifier-style splits, or the font names Stylelint requotes, and running the formatter first left that code unformatted until the next run. Fixer-inserted code is now formatted in the same run. The --claude and --codex agent passes follow the same order.

    unicorn/no-nested-ternary is now off in the oxlint and ESLint presets: its fixer adds parentheses that oxfmt and Prettier remove, so the two tools rewrote the file on every run. The core no-nested-ternary rule still reports nested ternaries.

  • 8ddc078: Enable three rules added in Stylelint 17 in the Stylelint preset: selector-no-deprecated and selector-no-invalid report selectors that CSS has dropped or that cannot parse, and relative-selector-nesting-notation is set to explicit, so nested relative selectors are written & > b rather than > b. The property-layout-mappings, unit-layout-mappings and value-keyword-layout-mappings rules are deliberately left off, since they reject every physical property, unit and keyword and can only autofix with a per-project languageOptions.directionality setting. The repo's own Stylelint lock is refreshed from 16.26.1 to 17.14.1, which the config packages already required; ultracite init already installs stylelint@latest so users are unaffected by the lock change.

  • 4609d79: Update the vendored anti-slop Oxlint plugin to upstream v0.1.2 (commit e8c4880). The rule set is unchanged; this picks up a round of correctness fixes: no-known-value-widening now also reports known values passed into local unknown-typed type predicates, no-object-parameters, no-unknown-parameters, no-unknown-returns and no-unknown-type-aliases resolve scoped and transparent generic aliases (including block-scoped aliases and forward references), no-unknown-returns covers PromiseLike<unknown>, no-unsafe-dictionary-type allows generic constraints such as T extends Record<string, unknown>, no-runtime-typeof always allows existence probes against "undefined", no-shape-in-symbol-names allows static member reads such as Zod's schema.shape, and require-safety-comment-for-type-assertion rejects empty justifications and gains a markers option (default ["SAFETY"]). Upstream also added a separate opt-in anti-slop-effect plugin for Effect projects, which is not vendored.

v7.10.7

Compare Source

Patch Changes
  • 15f7ae0: Add support for the Aube package manager: ultracite init --pm aube is now accepted and projects with an aube-lock.yaml lockfile are detected automatically

  • 1afc8fe: Re-declare selected Oxlint JS plugins on the root config so dependency analyzers see them. ultracite init --linter oxlint --js-plugins ... now generates const jsPlugins = selectJsPlugins([...]) and adds jsPlugins: jsPlugins.jsPlugins to the root config (also when the full ultracite/oxlint/js-plugins preset is extended). Knip only resolves jsPlugins from the root Oxlint config and never walks extends, so eslint-plugin-github, eslint-plugin-sonarjs, and oxlint-plugin-react-doctor were reported as unused devDependencies. Oxlint dedupes the plugin between the root and the extended preset, so linting is unchanged.

    Also fix ultracite update dropping the js-plugins preset from extends when the config used the documented import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins" form: the import parser only matched bare default imports. The regenerated full-preset config keeps settings: jsPluginSettings on the root as well.

  • 20b06bf: Ignore .alchemy across all linters and formatters. Alchemy (alchemy.run) writes local state and generated bindings to a .alchemy directory. It is now part of the shared ignore patterns synced into Biome's files.includes and imported by oxlint, oxfmt, and ESLint, and the Stylelint preset ignores it via ignoreFiles. Prettier needs no change: it already respects .gitignore/.prettierignore.

  • 6e9286c: Run lefthook install during ultracite init through the same spawn adapter as every other tool invocation instead of execSync, so it no longer goes through a shell and gets the same Windows command resolution as husky, the linters, and editor extension installs.

  • 8b24f34: Add support for the Nub package manager: ultracite init --pm nub is now accepted and projects with a nub.lock lockfile are detected automatically (requires nypm ^0.6.9)

  • 240cb6b: Install into the workspace root correctly for Nub and Aube monorepos: nypm emits no root selector for them, so nub add ran without -w and was refused. Ultracite now hands nypm pnpm's flag set for these pnpm-compatible CLIs, producing nub add --workspace-root --save-dev ultracite

  • 44ecbba: Add Vitest type-test files (**/*.{test-d,spec-d}.{ts,tsx,js,jsx}) to the test-file globs so the shared test relaxations and the Vitest rule overrides apply to them, and enable the Vitest plugin's typecheck setting in the ESLint preset so expectTypeOf/assertType count as assertions.

  • 7ba6bb8: Package the reusable Ultracite agent skill with the npm distribution.

v7.10.6

Compare Source

Patch Changes
  • 972b946: Update the oxlint presets for oxlint 1.79: replace the removed react/react-compiler rule with the 22 new React Compiler rules in the react preset, add jsdoc/no-blank-blocks and one-var to the core preset (mirrored in the ESLint presets), and require oxlint ^1.79.0
  • 2d5bbdb: Declare the jsPluginSettings named export in the ultracite/oxlint/js-plugins type declarations, so the documented (and ultracite init-generated) import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins" type-checks (#​773)
  • 56aef65: Refresh the toolchain versions that ultracite init installs into projects: @biomejs/biome 2.5.9, the ESLint plugin family (including eslint-plugin-cypress 7, eslint-plugin-jsdoc 64, eslint-plugin-solid 0.15, and eslint-plugin-unicorn 73 — the dynamic presets adopt their new rules automatically), and prettier-plugin-svelte 4.1.1 / prettier-plugin-tailwindcss 0.8.1

v7.10.5

Compare Source

Patch Changes
  • 8df6ad0: Offer the vendored anti-slop Oxlint preset during ultracite init — it now appears in the JS-plugins prompt when you pick Oxlint, and non-interactive setup accepts it via --js-plugins anti-slop. Selecting it adds ultracite/oxlint/anti-slop to the generated config's extends; since the preset is vendored inside Ultracite, nothing extra is installed.
  • cd229e9: Bump the oxlint-plugin-react-doctor pin from ^0.7.1 to ^0.9.12, so ultracite init installs the current plugin. All react-doctor rules enabled by the js-plugins presets still exist in 0.9.12, and the ported rules run in curated mode via the settings shipped alongside this release (#​771).
  • e1ac886: Pin React Doctor's ported rules to their framework-aware "curated" mode (#​771). react-doctor 0.9.x rewrote its ported oxc/react-refresh rules — notably only-export-components — with a stripped-down default mode: no framework detection, no route-file skipping, and allowConstantExport off, so Next.js route-segment exports like export const dynamic = "force-static" or metadata were flagged as non-component exports in every route file. The ESLint react preset now sets settings["react-doctor"].portedRuleMode: "curated", and generated oxlint configs apply a new jsPluginSettings export from ultracite/oxlint/js-plugins on the root config (oxlint does not merge settings from extended configs, so the setting cannot ride along inside the preset). If you extend the js-plugins preset manually, add settings: jsPluginSettings to your root oxlint config.
  • c27fe36: Generate oxlint configs that enable a subset of the JS plugins via a new selectJsPlugins export from ultracite/oxlint/js-plugins, instead of inlining the filtering logic into the generated file. The inlined block contained a typeof check that user-side lint presets flagged (anti-slop/no-runtime-typeof, #​770); the generated config is now a one-line extend, is emitted already formatted (including the previously missing blank line after imports), and re-running ultracite init migrates existing configs with the old inlined block automatically.
  • 0616523: Update the vendored anti-slop Oxlint plugin to upstream commit 446268e, picking up fixes to no-object-parameters and no-unknown-returns (respect lexical type binders in alias resolution) and a new allowInTypeGuards option on no-runtime-typeof. The ultracite/oxlint/anti-slop preset enables allowInTypeGuards, so typeof checks inside type predicate functions ((x): x is T) no longer need disable comments — predicates are the named-boundary pattern the rule pushes toward (dmmulroy/anti-slop#10).

v7.10.4

Compare Source

Patch Changes
  • 417a85a: Add an opt-in ultracite/oxlint/anti-slop preset that ships a vendored, self-contained build of the anti-slop Oxlint plugin — fifteen rules that reject low-evidence TypeScript and JavaScript patterns (unjustified type assertions, unknown leaking through signatures, Reflect-based access, module mocking, and more). Extend it alongside ultracite/oxlint/core; nothing extra to install. The preset also turns off two core rules that conflict with anti-slop's widening checks (typescript/consistent-indexed-object-style and unicorn/no-immediate-mutation) when extended after core.
  • 4d3fab8: Move suspicious/useArraySortCompare from the Biome core config to the opt-in type-aware config. The rule is in Biome's types domain — it type-infers the receiver of every method call before checking the method name, which made ultracite check up to ~260x slower on projects with expensive library types (zod, better-auth, Prisma). It now only runs when type-aware linting is explicitly enabled, alongside the other type/project-domain rules. Fixes #​768.

v7.10.3

Compare Source

Patch Changes
  • a1fa9c4: Replace the hand-rolled package exports map matching in the config-resolution doctor check with the resolve.exports library, which implements Node's full PACKAGE_TARGET_RESOLVE algorithm (wildcard patterns, key-order precedence, conditional exports, and array fallbacks). The manual node_modules walk is kept intentionally — it exists to avoid Bun's auto-install cache resolving specifiers the project's own node_modules can't.
  • 414ea80: Replace the hand-rolled monorepo workspace scan in framework detection with the find-workspaces library. Workspace declarations from package.json (array and yarn-classic object form) and pnpm-workspace.yaml — including negated globs — are now resolved by the library instead of manual pattern collection and globbing, and lerna/bolt monorepos are picked up as well.
  • a9a1989: Replace the hand-rolled upward directory walks in findNearestFile and detectLinter with the empathic library's find.any, which checks candidate names in order within each directory before moving to the parent — the same per-directory precedence the previous implementation enforced manually.
  • 27b2707: Use magicast to update ESM lint-staged config files during ultracite init. The config is now edited as an AST instead of being imported and re-serialized, so comments and function-valued entries elsewhere in the config survive the update, and the user's config code is no longer executed. If the Ultracite glob pattern is already owned by a non-array value, or the config isn't a mergeable object literal (e.g. defineConfig(...)), init warns and leaves the file untouched instead of rewriting it. CommonJS configs keep the previous behavior.
  • f2529b8: Rewrite the agent-fix progress renderer on top of log-update, cli-truncate, and string-width. log-update now owns the in-place block rewriting that was previously done with manual cursor-up/clear-line escape sequences, and line truncation is measured by display width instead of code units — so lint messages containing emoji or CJK text can no longer overflow the terminal row and corrupt the animated block.
  • 277b9d6: Replace the hand-rolled child-process handling in the agent fix runner with execa. The timeout → SIGTERM → grace period → SIGKILL escalation, stderr capture, and spawn-failure handling now use execa's timeout and forceKillAfterDelay options, which are battle-tested across platforms (including Windows kill semantics the manual implementation didn't cover). Behavior is unchanged: agent runs still time out after 5 minutes, escalate to SIGKILL after a 10-second grace period, and report a capped stderr tail.
  • 1614a80: Drop the direct cross-spawn dependency: all synchronous process spawning (linter runs, tool version checks, editor extension installs, skill installs) now goes through a small adapter over execa's sync API, which owns the Windows spawn semantics cross-spawn provided. The adapter preserves the spawnSync result shape (status/signal/error/stdout), always disables shell interpretation, and always decodes output as UTF-8. execa was already a dependency for the agent fix runner, so this consolidates on one process-spawning library.
  • ac114b4: Replace the glob dependency with fast-glob for the tsconfig.json scan during init. fast-glob was already in the dependency tree via find-workspaces, so this drops glob's transitive dependencies (minipass, path-scurry, etc.) from the install without changing behavior.

v7.10.2

Compare Source

Patch Changes
  • 1c48c68: Enable Tailwind CSS class sorting (sortTailwindcss) in the Oxfmt preset. Classes in class/className attributes and in clsx, cva, tw, twMerge, cn, twJoin, and tv calls are now sorted using the same algorithm as prettier-plugin-tailwindcss, matching the behavior of the Prettier preset (which always loads the Tailwind plugin) and the Biome preset's useSortedClasses rule. Projects without Tailwind installed are unaffected beyond class strings being sorted against the default theme, and oxfmt versions older than 0.35.0 ignore the option.
  • dc78be4: Stop sorting TanStack route option keys in route files. TanStack Router's route option types are order-sensitive (head/component infer loaderData from properties declared before them), so the Biome useSortedKeys source action rewrote createFileRoute literals into an order that breaks type inference (loaderData becomes never). The Biome TanStack preset now disables useSortedKeys for route files, and the oxlint TanStack preset disables sort-keys there so route files aren't caught between it and react-doctor/tanstack-start-route-property-order.

v7.10.1

Compare Source

Patch Changes
  • d018b7f: Fix several agent fix mode (fix --claude/--codex) issues: runs no longer abort with ENOBUFS when linter JSON output exceeds 1MB, user-supplied format/reporter flags can no longer override the JSON reporter and break parsing, a stuck agent process is force-killed 10 seconds after the timeout instead of hanging forever, and the progress renderer no longer garbles TTY output when file paths and rule names exceed the terminal width.
  • d018b7f: Fix Biome config migration leaving the legacy bare "extends": ["ultracite"] form in place, which breaks Biome's module resolution since the package has no root export. It's now mapped to ultracite/biome/core.
  • d018b7f: Fix ultracite doctor reporting spurious failures: config checks now walk up parent directories (matching check/fix and the linters themselves) so monorepo packages inheriting a root config pass, .oxlintrc.json is accepted as a valid oxlint config (with a migration suggestion), and Prettier/Stylelint configs declared via package.json keys are recognized.
  • d018b7f: Fix ultracite init corrupting existing Prettier/Stylelint/ESLint configs by writing an ESM module into JSON/YAML/TOML/CJS config files (e.g. .prettierrc, eslint.config.cjs). Updates now write the default .mjs config instead and remove the incompatible file so it can't shadow the new one.
  • d018b7f: Fix ultracite check/fix misrouting space-separated flag values (e.g. --max-warnings 10) into the file list, which scrambled the underlying linter invocation and made formatters fail on bogus targets. Positional files listed before a -- separator are also kept as lint targets instead of being reclassified as passthrough, which could silently widen formatter runs to the whole project.
  • d018b7f: Fix Lefthook and pre-commit YAML updates silently doing nothing on common config shapes: the Lefthook job is now inserted correctly when jobs: isn't the first key under pre-commit: (and no longer matches a jobs: key in a different hook), repos: [] in .pre-commit-config.yaml is handled, and shapes that can't be safely edited produce a warning instead of writing the file back unchanged.
  • d018b7f: Fix the Husky integration overwriting an existing .husky/pre-commit hook: ultracite init ran husky init, which unconditionally replaces the hook with npm test. It now runs plain husky to set up the hooks infrastructure without touching the hook file.
  • d018b7f: Fix ultracite init destroying user files it couldn't parse or merge: unparseable tsconfig.json files are no longer replaced with a minimal config, unparseable .vscode/.zed settings are no longer overwritten wholesale, and lint-staged configs with function-valued entries are left untouched — all now warn and skip instead.
  • d018b7f: Fix re-running ultracite init on an oxlint setup silently enabling the full js-plugins preset — the previously selected JS plugins are now preserved when no new selection is made. Init also no longer flips an explicit "type": "commonjs" in package.json to "module"; it warns instead.
  • d018b7f: Fix switching linters removing storybook from the project's dependencies. It was swept into the removal set as a peer of eslint-plugin-storybook, but it's a user-facing tool a project may use independently of linting.
  • d018b7f: Fix Stylelint target generation dropping directories with a dot in their name (e.g. app.web) and producing non-matching globs from Windows-style backslash paths. Framework detection also handles negated workspace patterns (!packages/legacy) again.
  • d018b7f: Fix the CLI becoming a silent no-op (exiting 0 without linting anything) when a generic TEST environment variable is set, as is common in CI matrices. The internal test guard now uses ULTRACITE_TEST.
  • 36c7b80: Move @​typescript-eslint/utils from dependencies to devDependencies. It was accidentally shipped as a runtime dependency in 7.9.0, pulling eslint and the typescript-eslint packages into every consumer's install (including oxlint-only setups) via npm's automatic peer dependency installation. Nothing in the published package imports it — it only exists to support the workspace-internal rule-parity script.

v7.10.0

Compare Source

Minor Changes
  • cd0a36c: Add --claude and --codex flags to ultracite fix. After the normal autofix pass, remaining diagnostics are handed to the Claude Code or Codex CLI non-interactively, one agent run per affected file, with a live per-issue spinner that flips to ✓/✗ once the fix is verified by a re-lint. Fixes that don't survive verification are retried (up to 3 attempts per file) with the fresh diagnostics and feedback that the previous approach failed. Works with all three linter modes (Oxlint, Biome, ESLint); exits non-zero if any issues remain, matching the plain fix contract.

  • e089510: Scope React Doctor's framework-specific rules to per-framework add-on presets (#​752)

    The ultracite/oxlint/js-plugins preset no longer enables React Doctor's nextjs-* and TanStack (query-*, tanstack-start-*) rules for every consumer. Rules like nextjs-no-img-element and tanstack-start-no-anchor-element fire on plain <img>/<a> JSX and recommend framework replacements, which falsely errored in Vite + React and other non-Next/non-TanStack projects.

    Those rules now live in two new add-on presets:

    • ultracite/oxlint/next/js-plugins
    • ultracite/oxlint/tanstack/js-plugins

    ultracite init wires the matching add-on automatically when you select the framework together with oxlint-plugin-react-doctor. If you manage oxlint.config.ts by hand and use Next.js or TanStack, add the matching add-on preset to extends alongside js-plugins to keep those rules — or re-run npx ultracite init.

    Also fixes re-running init on a config that already extends js-plugins producing a duplicate import jsPlugins declaration.

Patch Changes
  • 3320cd8: Update Biome to 2.5.6. No stable (non-nursery) rules were added, removed, or promoted between 2.5.3 and 2.5.6, so the preset configs are unchanged.

  • 477cd6e: Update ESLint to 10.8.0 and all ESLint plugins to their latest versions. Highlights:

    • eslint-plugin-react-doctor 0.9.3: the react preset expands from 149 to 417 rules, adopting the upstream recommended set (react-router, three.js/r3f, ink, motion, remotion, zustand/valtio/mobx, and more) while excluding rules that duplicate already-enabled react, react-hooks, and jsx-a11y rules. The next preset gains nextjs-async-dynamic-api-not-awaited and nextjs-metadata-url-consistency; the tanstack preset gains tanstack-start-missing-scripts, query-floating-mutate-async, and query-no-mutation-in-effect-as-read.
    • eslint-plugin-unicorn 72: adds no-missing-local-resource, no-multiple-promise-resolver-calls, no-shorthand-property-overrides, no-transition-all, no-unnecessary-string-trim, no-useless-re-export, prefer-then-catch, and require-frontmatter-fields. CSS-only rules are excluded from the preset since they fail config validation for JS files.
    • eslint-plugin-sonarjs 4.2: adds 11 rules including no-fixed-wait-in-tests, parameterized-tests, assertions-in-test-cases, prefer-native-lodash-alternative, and explicit-test-skip.
    • typescript-eslint 8.65: @typescript-eslint/no-loop-func and @typescript-eslint/no-restricted-imports were deprecated upstream in favor of the base rules, which now apply to TypeScript files.
    • eslint-plugin-astro 3: removes astro/no-omitted-end-tags and astro/valid-compile.
    • eslint-plugin-svelte 3.22: adds no-bind-value-on-checkable-inputs and no-conflicting-module-names; no-restricted-html-elements is now off because its schema requires a user-supplied element list.
    • @angular-eslint/eslint-plugin 22.1: adds inject-at-top and prefer-service-decorator.
  • b81578b: Fix the useSortedPackageJson action not being executed by turning on assist actions for package.json-like files.

  • 9ec454a: Update oxlint to 1.76.0 and oxfmt to 0.61.0. New stable rules added to the presets: oxc/bad-match-all-arg, id-denylist, node/exports-style (core), react/function-component-definition with arrow-function components (react), and vitest/padding-around-test-blocks (vitest). node/no-top-level-await is off — top-level await is idiomatic in ESM, Astro frontmatter, and build scripts — and the ESLint preset's n/no-top-level-await is now off to match. No rules were removed or promoted out of nursery.

  • ba61c02: Fix generated oxlint.config.ts accessing plugin.name on ExternalPluginEntry without narrowing the string form, which caused a TypeScript error in projects that type-check the config (#​753)

v7.9.4

Compare Source

Patch Changes
  • f480c12: Upgrade Biome to 2.5.3 to fix the LSP scanner deadlock (#​10845) where editors get stuck on "Biome is scanning the project".
  • 1d70c40: Fail fast with an actionable message when Biome can't resolve ultracite/biome/core. Biome resolves that config out of the project's node_modules, so it errors with an opaque "module not found" whenever Ultracite isn't installed there — a state npx ultracite check / bunx ultracite check hide, because they run the CLI from a temp cache regardless. check and fix now detect it before invoking Biome and say what's actually wrong, and doctor verifies that Ultracite resolves rather than just appearing in package.json (#​750).
  • 38d10bc: Move Biome's noUnknownAttribute rule out of the core preset and into the react preset. The rule only recognises React's JSX attribute names, so projects using Solid, Svelte, Vue, or Qwik were incorrectly flagged for framework-standard attributes such as class.
  • cf723bd: Add interactive and non-interactive selection for optional Oxlint JS plugins during init.

v7.9.3

Compare Source

Patch Changes
  • dc6d760: Disable the n/no-unpublished-import rule in the ESLint core config. This rule flags imports of packages that aren't listed as published dependencies, but it produces a lot of false positives in practice, so it's now turned off.
  • 15ecfba: Fix ultracite init --linter eslint installing an unusable toolchain. The generated ESLint config imports eslint-plugin-storybook unconditionally (which requires the storybook peer) and the generated Stylelint config extends stylelint-config-standard / stylelint-config-idiomatic-order / stylelint-prettier, but none of those packages were installed — so a fresh ESLint setup failed to load with "Cannot find package 'storybook'" or "Could not find stylelint-config-standard". These four packages are now installed with the ESLint linter.
  • 2f73a41: Upgrade to oxlint 1.73.0 and oxfmt 0.58.0, and enable the new lint rules they introduce: no-unreachable-loop, unicorn/explicit-timer-delay, and unicorn/no-confusing-array-with.
  • 83b2783: Add an [astro] formatter mapping (astro-build.astro-vscode) to the oxlint VS Code editor settings generated by ultracite init, since oxfmt doesn't format .astro files.
  • d186c53: Move every JS-plugin-based rule set out of the Oxlint core and framework presets and into a single opt-in ultracite/oxlint/js-plugins preset. This covers eslint-plugin-github and eslint-plugin-sonarjs (previously in core) as well as oxlint-plugin-react-doctor (previously bundled into the react, next, and tanstack presets). The core, react, next, and tanstack presets now run entirely on Oxlint's native Rust rules, so new setups no longer install those dependencies and no longer pay the slower JS-plugin lint pass. To keep the extra ESLint-parity and React Doctor rules, install eslint-plugin-github, eslint-plugin-sonarjs, and oxlint-plugin-react-doctor and extend ultracite/oxlint/js-plugins alongside core (and your framework preset).
  • 057753e: Add performance benchmarks for ultracite check / ultracite fix across all three providers (oxlint, biome, eslint). A new CI job builds the PR and its base branch on the same runner, benchmarks them interleaved, and fails on a statistically significant regression (median ratio > 1.25x with Mann-Whitney U p < 0.05) so config changes can't silently slow the linters down again.

v7.9.2

Compare Source

Patch Changes
  • c335a1f: Add **/node_modules and **/.git to the shared ignore patterns. oxlint only skips node_modules when a .gitignore lists it, so in projects without one, ultracite fix would lint and autofix files inside node_modules — corrupting installed packages (e.g. rewriting var enum wrappers in typescript/lib/typescript.js to self-referencing const, causing "Cannot access 'Comparison' before initialization" when oxlint loads eslint-plugin-sonarjs). Fixes #​737.

v7.9.1

Compare Source

Patch Changes
  • ecd10cc: Disable sonarjs/no-implicit-dependencies and github/no-implicit-buggy-globals in the oxlint and ESLint presets. Both produce false positives through oxlint's JS plugin bridge: no-implicit-dependencies has no dependency-manifest resolution so it flags builtin (bun:test) and workspace imports as missing dependencies, and no-implicit-buggy-globals misreads module-scoped declarations such as Astro frontmatter as implicit globals.

  • c76f59d: Disable sonarjs/file-name-differ-from-class in the oxlint and ESLint presets. It fires on any file whose name differs from an exported class, which is noise for the many config and module files that export objects rather than classes.

  • 29e30ce: Fold the github and sonarjs rules into the oxlint core preset. The standalone ultracite/oxlint/github and ultracite/oxlint/sonarjs presets are removed — ultracite ships framework presets, not individual plugins. Their rules now live in ultracite/oxlint/core, so every oxlint setup gets eslint-plugin-github and eslint-plugin-sonarjs through oxlint's JS plugin bridge, matching how the ESLint preset already bundles them into core.

    This is a breaking change to generated configs: ultracite/oxlint/github and ultracite/oxlint/sonarjs no longer exist. Re-run ultracite init to regenerate oxlint.config.ts.

    Also fixed: nine sonarjs rules (async-test-assertions, hooks-before-test-cases, no-duplicate-test-title, no-empty-test-title, no-floating-point-equality, no-forced-browser-interaction, no-trivial-assertions, prefer-specific-assertions, super-linear-regex) that exist in eslint-plugin-sonarjs but that oxlint's JS plugin bridge does not register. Naming them made oxlint hard-fail config parsing, which broke ultracite fix/check for oxlint projects using the sonarjs preset. They are omitted from oxlint core (still enabled in the ESLint preset), and a test now runs oxlint against core to catch this class of regression.

    The React Doctor, github, and sonarjs plugins are installed into your project's devDependencies at init (as the ESLint plugins already were), rather than bundled as dependencies of ultracite — oxlint resolves JS plugin specifiers from the project root, so they must be installed there directly.

  • 8a4291f: Upgrade to Oxlint 1.72.0 and Oxfmt 0.57.0. Oxfmt 0.57 adds native CSS and GraphQL formatters. The five new non-nursery Oxlint rules from the 1.71/1.72 releases are already covered by the presets (node/no-sync, node/no-mixed-requires, unicorn/prefer-number-coercion, unicorn/max-nested-calls, vue/no-async-in-computed-properties). The markdown ::: container-directive fence patch (which keeps proseWrap: "never" from folding fences into prose) was regenerated against the 0.57 bundle.


Configuration

📅 Schedule: (in timezone Europe/Warsaw)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | [`2.5.2` → `2.5.13`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.5.2/2.5.13) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@biomejs%2fbiome/2.5.13?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@biomejs%2fbiome/2.5.2/2.5.13?slim=true) | | [modernc.org/sqlite](https://gitlab.com/cznic/sqlite) | `v1.59.0` → `v1.60.1` | ![age](https://developer.mend.io/api/mc/badges/age/go/modernc.org%2fsqlite/v1.60.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/go/modernc.org%2fsqlite/v1.59.0/v1.60.1?slim=true) | | [ultracite](https://www.ultracite.ai/) ([source](https://github.com/haydenbleasel/ultracite)) | [`7.9.0` → `7.12.2`](https://renovatebot.com/diffs/npm/ultracite/7.9.0/7.12.2) | ![age](https://developer.mend.io/api/mc/badges/age/npm/ultracite/7.12.2?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ultracite/7.9.0/7.12.2?slim=true) | --- ### Release Notes <details> <summary>biomejs/biome (@&#8203;biomejs/biome)</summary> ### [`v2.5.13`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2513) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.12...@biomejs/biome@2.5.13) ##### Patch Changes - [#&#8203;11379](https://github.com/biomejs/biome/pull/11379) [`07a0073`](https://github.com/biomejs/biome/commit/07a0073c1e1b1de323292968b8988cc6f79ec5c7) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added the nursery rule [`useLayeredStyles`](https://biomejs.dev/linter/rules/use-layered-styles/), which enforces that style rules are defined within a cascade layer and import rules to import its styles into a cascade layer. ```css /* Invalid */ @import 'foo.css'; .my-style { color: red; } /* Valid */ @import 'foo.css' layer(base); @layer base { .my-style { color: red; } } ``` - [#&#8203;11667](https://github.com/biomejs/biome/pull/11667) [`e997900`](https://github.com/biomejs/biome/commit/e997900c3eaf9d5efaf1ca12a067a962e1a04d0b) Thanks [@&#8203;devtechedge](https://github.com/devtechedge)! - Added the nursery rule [`useBetterDomTraversing`](https://biomejs.dev/linter/rules/use-better-dom-traversing), which prefers `.firstChild`, `.firstElementChild`, `.closest()`, and merged `.querySelector()` calls over positional DOM traversal. ```js element.childNodes[0]; element.children[0]; element.parentElement.parentElement; element.querySelector("a").querySelector("b"); ``` - [#&#8203;11620](https://github.com/biomejs/biome/pull/11620) [`20e513a`](https://github.com/biomejs/biome/commit/20e513af6fb0127854f4eb5cb9edee0f20d1b543) Thanks [@&#8203;jakeleventhal](https://github.com/jakeleventhal)! - Fixed [#&#8203;11610](https://github.com/biomejs/biome/issues/11610), [#&#8203;11611](https://github.com/biomejs/biome/issues/11611), [#&#8203;11612](https://github.com/biomejs/biome/issues/11612), [#&#8203;11615](https://github.com/biomejs/biome/issues/11615), and [#&#8203;11616](https://github.com/biomejs/biome/issues/11616): Biome no longer fully infers an imported generic declaration just to apply its type arguments, restoring type-aware lint performance for large libraries such as Zod. This improves [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing), and [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands). - [#&#8203;11657](https://github.com/biomejs/biome/pull/11657) [`e322040`](https://github.com/biomejs/biome/commit/e32204014687469e6c6f3684d32caf56311cc118) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7495](https://github.com/biomejs/biome/issues/7495): [`noUselessConstructor`](https://biomejs.dev/linter/rules/no-useless-constructor/) now ignores TypeScript constructors that forward at least one argument to `super`, preserving constructors that narrow the subclass's accepted parameter types. The exemption also applies when the parent and child signatures are identical; JavaScript and zero-argument forwarding behavior are unchanged. - [#&#8203;11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7076](https://github.com/biomejs/biome/issues/7076): [`useAriaPropsForRole`](https://biomejs.dev/linter/rules/use-aria-props-for-role) and [`useFocusableInteractive`](https://biomejs.dev/linter/rules/use-focusable-interactive) no longer report non-focusable elements with `role="separator"`. A separator with an explicit `tabIndex` or `tabindex` still requires `aria-valuenow`. - [#&#8203;11627](https://github.com/biomejs/biome/pull/11627) [`23aad6d`](https://github.com/biomejs/biome/commit/23aad6df8f71bd9b134633c43d2334771687d10d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6571](https://github.com/biomejs/biome/issues/6571) so Grit plugins can capture and inspect multiple named import specifiers. - [#&#8203;11631](https://github.com/biomejs/biome/pull/11631) [`00dbd3a`](https://github.com/biomejs/biome/commit/00dbd3a30489617d5bb55466006ac9977612a23b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Reduced unnecessary type inference when type-aware lint rules inspect members of namespace imports from libraries such as Zod. Fixed type inference so blanket re-exports do not expose default exports. - [#&#8203;11628](https://github.com/biomejs/biome/pull/11628) [`a2f8ff7`](https://github.com/biomejs/biome/commit/a2f8ff7a1eb01f5c91e7154937e17f761863e3bc) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noXorAsExponentiation`](https://biomejs.dev/linter/rules/no-xor-as-exponentiation/), which reports the bitwise XOR operator `^` between two decimal integer literals, where the exponentiation operator `**` was likely intended. ```js const kibibyte = 2 ^ 10; // 8, not 1024 ``` - [#&#8203;11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7192](https://github.com/biomejs/biome/issues/7192): [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) now considers compound assignments such as `??=` to read and use private class members. - [#&#8203;11676](https://github.com/biomejs/biome/pull/11676) [`840a52a`](https://github.com/biomejs/biome/commit/840a52ad14b027e21661a9121b316ccac139d736) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11672](https://github.com/biomejs/biome/issues/11672) and [#&#8203;11671](https://github.com/biomejs/biome/issues/11671) by disabling the experimental capitalized-call and effect-dependency checks in [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/), matching their exclusion from upstream's recommended lint preset. Valid calls such as `Intl.NumberFormat()` and captures of variables declared inside effects no longer produce these diagnostics. - [#&#8203;11660](https://github.com/biomejs/biome/pull/11660) [`49485ed`](https://github.com/biomejs/biome/commit/49485eda65813e5b7e2be68cdd56ffd90674f713) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11653](https://github.com/biomejs/biome/issues/11653): Astro template suppression comments (`{/* biome-ignore lint: reason */}`) now suppress matching HTML lint diagnostics on the following line when full HTML support is enabled. - [#&#8203;11664](https://github.com/biomejs/biome/pull/11664) [`9a73b9c`](https://github.com/biomejs/biome/commit/9a73b9cc4bb1000336dc25704546f4d63a9bb326) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/). - [#&#8203;11661](https://github.com/biomejs/biome/pull/11661) [`5341b3f`](https://github.com/biomejs/biome/commit/5341b3fb9c7bae8ce2426d32e6e72aed9637a82f) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7479](https://github.com/biomejs/biome/issues/7479). [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now treats Unicode escapes in identifiers as the same binding as their decoded spelling. - [#&#8203;11630](https://github.com/biomejs/biome/pull/11630) [`62e1fc5`](https://github.com/biomejs/biome/commit/62e1fc59621b6ab5c3988ae36b6591180e07d08f) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed the HTML formatter inserting whitespace between adjacent Svelte expressions when their combined length exceeds the line width. ```diff <span> - {head.median - base.median >= 0 ? "+" : "−"} - {formatMs(Math.abs(head.median - base.median))} + {head.median - base.median >= 0 ? "+" : "−"}{formatMs(Math.abs(head.median - base.median))} </span> ``` - [#&#8203;11658](https://github.com/biomejs/biome/pull/11658) [`ed4bfa4`](https://github.com/biomejs/biome/commit/ed4bfa4a1de63241a7c3586ff12d7f990cf84303) Thanks [@&#8203;fredrikblau](https://github.com/fredrikblau)! - Fixed [#&#8203;11644](https://github.com/biomejs/biome/issues/11644): [`useHeadingContent`](https://biomejs.dev/linter/rules/use-heading-content/) no longer reports headings that render their text with a directive: `set:html` and `set:text` in Astro files, `v-html` and `v-text` in Vue files. ```astro <h1 set:html={heading} /> <h2 set:text={heading}></h2> ``` ```vue <template> <h1 v-html="heading"></h1> <h2 v-text="heading"></h2> </template> ``` - [#&#8203;11613](https://github.com/biomejs/biome/pull/11613) [`47d7383`](https://github.com/biomejs/biome/commit/47d7383d049b36ff8eaba50912176928143dd9e9) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the performance of Biome Formatter up to \~50% in some cases. - [#&#8203;11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6974](https://github.com/biomejs/biome/issues/6974), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported TypeScript private constructor properties read through object destructuring from `this` as unused. - [#&#8203;11618](https://github.com/biomejs/biome/pull/11618) [`21a10cf`](https://github.com/biomejs/biome/commit/21a10cfcac4db8044e8bff6b24d9b1e197c2b343) Thanks [@&#8203;siketyan](https://github.com/siketyan)! - Fixed [#&#8203;11605](https://github.com/biomejs/biome/issues/11605): Type inference now infers the type of an unannotated callback parameter from the signature of the function the callback is passed to, and honours explicit type arguments on call expressions. This improves type-aware analysis for [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/), [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/), [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/), [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/), [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/), [`noUnsafePlusOperands`](https://biomejs.dev/linter/rules/no-unsafe-plus-operands/), [`noUselessTypeConversion`](https://biomejs.dev/linter/rules/no-useless-type-conversion/), [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/), [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/), [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/), [`useDisposables`](https://biomejs.dev/linter/rules/use-disposables/), [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/), [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/), [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing/), [`useRegexpExec`](https://biomejs.dev/linter/rules/use-regexp-exec/), and [`useStringStartsEndsWith`](https://biomejs.dev/linter/rules/use-string-starts-ends-with/). For example, `noFloatingPromises` can now detect Promises reached through such parameters: ```ts interface Context { doSomething(): Promise<void>; } declare function test(callback: (ctx: Context) => Promise<void>): void; test(async (ctx) => { ctx.doSomething(); // now reported as a floating promise }); ``` - [#&#8203;11698](https://github.com/biomejs/biome/pull/11698) [`b019982`](https://github.com/biomejs/biome/commit/b019982bfbf8a9db58bd16b1e5e1a241128540d4) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed parsing of unquoted CSS URLs beginning with `@` or `!`, such as `url(@/assets/icon.svg)` and `url(!font.woff2)`. Preserved escaped and non-ASCII whitespace in raw URLs during formatting. ```diff -background-image: url(image\); +background-image: url(image\ ); ``` - [#&#8203;11622](https://github.com/biomejs/biome/pull/11622) [`c23e4c7`](https://github.com/biomejs/biome/commit/c23e4c7e7a33d3f00863d80be663678af8c2a073) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added the nursery rule [`noUnsafeIframeSandbox`](https://biomejs.dev/linter/rules/no-unsafe-iframe-sandbox/), which reports `iframe` elements whose `sandbox` attribute combines `allow-scripts` and `allow-same-origin`, since that combination lets the embedded document remove its own sandboxing. ```jsx <iframe src="https://example.com" sandbox="allow-scripts allow-same-origin" /> ``` - [#&#8203;11606](https://github.com/biomejs/biome/pull/11606) [`de0528f`](https://github.com/biomejs/biome/commit/de0528f940ea41b798816e1923b2b51ffcd0b473) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the recommended [`noSvelteAtHtmlTags`](https://biomejs.dev/linter/rules/no-svelte-at-html-tags) nursery rule, which reports Svelte `{@html}` tags that render unescaped HTML. - [#&#8203;11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6782](https://github.com/biomejs/biome/issues/6782): GritQL plugins now match captured JSX component names against code snippets such as `React.Fragment`. - [#&#8203;11687](https://github.com/biomejs/biome/pull/11687) [`09d97d9`](https://github.com/biomejs/biome/commit/09d97d973b522c6bd95e6d26006cb4b3a221396d) Thanks [@&#8203;hori-design](https://github.com/hori-design)! - Fixed [#&#8203;11678](https://github.com/biomejs/biome/issues/11678): [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) no longer panics on files that contain non-ASCII characters. This bumps the React Compiler version. - [#&#8203;11595](https://github.com/biomejs/biome/pull/11595) [`a64d757`](https://github.com/biomejs/biome/commit/a64d7572d5684f3555be5dc02eb1d29a16f290dc) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery Vue-domain rule [`useVueBaseImport`](https://biomejs.dev/linter/rules/use-vue-base-import/) rule, which enforces importing Vue APIs from `vue` instead of internal `@vue/*` packages. - [#&#8203;11675](https://github.com/biomejs/biome/pull/11675) [`353cbae`](https://github.com/biomejs/biome/commit/353cbae47056f8e03b27d1d9b69e165b5b72f122) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/) silently producing no diagnostics in WebAssembly builds, including the playground. - [#&#8203;11625](https://github.com/biomejs/biome/pull/11625) [`ea20e5a`](https://github.com/biomejs/biome/commit/ea20e5a4640b4455cd12e0eb6ffaa590803c67a2) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Improved linting performance for large CSS and JSON files. - [#&#8203;11670](https://github.com/biomejs/biome/pull/11670) [`4969ee1`](https://github.com/biomejs/biome/commit/4969ee1d73b48615f46f024539cfdb847f07064d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7527](https://github.com/biomejs/biome/issues/7527): suppression actions for diagnostics emitted on comments are now inserted before the diagnostic comment. In particular, suppressing [`noTsIgnore`](https://biomejs.dev/linter/rules/no-ts-ignore/) now places the `biome-ignore` comment before `@ts-ignore`. - [#&#8203;11655](https://github.com/biomejs/biome/pull/11655) [`fd8fc74`](https://github.com/biomejs/biome/commit/fd8fc741ee2b77b3b127859fabc7a29b19e1fb0b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;8629](https://github.com/biomejs/biome/issues/8629), where [`noUnusedPrivateClassMembers`](https://biomejs.dev/linter/rules/no-unused-private-class-members/) incorrectly reported used private TypeScript method overload signatures as unused. - [#&#8203;11669](https://github.com/biomejs/biome/pull/11669) [`579f401`](https://github.com/biomejs/biome/commit/579f401b0a97760db99d64b97b2bc29ab20e3f8a) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Improved the performance of [`noExcessiveLinesPerFile`](https://biomejs.dev/linter/rules/no-excessive-lines-per-file/) when `skipBlankLines` is `false`. ### [`v2.5.12`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2512) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.11...@biomejs/biome@2.5.12) ##### Patch Changes - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro attribute expressions rejecting TypeScript and JSX syntax that is accepted in text expressions. ```astro <Component icon={<Icon />} count={total as number} onSelect={(e: Event) => e} /> ``` - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro attribute names being split on `:` and `.` inside an expression, such as `{x && <button x-on:keyup.enter={go} client:load.foo />}`. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed a bare `>` in the children of an Astro expression being treated as markup, such as `{x && <div>a > b</div>}`. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed HTML comments inside an Astro expression failing to parse. They are now read as trivia, wherever they appear among the children. ```astro {x && <div><!-- first -->text<!-- last --></div>} {cond && <a></a><!-- c --><b></b>} ``` - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed `is:raw` children inside an Astro expression being read as JSX, such as `{x && <div is:raw>{not js} < & text</div>}`. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed an apostrophe or quote in the text of a JSX element inside an Astro expression ending the expression early, such as `{items.map((i) => <li>it's {i}</li>)}`. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed the children of a `<script>` or `<style>` inside an Astro expression being read as JSX. Their contents are text, so braces and comparisons no longer have to be escaped. ```astro {cond && <style>a { color: red }</style>} {cond && <script>let x = {a: 1};</script>} ``` - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Added support for template literal attribute values inside an Astro expression, such as ``{x && <C data-x=`t${x}` />}``. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed unquoted attribute values being rejected inside an Astro expression, such as `{x && <a class=foo maxlength=255 href=/about>go</a>}`. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed a template literal nested inside `${}` breaking the rest of an Astro file, such as ``const href = `/blog${page === 0 ? '' : `/${page + 1}`}`;``. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed a quote inside a regex character class breaking the rest of an Astro file, such as `const unsafe = /[/"]/;`. - [#&#8203;11508](https://github.com/biomejs/biome/pull/11508) [`54f3a2e`](https://github.com/biomejs/biome/commit/54f3a2ea2765c80df11d04e47cd8da0354f5f7ca) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useFlatMathMinMax`](https://biomejs.dev/linter/rules/use-flat-math-min-max/). Because `Math.min()` and `Math.max()` accept any number of arguments, the rule reports unnecessary nested calls to the same method: ```js Math.max(Math.max(a, b), c); ``` The fix flattens this expression to `Math.max(a, b, c)`. - [#&#8203;11585](https://github.com/biomejs/biome/pull/11585) [`c5c8315`](https://github.com/biomejs/biome/commit/c5c8315cc2174b52834513d4c01edd09341e46cd) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;11475](https://github.com/biomejs/biome/issues/11475): `noUnresolvedImports` no longer reports Bun runtime built-in modules (`bun`, `bun:bundle`, `bun:ffi`, `bun:jsc`, `bun:sqlite`, `bun:test`). - [#&#8203;11368](https://github.com/biomejs/biome/pull/11368) [`52a57b3`](https://github.com/biomejs/biome/commit/52a57b374af947ffcba11f0dd97b3cb9676ce044) Thanks [@&#8203;Austin1serb](https://github.com/Austin1serb)! - Fixed [#&#8203;6830](https://github.com/biomejs/biome/issues/6830): Biome now reports a diagnostic for excessively deep syntax instead of overflowing the native stack while releasing the parsed tree. - [#&#8203;11596](https://github.com/biomejs/biome/pull/11596) [`1fc42ed`](https://github.com/biomejs/biome/commit/1fc42ed80a00e3ca86d44de8e1f66707061eb862) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noThisOutsideOfClass`](https://biomejs.dev/linter/rules/no-this-outside-of-class/). The rule reports `this` outside class members and TypeScript functions with an explicit `this` parameter. ```js function Person(name) { this.name = name; } ``` - [#&#8203;11555](https://github.com/biomejs/biome/pull/11555) [`2516335`](https://github.com/biomejs/biome/commit/25163350c44aee821d3aeac5b20569cd37d1ae31) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11529](https://github.com/biomejs/biome/issues/11529), where [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) missed unhandled Promise chains when the imported function's module belonged to an import cycle. Cyclic modules now preserve types for exports that do not participate in recursive type dependencies. - [#&#8203;11518](https://github.com/biomejs/biome/pull/11518) [`0fee70c`](https://github.com/biomejs/biome/commit/0fee70c6420140d62e9e9507ff3eda735077691b) Thanks [@&#8203;HarperZ9](https://github.com/HarperZ9)! - Fixed [#&#8203;11500](https://github.com/biomejs/biome/issues/11500): the formatter now prints the `declare` modifier before accessibility modifiers on class properties. `private declare readonly name: string` is now formatted as `declare private readonly name: string`, matching Prettier and TypeScript's canonical modifier order. - [#&#8203;11580](https://github.com/biomejs/biome/pull/11580) [`1277af2`](https://github.com/biomejs/biome/commit/1277af285ff5ab2e7a4deb07b32855c9caa7b770) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;5091](https://github.com/biomejs/biome/issues/5091): Biome no longer moves comments next to the `<` of a generic, which causes invalid TypeScript syntax: ```diff - Generic<// a comment + Generic< + // a comment ``` - [#&#8203;11577](https://github.com/biomejs/biome/pull/11577) [`42995d2`](https://github.com/biomejs/biome/commit/42995d2d19a937c44e9abbd400901bc6ec0dcaf5) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;4592](https://github.com/biomejs/biome/issues/4592). Biome no longer crashes while parsing malformed `delete` expressions. - [#&#8203;11590](https://github.com/biomejs/biome/pull/11590) [`67963b4`](https://github.com/biomejs/biome/commit/67963b4085558e414bc48bddb82618b7cc6d8fdf) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6427](https://github.com/biomejs/biome/issues/6427) so Grit plugins can use `function = ...` as a node argument. - [#&#8203;11600](https://github.com/biomejs/biome/pull/11600) [`a689cb5`](https://github.com/biomejs/biome/commit/a689cb5405885db94693e8ce39a22a53950cf2bf) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6644](https://github.com/biomejs/biome/issues/6644): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now recognizes all interface declarations in a TypeScript declaration-merging group when the interface is referenced. The following snippet no longer triggers the rule. ```ts interface Things { foo: string; } interface Things { bar: string; } export type Key = keyof Things; interface Things { baz: string; } ``` - [#&#8203;11591](https://github.com/biomejs/biome/pull/11591) [`d4a0716`](https://github.com/biomejs/biome/commit/d4a07167df43309f424dc906fc5d0dc80b5e208d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6615](https://github.com/biomejs/biome/issues/6615). [`noDuplicateProperties`](https://biomejs.dev/linter/rules/no-duplicate-properties/) no longer reports declarations nested in block at-rules as duplicates of declarations in their parent block. - [#&#8203;11492](https://github.com/biomejs/biome/pull/11492) [`f2a07aa`](https://github.com/biomejs/biome/commit/f2a07aadedd47034dccffd941935c71481b4c354) Thanks [@&#8203;santichausis](https://github.com/santichausis)! - Fixed [#&#8203;11454](https://github.com/biomejs/biome/issues/11454): [`noMisplacedAssertion`](https://biomejs.dev/linter/rules/no-misplaced-assertion/) now recognises `@fast-check/vitest`'s `test.prop(...)` (and `.concurrent.prop`, `.skip.prop`, etc.) as a test function, the same way it already recognises `test.each`. The JS formatter picks up the same recognition, so a curried `test.prop(...)(...)` call is now formatted with the regular breakable argument layout used for `test.each`/`test.for`, instead of the single-line-hugging layout used for plain `it`/`test` calls. For example, Biome no longer reports the assertion below as misplaced: ```js import { fc, test } from "@fast-check/vitest"; test.prop([fc.string()])("round-trips", (s) => { expect(s).toBe(s); }); ``` - [#&#8203;11589](https://github.com/biomejs/biome/pull/11589) [`65742b3`](https://github.com/biomejs/biome/commit/65742b3658ab08aed31be6afdfbb4d8d5a737c47) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;4928](https://github.com/biomejs/biome/issues/4928): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports a value declaration as unused when its merged namespace is referenced. - [#&#8203;11559](https://github.com/biomejs/biome/pull/11559) [`472dbc2`](https://github.com/biomejs/biome/commit/472dbc2c38ed1dbed6066fe26eac7ef97c79b05d) Thanks [@&#8203;levrik](https://github.com/levrik)! - Fixed a false positive in [`noVueDuplicateKeys`](https://biomejs.dev/linter/rules/no-vue-duplicate-keys/) where a `<script setup>` variable initialized from `props` was reported as a duplicate of the prop it derives from. Biome now exempts any variable whose initializer references `props`, instead of only recognizing `defineProps()` and `toRefs(props)`. For example, Biome no longer reports `foo` below as a duplicate key: ```vue <script setup> import { toRef } from 'vue'; const props = defineProps(['foo']); const foo = toRef(props, 'foo'); </script> ``` - [#&#8203;11594](https://github.com/biomejs/biome/pull/11594) [`6586ceb`](https://github.com/biomejs/biome/commit/6586cebec6182d37361ce42ca906ab190fd9a15b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6640](https://github.com/biomejs/biome/issues/6640). Biome no longer crashes when linting malformed `for...of` statements. - [#&#8203;11571](https://github.com/biomejs/biome/pull/11571) [`85b197d`](https://github.com/biomejs/biome/commit/85b197da722fc8d07cd10b8fa7e1271652ed5e26) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10838](https://github.com/biomejs/biome/issues/10838): [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) no longer corrupts JSX attributes when nested JSX elements also require sorting. - [#&#8203;11533](https://github.com/biomejs/biome/pull/11533) [`97e76c0`](https://github.com/biomejs/biome/commit/97e76c04cf19de45e63a22a9954c5077f45d4e6c) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11520](https://github.com/biomejs/biome/issues/11520), where the Biome scanner would start analysing dependencies multiple times, leading to long and unresponsive sessions. - [#&#8203;11564](https://github.com/biomejs/biome/pull/11564) [`18a0e1f`](https://github.com/biomejs/biome/commit/18a0e1f058df3c8434d98d700eef5949695cb8f6) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed the diagnostic range of [`noInferrableTypes`](https://biomejs.dev/linter/rules/no-inferrable-types/) so it now highlights only the type instead of including the leading `:` colon, spaces and comments. - [#&#8203;11540](https://github.com/biomejs/biome/pull/11540) [`124fdaa`](https://github.com/biomejs/biome/commit/124fdaa1dad40a1e5d485da13ca51064b0a40adb) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`#11537`](https://github.com/biomejs/biome/issues/11537): [`noShorthandPropertyOverrides`](https://biomejs.dev/linter/rules/no-shorthand-property-overrides/) now compares declarations only within the same block. The rule no longer reports `@supports` feature queries and correctly checks nested, `@keyframes`, and `@page` blocks. - [#&#8203;11532](https://github.com/biomejs/biome/pull/11532) [`7ceb0ee`](https://github.com/biomejs/biome/commit/7ceb0ee925461abd9afe17b12a09abc9c0b43c28) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11528](https://github.com/biomejs/biome/issues/11528): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports statement-level `await` expressions that handle Promise values, including overloaded calls returning Promise aliases. Awaited values that resolve to arrays of Promises remain reported because their element Promises are not handled by `await`. - [#&#8203;11474](https://github.com/biomejs/biome/pull/11474) [`3c6412e`](https://github.com/biomejs/biome/commit/3c6412e7f44b9aaac750844f9a5f7ff7c3aa0feb) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10241](https://github.com/biomejs/biome/issues/10241). Biome no longer reports unsupported text expression diagnostics for double-curly text in vanilla HTML, and the formatter preserves adjacent curly-brace text. - [#&#8203;11593](https://github.com/biomejs/biome/pull/11593) [`6c7fd27`](https://github.com/biomejs/biome/commit/6c7fd273848765547dba547e550fc319df7455a0) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noVueDeprecatedScopedSlots`](https://biomejs.dev/linter/rules/no-vue-deprecated-scoped-slots/). It reports deprecated `$scopedSlots` references in Vue templates and component objects, and offers an unsafe replacement with `$slots`. For example, Biome now reports `this.$scopedSlots.default` inside a Vue component. - [#&#8203;11440](https://github.com/biomejs/biome/pull/11440) [`b88f1ea`](https://github.com/biomejs/biome/commit/b88f1ea368c727ff8ebeddcaf9448f6ddc7c4878) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed the formatter crashing on an Astro or Svelte expression spanning several lines in a file with CRLF line endings, such as `<p>{a +\r\n b}</p>`. - [#&#8203;11581](https://github.com/biomejs/biome/pull/11581) [`f4e5ebb`](https://github.com/biomejs/biome/commit/f4e5ebb40e64d4488166bf0f2b7d8d96a6118016) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useModernMathApis`](https://biomejs.dev/linter/rules/use-modern-math-apis/). The rule reports legacy mathematical patterns that have direct modern `Math` equivalents. ```js Math.sqrt(a * a + b * b); ``` - [#&#8203;11597](https://github.com/biomejs/biome/pull/11597) [`a20f44a`](https://github.com/biomejs/biome/commit/a20f44a3eb2086e65a6d8077eb89ab81f4d73130) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added the nursery rule [`noBunModules`](https://biomejs.dev/linter/rules/no-bun-modules/), which forbids the use of Bun builtin modules (e.g. `bun:sqlite`, `bun:ffi`). - [#&#8203;11545](https://github.com/biomejs/biome/pull/11545) [`7d54688`](https://github.com/biomejs/biome/commit/7d54688ee89244af3b287402295340d1d35ca96e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11542](https://github.com/biomejs/biome/issues/11542): Biome now reports HTML comments between Svelte tag attributes as parse errors. - [#&#8203;11582](https://github.com/biomejs/biome/pull/11582) [`b6611dd`](https://github.com/biomejs/biome/commit/b6611dd5c1a54b80f181f4c0b5147a2c1c311dc9) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;3862](https://github.com/biomejs/biome/issues/3862). Biome now parses legacy Internet Explorer `filter` and `-ms-filter` values such as `progid:DXImageTransform...` and `alpha(opacity=40)`. - [#&#8203;11575](https://github.com/biomejs/biome/pull/11575) [`65da251`](https://github.com/biomejs/biome/commit/65da251b0f4da0680f7ccb8820ba428344018848) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the Tailwind parser's ability to recover from parsing failures. Whitespace now always allows the parser to recover and start parsing a new class. - [#&#8203;11576](https://github.com/biomejs/biome/pull/11576) [`0f78499`](https://github.com/biomejs/biome/commit/0f784998407970338481a1017279b9f17c43c61f) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;3515](https://github.com/biomejs/biome/issues/3515) and [#&#8203;10395](https://github.com/biomejs/biome/issues/10395), where Biome could corrupt Unicode characters while writing source received through standard input to standard output. Characters such as `⚠` and `✔` are now preserved. - [#&#8203;11539](https://github.com/biomejs/biome/pull/11539) [`0fca643`](https://github.com/biomejs/biome/commit/0fca643d22845c28e0e0b7375013155e3f80717f) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11512](https://github.com/biomejs/biome/issues/11512), where [`style/noDescendingSpecificity`](https://biomejs.dev/linter/rules/no-descending-specificity/) missed lower-specificity selectors after a later higher-specificity selector with the same tail selector. - [#&#8203;11544](https://github.com/biomejs/biome/pull/11544) [`040f867`](https://github.com/biomejs/biome/commit/040f86770cb830cd9ddaa827fd5b78fa16e7484c) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11541](https://github.com/biomejs/biome/issues/11541): formatting a Svelte render tag followed by an HTML comment no longer duplicates the comment. ```diff <div> {@render children?.()} <!-- comment --> - <!-- comment --> </div> ``` - [#&#8203;11565](https://github.com/biomejs/biome/pull/11565) [`ee69e0e`](https://github.com/biomejs/biome/commit/ee69e0e8a90e6231a3b208cda4b3e65ad8b2006a) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11525](https://github.com/biomejs/biome/issues/11525). Now the configuration schema correctly provides auto-completion for linter domains. - [#&#8203;11583](https://github.com/biomejs/biome/pull/11583) [`b19390c`](https://github.com/biomejs/biome/commit/b19390cb6ec276651365542387469c8b4634e0af) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11352](https://github.com/biomejs/biome/issues/11352): [`useExplicitLengthCheck`](https://biomejs.dev/linter/rules/use-explicit-length-check/) no longer reports `length`-like properties used as value-producing `||` fallbacks or optional chains, and it no longer offers fixes for value-producing `&&` checks or unsafe negations. - [#&#8203;11562](https://github.com/biomejs/biome/pull/11562) [`753e955`](https://github.com/biomejs/biome/commit/753e955afe7bcb360506795fed25697828a59772) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where the Biome Language Server would start with logging level set to debug. This would cause logs to grow exponentially in long sessions. - [#&#8203;11217](https://github.com/biomejs/biome/pull/11217) [`7d3ee9c`](https://github.com/biomejs/biome/commit/7d3ee9ccd5cf5df585ab3a17517a9514608a645a) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed handling of `biome-ignore format` suppression comments on TypeScript declared class properties with string literal names. ```ts class A { declare /* biome-ignore format: exercise suppression checking */ 'a-b': 0; } ``` - [#&#8203;11497](https://github.com/biomejs/biome/pull/11497) [`f5d7896`](https://github.com/biomejs/biome/commit/f5d7896f7115a2d57962471f6d7abfafddb07918) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the [`noInvalidFileInputAccept`](https://biomejs.dev/linter/rules/no-invalid-file-input-accept/) nursery rule. The rule reports invalid literal `accept` values on file inputs in JSX and HTML, and normalizes common mistakes. ```jsx <input type="file" accept="image/jpg" /> ``` - [#&#8203;11345](https://github.com/biomejs/biome/pull/11345) [`ac58958`](https://github.com/biomejs/biome/commit/ac58958135d79e790f0edee8ec18aaa16f5d9849) Thanks [@&#8203;jakeleventhal](https://github.com/jakeleventhal)! - Improved type inference performance by avoiding resolution of unused members in object arguments. - [#&#8203;11554](https://github.com/biomejs/biome/pull/11554) [`2d55931`](https://github.com/biomejs/biome/commit/2d559316e00764b0843d3d483d4a093fb566de57) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added the new nursery rule [`useReactNamingConvention`](https://biomejs.dev/linter/rules/use-react-naming-convention/), which enforces naming conventions for React values assigned from `createContext`, `useId`, and `useRef`. A value from `createContext` must be a PascalCase component name ending with `Context`, a value from `useId` must be named `id` or end with `Id`, and a value from `useRef` must be named `ref` or end with `Ref`. - [#&#8203;11491](https://github.com/biomejs/biome/pull/11491) [`1d6210b`](https://github.com/biomejs/biome/commit/1d6210b8ef6a2d2d83ea16e6fb95c124fd370690) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noUnmodifiedLoopCondition`](https://biomejs.dev/linter/rules/no-unmodified-loop-condition/), which reports variables in loop conditions that are never modified in the loop. ```js let node = getNode(); while (node) { process(node); } ``` ### [`v2.5.11`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2511) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.10...@biomejs/biome@2.5.11) ##### Patch Changes - [#&#8203;11499](https://github.com/biomejs/biome/pull/11499) [`9743d0c`](https://github.com/biomejs/biome/commit/9743d0ceae807757300e5b0ec66266125bc664c1) Thanks [@&#8203;scs0209](https://github.com/scs0209)! - Fixed [#&#8203;11496](https://github.com/biomejs/biome/issues/11496): [`useValidAnchor`](https://biomejs.dev/linter/rules/use-valid-anchor/) now treats Astro JSX shorthand attributes like `<a {href}>` as a valid `href`. - [#&#8203;11437](https://github.com/biomejs/biome/pull/11437) [`88f805e`](https://github.com/biomejs/biome/commit/88f805e19b67ab4c876e4fc4a8b4018bd03df20b) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed [#&#8203;9944](https://github.com/biomejs/biome/issues/9944): adjacent elements inside an Astro expression now parse as an implicit fragment instead of raising an error. ```astro {options.map(() => <div /> <div /> )} ``` - [#&#8203;11437](https://github.com/biomejs/biome/pull/11437) [`88f805e`](https://github.com/biomejs/biome/commit/88f805e19b67ab4c876e4fc4a8b4018bd03df20b) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro templates rejecting unclosed HTML void elements, such as `{cond && <br>}`. - [#&#8203;11507](https://github.com/biomejs/biome/pull/11507) [`e2fc036`](https://github.com/biomejs/biome/commit/e2fc03669886732ac9c768aa00f3ffae46241848) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11157](https://github.com/biomejs/biome/issues/11157): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports Vue `<script setup>` bindings used by CSS `v-bind()` as unused. - [#&#8203;11398](https://github.com/biomejs/biome/pull/11398) [`afc4615`](https://github.com/biomejs/biome/commit/afc4615079a72e0810f06186f78e5cb177a5638e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11389](https://github.com/biomejs/biome/issues/11389): Files passed through `--stdin-file-path` now use full HTML support for Astro, Svelte, and Vue when it is enabled. - [#&#8203;11526](https://github.com/biomejs/biome/pull/11526) [`372cd68`](https://github.com/biomejs/biome/commit/372cd68ba156efdc497017598a49e21484a3ada9) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [`noVueRefAsOperand`](https://biomejs.dev/linter/rules/no-vue-ref-as-operand/) to track Vue refs through declaration aliases and `toRefs()` properties, and to recognize `useTemplateRef()` results. The rule no longer reports false positives such as plain ref transfers, plain `toRefs()` property access, `defineModel()` modifiers, or the supported `.effect` member as operands. The refactor enabling these fixes also improves the performance of the rule. - [#&#8203;11458](https://github.com/biomejs/biome/pull/11458) [`a7cd286`](https://github.com/biomejs/biome/commit/a7cd2868c3d98fbc75174c5bf69fdcfacbe87304) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11436](https://github.com/biomejs/biome/issues/11436): GritQL snippets such as `export { $specifiers } from $source` now match named re-exports with aliases, inline `type` modifiers, and multiple specifiers. - [#&#8203;11515](https://github.com/biomejs/biome/pull/11515) [`382b15d`](https://github.com/biomejs/biome/commit/382b15d5e0f9e2a75604fec1f15ad342628c99c7) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11390](https://github.com/biomejs/biome/issues/11390), where `noFloatingPromises` performed expensive full type inference for calls to non-Promise methods declared on third-party TypeScript classes. The rule now classifies those calls using targeted type information. - [#&#8203;11516](https://github.com/biomejs/biome/pull/11516) [`6f40e82`](https://github.com/biomejs/biome/commit/6f40e8224afc58737626d997c0ea779e2b37baca) Thanks [@&#8203;levrik](https://github.com/levrik)! - Fixed [`noVueRefAsOperand`](https://biomejs.dev/linter/rules/no-vue-ref-as-operand/) so it no longer reports a callback parameter (e.g. from `.find()`, `.map()`) as an unwrapped ref value just because it's nested inside a `ref()`, `computed()`, or similar call. ```js const result = computed(() => list.find((item) => item.label === "a")); ``` Previously, `item` here was incorrectly treated as a ref value because the rule attributed it to the outer `computed()` call. - [#&#8203;11495](https://github.com/biomejs/biome/pull/11495) [`496268d`](https://github.com/biomejs/biome/commit/496268d1470b6a4cd52bff03d37899c4bb7f77ab) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [`useGraphqlNamingConvention`](https://biomejs.dev/linter/rules/use-graphql-naming-convention/) so it no longer reports GraphQL enum value definitions with comments & descriptions and now displays a more accurate diagnostic range. - [#&#8203;11407](https://github.com/biomejs/biome/pull/11407) [`6ef52b0`](https://github.com/biomejs/biome/commit/6ef52b02fc07e23de7ad498d853aaf2c825717fd) Thanks [@&#8203;1678092075](https://github.com/1678092075)! - Fixed [#&#8203;11214](https://github.com/biomejs/biome/issues/11214): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports type parameters declared by non-default function overload signatures that have an implementation. - [#&#8203;11322](https://github.com/biomejs/biome/pull/11322) [`5c353e6`](https://github.com/biomejs/biome/commit/5c353e6c85a40807e2710684da807f8757ee650c) Thanks [@&#8203;jp-knj](https://github.com/jp-knj)! - Added a new nursery rule `noAstroSetHtmlDirective`, which disallows Astro's `set:html` directive because untrusted content can introduce cross-site scripting vulnerabilities. For example, the following snippet triggers the rule: ```astro <div set:html={content} /> ``` - [#&#8203;11462](https://github.com/biomejs/biome/pull/11462) [`18883b7`](https://github.com/biomejs/biome/commit/18883b7dafb8f9581534508fdd5b1e34632f2724) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10776](https://github.com/biomejs/biome/issues/10776): [`useVueHyphenatedAttributes`](https://biomejs.dev/linter/rules/use-vue-hyphenated-attributes/) no longer reports lowercase attribute names containing punctuation, such as `pt:header:data-test-id` and `some_attr`. - [#&#8203;11476](https://github.com/biomejs/biome/pull/11476) [`3270ca4`](https://github.com/biomejs/biome/commit/3270ca4560a28eee92564b9ef64f778972cbf3ab) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10330](https://github.com/biomejs/biome/issues/10330): Vue interpolation delimiters now stay attached to whitespace-sensitive element boundaries and adjacent inline siblings, wrapping their expression when needed to fit the configured line width. Interpolations followed by text now also converge after one formatting pass. ```diff -<v-btn v-if="store.state.user" variant="text" to="/my-rooms" - >{{ $t("nav.my-rooms") }}</v-btn -> +<v-btn v-if="store.state.user" variant="text" to="/my-rooms">{{ + $t("nav.my-rooms") +}}</v-btn> ``` - [#&#8203;11191](https://github.com/biomejs/biome/pull/11191) [`3e5367f`](https://github.com/biomejs/biome/commit/3e5367f13de6c8cb80070544774c9935cac7d649) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Added the nursery rule [`noUndeclaredCustomProperties`](https://biomejs.dev/linter/rules/no-undeclared-custom-properties/), which reports references to custom properties that are not defined in available CSS, static HTML-like `style` attributes, or JSX string `style` attributes. For example, the following snippet triggers the rule: ```css a { color: var(--undefined-color); } ``` - [#&#8203;11435](https://github.com/biomejs/biome/pull/11435) [`7754894`](https://github.com/biomejs/biome/commit/7754894ffaaaa2ab0b281789d5ceae8f333d61a4) Thanks [@&#8203;levrik](https://github.com/levrik)! - Fixed: Variables and imports used as custom Vue directives are no longer reported as unused. For example: ```vue <script setup> const vHighlight = { mounted: (element) => { element.style.color = "red"; }, }; </script> <template> <p v-highlight>Hello</p> </template> ``` - [#&#8203;11501](https://github.com/biomejs/biome/pull/11501) [`e6acded`](https://github.com/biomejs/biome/commit/e6acdedf09c452371670aaaffd0b55206019d1e6) Thanks [@&#8203;aminya](https://github.com/aminya)! - Improved the performance of [`useArraySortCompare`](https://biomejs.dev/linter/rules/use-array-sort-compare/) by skipping type inference for calls to unrelated methods. - [#&#8203;11467](https://github.com/biomejs/biome/pull/11467) [`66b282c`](https://github.com/biomejs/biome/commit/66b282cb70cd61b7606ce1658482b9fe082e37e6) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11464](https://github.com/biomejs/biome/issues/11464): Biome now parses parenthesized object literals returned from arrow functions when they contain a conditional expression and a nested arrow function. - [#&#8203;11456](https://github.com/biomejs/biome/pull/11456) [`db9aa2a`](https://github.com/biomejs/biome/commit/db9aa2a3d936372cbe3ee87687ad25816c9d75ae) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10278](https://github.com/biomejs/biome/issues/10278): Marked the fix for [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) as unsafe by default. - [#&#8203;11502](https://github.com/biomejs/biome/pull/11502) [`652aedb`](https://github.com/biomejs/biome/commit/652aedbdcba8ccb45ccecbce506c90a337f2d64c) Thanks [@&#8203;levrik](https://github.com/levrik)! - `noGlobalAssign` no longer reports assignments to a Vue `<script setup>` binding from a template expression, when the binding's name happens to match a built-in global (e.g. `open`, `parent`, `top`). For example, this no longer triggers a diagnostic: ```vue <script setup> const open = defineModel(); </script> <template> <button @click="open = !open">Toggle</button> </template> ``` ### [`v2.5.10`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#2510) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.9...@biomejs/biome@2.5.10) ##### Patch Changes - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting JavaScript comments between attributes. ```astro <div /* block comment */ class="something"></div> <Component /* c */ client:load /> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed a bare `<` in Astro text being treated as the start of a tag, such as `<p>5 < 6 and 7 > 6</p>`. As in HTML, a `<` that cannot open a tag is text and needs no escaping. - [#&#8203;11438](https://github.com/biomejs/biome/pull/11438) [`3133ffa`](https://github.com/biomejs/biome/commit/3133ffa9ae6beaa3c4464edac60de47d5c6f6426) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed [#&#8203;8294](https://github.com/biomejs/biome/issues/8294): an Astro expression holding only a comment is no longer reported as a parse error, which also stopped the whole file from being formatted. ```astro <div>{/* a note */}</div> <div class={/* a note */}>x</div> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed [#&#8203;9165](https://github.com/biomejs/biome/issues/9165): an empty Astro expression such as `<div>{}</div>` no longer fails to parse. Astro renders `{}` as nothing. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro expressions containing a comment failing to parse. ```astro <div>{/* block comment */ x}</div> <div>{/* only a comment */}</div> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Added support for Astro's fragment shorthand. ```astro <> <p>a</p> </> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed an Astro frontmatter block being cut short by a closing tag inside a string or comment. ```astro --- const a = "</script>"; // </script> in a comment --- ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed `---` being read as an Astro frontmatter fence when markup precedes it. Astro only recognizes frontmatter at the very start of a file, so a file opening with a comment now has no frontmatter, and its `---` lines are content. ```astro <!-- c --> --- this is text, not frontmatter --- ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed an Astro frontmatter block ending early on a line that merely starts with a dash. ```astro --- --count; --- ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed the children of an Astro element carrying `is:raw` being parsed as markup instead of raw text. This now also covers `<script>` and `<style>`, whose contents Astro emits verbatim rather than processing, so they are no longer linted as JavaScript or CSS. ```astro <article is:raw><% awesome %></article> <script is:raw>{{ mustache }}</script> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting attribute names that start with a colon, such as `:href`. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed the Astro parser failing to recover from a malformed closing tag such as `<div></{<//`, so that a later mistake is reported where it happens rather than cascading. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed `{` inside an Astro `<math>` element opening an expression. MathML is foreign content where Astro parses no expressions, so LaTeX such as `R^{2x}` now survives as text. `<svg>` is unaffected. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed `{{` at the start of an Astro expression being read as an interpolation. Astro has no `{{ }}` syntax, so `{{ a: 1 }}` and `<Comp a={{ b: 1 }} />` are object literals. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed expressions inside an Astro `<pre>` or `<textarea>` being read as raw text. Astro parses both as ordinary elements, so their markup and interpolations are now parsed, and a variable used only inside one is no longer reported as unused. ```astro <pre>{value}</pre> <textarea><div>{value}</div></textarea> ``` - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Added support for template literal attribute values in Astro, such as ``<div class=`a ${b} c`>``. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed Astro rejecting HTML5 unquoted attribute values that contain `` ` ``, `=`, `'` or `"`, such as `<a href=a=b>` and `<a href=a'b>`. - [#&#8203;11393](https://github.com/biomejs/biome/pull/11393) [`dec5a8f`](https://github.com/biomejs/biome/commit/dec5a8fadcb565867526e51da0895c2be27400bb) Thanks [@&#8203;1678092075](https://github.com/1678092075)! - Fixed [#&#8203;11207](https://github.com/biomejs/biome/issues/11207): [`useStrictMode`](https://biomejs.dev/linter/rules/use-strict-mode/) no longer reports Vue event handlers such as `@click="count++"`. - [#&#8203;11431](https://github.com/biomejs/biome/pull/11431) [`c065f99`](https://github.com/biomejs/biome/commit/c065f995909d16cbf98c247a280a48c156aeb61f) Thanks [@&#8203;levrik](https://github.com/levrik)! - Fixed [#&#8203;11429](https://github.com/biomejs/biome/issues/11429): Variables and imports used by Vue same-name bindings such as `:disabled` or `v-bind:disabled` are no longer reported as unused. - [#&#8203;11409](https://github.com/biomejs/biome/pull/11409) [`405dedb`](https://github.com/biomejs/biome/commit/405dedb0ff65dd29927faf587f6542e3c29db248) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a memory leak in the LSP server where memory usage kept growing over long editor sessions. - [#&#8203;11422](https://github.com/biomejs/biome/pull/11422) [`a51eff7`](https://github.com/biomejs/biome/commit/a51eff7f7ca71e8786a2f0db1d560455b83ce21c) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11416](https://github.com/biomejs/biome/issues/11416): Biome no longer crashes when parsing incomplete `{let}` or `{const}` declarations in Svelte files. - [#&#8203;11378](https://github.com/biomejs/biome/pull/11378) [`34b715c`](https://github.com/biomejs/biome/commit/34b715cb417d482bfb4630c05a576b748c8faa8b) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added extra rule sources from `@eslint/css`. `biome migrate eslint` detects rules in your eslint configurations more reliably. - [#&#8203;11403](https://github.com/biomejs/biome/pull/11403) [`8f7786f`](https://github.com/biomejs/biome/commit/8f7786ff62aef61cf75a91e1604cd380456a60f4) Thanks [@&#8203;Princesseuh](https://github.com/Princesseuh)! - Fixed `{#`, `{/`, `{:` and `{@` being read as Svelte block openings in every HTML-like file. They are now Svelte-only, so in HTML, Vue and Angular files a sequence such as `{#if x}` is ordinary text instead of a parse error. - [#&#8203;11443](https://github.com/biomejs/biome/pull/11443) [`8d45229`](https://github.com/biomejs/biome/commit/8d452293d04272c876b0414292540645cfea87e4) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11390](https://github.com/biomejs/biome/issues/11390): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer performs unnecessary type inference on call arguments when checking methods of non-generic class instances created with `new`. - [#&#8203;11425](https://github.com/biomejs/biome/pull/11425) [`9c2667b`](https://github.com/biomejs/biome/commit/9c2667ba2010441054bc0b54a1a810e851207560) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;6426](https://github.com/biomejs/biome/issues/6426): GritQL plugins now match and rewrite metavariables embedded in quoted strings. - [#&#8203;11441](https://github.com/biomejs/biome/pull/11441) [`00317c3`](https://github.com/biomejs/biome/commit/00317c353a65214d8f4cb0f2d930d7c4e1f305dd) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved performance of [`useNamedCaptureGroup`](https://biomejs.dev/linter/rules/use-named-capture-group/), [`noMisplacedAssertion`](https://biomejs.dev/linter/rules/no-misplaced-assertion/), [`noSkippedTests`](https://biomejs.dev/linter/rules/no-skipped-tests/), [`noExportsInTest`](https://biomejs.dev/linter/rules/no-exports-in-test/), [`noDuplicateTestHooks`](https://biomejs.dev/linter/rules/no-duplicate-test-hooks/), [`noIdenticalTestTitle`](https://biomejs.dev/linter/rules/no-identical-test-title/), [`useTestHooksInOrder`](https://biomejs.dev/linter/rules/use-test-hooks-in-order/), and [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top/). ### [`v2.5.9`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#259) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.8...@biomejs/biome@2.5.9) ##### Patch Changes - [#&#8203;11321](https://github.com/biomejs/biome/pull/11321) [`41386f3`](https://github.com/biomejs/biome/commit/41386f38935b299f1a1f759a2c7fdd5c2050bded) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11315](https://github.com/biomejs/biome/issues/11315): The CSS parser now recovers at declaration boundaries after bogus declarations, allowing subsequent valid declarations to be parsed. - [#&#8203;11248](https://github.com/biomejs/biome/pull/11248) [`57b197e`](https://github.com/biomejs/biome/commit/57b197e6d5a2432ff6904afff24125e4d8ec01cd) Thanks [@&#8203;yanthomasdev](https://github.com/yanthomasdev)! - Expanded the environment variable metadata used by `biome rage` to include `BIOME_BINARY`, `BIOME_LOG_FILE`, and `RUST_BACKTRACE` as well as reworded explanations for better readability. - [#&#8203;11377](https://github.com/biomejs/biome/pull/11377) [`a8798ea`](https://github.com/biomejs/biome/commit/a8798ea9f2569fab4524704c99a8e2fe45c2ca32) Thanks [@&#8203;Netail](https://github.com/Netail)! - Added a new nursery rule [`useNamedLayer`](https://biomejs.dev/linter/rules/use-named-layer) which disallows anonymous cascade layers. ```css @layer { a { color: red; } } ``` - [#&#8203;11327](https://github.com/biomejs/biome/pull/11327) [`6771cf5`](https://github.com/biomejs/biome/commit/6771cf5bd2e64f256468a33b811adec8e793d933) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - The HTML formatter now preserves meaningful blank lines in HTML, including spacing after elements with trailing spaces and blank lines between comment groups. ```diff <div> <!-- first group --> + <!-- second group --> </div> ``` - [#&#8203;10312](https://github.com/biomejs/biome/pull/10312) [`ba8aa18`](https://github.com/biomejs/biome/commit/ba8aa183371b3080691ed80e5a9f6f0239cf451b) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTailwindShorthandClasses`](https://biomejs.dev/linter/rules/use-tailwind-shorthand-classes/), which suggests shorter Tailwind utility classes. For example, the rule suggests replacing `w-4 h-4` with `size-4`. - [#&#8203;11333](https://github.com/biomejs/biome/pull/11333) [`715e0cd`](https://github.com/biomejs/biome/commit/715e0cd1b3e6c88d153554901a659378c728e408) Thanks [@&#8203;kkkhs](https://github.com/kkkhs)! - Fixed [#&#8203;11328](https://github.com/biomejs/biome/issues/11328): `lint/nursery/useExpect` now recognizes Vitest Browser Mode `expect.element()` calls as assertions. - [#&#8203;11343](https://github.com/biomejs/biome/pull/11343) [`9b98211`](https://github.com/biomejs/biome/commit/9b982113dba8b37c163662d59611ecba0fc02f5a) Thanks [@&#8203;johncarmack1984](https://github.com/johncarmack1984)! - Fixed [#&#8203;11311](https://github.com/biomejs/biome/issues/11311): the CSS parser now accepts Tailwind container-query variant names in `@variant`, such as `@xl` and `@max-xl`. These previously produced a parse error and a [`noUnknownAtRules`](https://biomejs.dev/linter/rules/no-unknown-at-rules/) diagnostic. ```css @variant @xl { div { background: red; } } ``` - [#&#8203;11220](https://github.com/biomejs/biome/pull/11220) [`3e8c488`](https://github.com/biomejs/biome/commit/3e8c4887c4ef87df45f56aafa4fbc5f497dae42f) Thanks [@&#8203;santichausis](https://github.com/santichausis)! - Fixed [#&#8203;9541](https://github.com/biomejs/biome/issues/9541): [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/), [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/), and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) now correctly recognise exported variables and functions declared in one embedded `<script>` block as usable from a sibling `<script>` block, in Svelte's `<script module>`/`<script>` pair and Vue's non-`setup` `<script>` blocks. For example, Biome no longer reports `greet` as undeclared in the following Svelte component: ```svelte <script module> export function greet() { console.log("Hello!"); } </script> <script> greet(); </script> ``` - [#&#8203;11300](https://github.com/biomejs/biome/pull/11300) [`36430eb`](https://github.com/biomejs/biome/commit/36430ebb9679d1ca5d9c231a36b709a4b5eab9b3) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed the HTML formatter's whitespace handling for `marquee`, `noscript`, `video`, `audio`, and `object` elements. ```diff - <marquee behavior="alternate"> This text will bounce </marquee> + <marquee behavior="alternate">This text will bounce</marquee> ``` - [#&#8203;11299](https://github.com/biomejs/biome/pull/11299) [`6559e6c`](https://github.com/biomejs/biome/commit/6559e6ced6d4ebe8c26e818931df15d02829130d) Thanks [@&#8203;jp-knj](https://github.com/jp-knj)! - Added the nursery rule `useAstroClientOnlyDirectiveValue`, which reports Astro `client:only` directives without an initializer. For example, `<Component client:only />` triggers the rule. - [#&#8203;11365](https://github.com/biomejs/biome/pull/11365) [`7529811`](https://github.com/biomejs/biome/commit/7529811358079edb5a2a9d4a5f67a9f639a63f3a) Thanks [@&#8203;MHJahanbakhsh](https://github.com/MHJahanbakhsh)! - Fixed [#&#8203;11229](https://github.com/biomejs/biome/issues/11229): The [`useGenericFontNames`](https://biomejs.dev/linter/rules/use-generic-font-names/) rule now treats `math` as a valid generic font family. - [#&#8203;11346](https://github.com/biomejs/biome/pull/11346) [`674f5f4`](https://github.com/biomejs/biome/commit/674f5f4b4e6923b6c7fd12d76e366f82ffe6405b) Thanks [@&#8203;Jayllyz](https://github.com/Jayllyz)! - Fixed [#&#8203;11335](https://github.com/biomejs/biome/issues/11335): [`noComponentHookFactories`](https://biomejs.dev/linter/rules/no-component-hook-factories/) now reports a `use`-prefixed variable only when a function is assigned to it directly. ```js function factory() { const useColors = true; // no longer reported const useStore = createStore({ count: 0 }); // no longer reported const useData = () => useState(null); // still reported return useColors; } ``` - [#&#8203;11334](https://github.com/biomejs/biome/pull/11334) [`c87c46a`](https://github.com/biomejs/biome/commit/c87c46ab350a40fd38b2288887e2d6e930a2d62d) Thanks [@&#8203;zkasuran](https://github.com/zkasuran)! - Fixed [#&#8203;11317](https://github.com/biomejs/biome/issues/11317): [`noSvgWithoutTitle`](https://biomejs.dev/linter/rules/no-svg-without-title/) no longer reports an `svg` that uses the boolean shorthand `aria-hidden` (equivalent to `aria-hidden={true}` in React). - [#&#8203;11364](https://github.com/biomejs/biome/pull/11364) [`13853b1`](https://github.com/biomejs/biome/commit/13853b16685d96bfb9158de7d5f4c101d114ba32) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a bug where [`useJsxKeyInIterable`](https://biomejs.dev/linter/rules/use-jsx-key-in-iterable/) incorrectly flagged Astro files. - [#&#8203;11321](https://github.com/biomejs/biome/pull/11321) [`41386f3`](https://github.com/biomejs/biome/commit/41386f38935b299f1a1f759a2c7fdd5c2050bded) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11315](https://github.com/biomejs/biome/issues/11315): Invalid CSS declarations in HTML `style` attributes now produce parser diagnostics instead of causing a panic. - [#&#8203;11325](https://github.com/biomejs/biome/pull/11325) [`67c3bf0`](https://github.com/biomejs/biome/commit/67c3bf01131c0c079fa058eef96dc28d52c2c59f) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed HTML text wrapping to account for the width of an adjacent closing tag, avoiding lines that exceed the configured width when the final word and tag must move together. ```diff <a-long-long-long-element - >foo bar foo bar foo bar foo bar foo bar foo bar foo bar</a-long-long-long-element + >foo bar foo bar foo bar foo bar foo bar foo + bar</a-long-long-long-element > ``` - [#&#8203;11367](https://github.com/biomejs/biome/pull/11367) [`fe5b5d4`](https://github.com/biomejs/biome/commit/fe5b5d41c863d5e2f3b58570e15f483c189d2825) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed TypeScript `compilerOptions.paths` resolution when mapping targets omit `./`. Biome now resolves these targets relative to their configured path base. - [#&#8203;11316](https://github.com/biomejs/biome/pull/11316) [`17e48d6`](https://github.com/biomejs/biome/commit/17e48d6088f23ec30a1e17e315b52369f1e4836c) Thanks [@&#8203;wanxiankai](https://github.com/wanxiankai)! - Fixed [#&#8203;11289](https://github.com/biomejs/biome/issues/11289): the safe fix for [`noExtraBooleanCast`](https://biomejs.dev/linter/rules/no-extra-boolean-cast/) now preserves parentheses around nested conditional expressions. - [#&#8203;11254](https://github.com/biomejs/biome/pull/11254) [`d25d113`](https://github.com/biomejs/biome/commit/d25d113aed23ca9b5ee9b7cdedb208d8a0b2cd00) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;11242](https://github.com/biomejs/biome/issues/11242): Biome no longer crashes with an access violation when analysing files on Windows ARM64. - [#&#8203;11221](https://github.com/biomejs/biome/pull/11221) [`85aac73`](https://github.com/biomejs/biome/commit/85aac73d32a5f4a0db7bab3ebd195e35b32d513d) Thanks [@&#8203;freeatnet](https://github.com/freeatnet)! - Added the nursery rule [`noUnsafeTypeAssertion`](https://biomejs.dev/linter/rules/no-unsafe-type-assertion/), which disallows TypeScript type assertions while allowing const assertions. ```ts const value = input as SomeType; ``` - [#&#8203;11314](https://github.com/biomejs/biome/pull/11314) [`7ffb677`](https://github.com/biomejs/biome/commit/7ffb677159c96f072a508e58bfad26ca9c301ac4) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11310](https://github.com/biomejs/biome/issues/11310): Restored the performance of [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) and [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) when analyzed expressions share deep imported type paths. - [#&#8203;11356](https://github.com/biomejs/biome/pull/11356) [`6cd3263`](https://github.com/biomejs/biome/commit/6cd32636f463551b8dfe46aeefb1191d437b4694) Thanks [@&#8203;johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands modifiers on bare utilities (`@container/sidebar`, `shadow/50`). - [#&#8203;11318](https://github.com/biomejs/biome/pull/11318) [`76059e9`](https://github.com/biomejs/biome/commit/76059e9f03f5962a18f3569714f8f207ef7c1d91) Thanks [@&#8203;johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands container-query variants (`@sm:`, `@max-lg:`, `@min-[400px]:`) and child and descendant variants (`*:`, `**:`). - [#&#8203;11357](https://github.com/biomejs/biome/pull/11357) [`faa2074`](https://github.com/biomejs/biome/commit/faa2074472bc0f4a11f4e80cb4d2b0e55883226a) Thanks [@&#8203;johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now accepts the legacy leading `!` important marker (`!flex`, `hover:!p-4`). - [#&#8203;11344](https://github.com/biomejs/biome/pull/11344) [`f34e15c`](https://github.com/biomejs/biome/commit/f34e15c946511d998c01b6c6e410f0c220c2943e) Thanks [@&#8203;johncarmack1984](https://github.com/johncarmack1984)! - The Tailwind parser now understands combinator selectors in arbitrary variants (`has-[>svg]:`, `has-[+p]:`), modifiers on variants (`group-hover/menu:`, `@sm/main:`), and arbitrary container-query sizes (`@[400px]:`). - [#&#8203;11324](https://github.com/biomejs/biome/pull/11324) [`2f5d452`](https://github.com/biomejs/biome/commit/2f5d452015ee80a02d4e50c4bb2ba930092048a2) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed HTML formatting that inserted rendered whitespace between an element and touching text when the line wrapped. ```diff <div> - before<meter value=".5"></meter> - after + before<meter value=".5"></meter + >after </div> ``` - [#&#8203;11312](https://github.com/biomejs/biome/pull/11312) [`e65f07e`](https://github.com/biomejs/biome/commit/e65f07e06342c7d8d74b98ff219d72c7e081b4f2) Thanks [@&#8203;xosnos](https://github.com/xosnos)! - Added a new nursery rule [`useControlLabel`](https://biomejs.dev/linter/rules/use-control-label/) for both HTML and JSX, which reports interactive control elements (`button`, `menuitem`) without an accessible label. ```jsx <button /> ``` - [#&#8203;11364](https://github.com/biomejs/biome/pull/11364) [`13853b1`](https://github.com/biomejs/biome/commit/13853b16685d96bfb9158de7d5f4c101d114ba32) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed SVG parsing for files with an XML declaration followed by a `PUBLIC` doctype, such as `<?xml version="1.0"?><!DOCTYPE svg PUBLIC "a" "b">`. - [#&#8203;11301](https://github.com/biomejs/biome/pull/11301) [`610ee28`](https://github.com/biomejs/biome/commit/610ee282989ac73908e0f8bd6e49bc40cccfef77) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed parent tag wrapping when an HTML element starts or ends with a block-like or hidden child such as `source`, `track`, or `param`. ```diff - <video src="brave.webm"><track kind="subtitles" src="brave.en.vtt"></video> + <video src="brave.webm"> + <track kind="subtitles" src="brave.en.vtt"> + </video> ``` ### [`v2.5.8`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#258) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.7...@biomejs/biome@2.5.8) ##### Patch Changes - [#&#8203;10710](https://github.com/biomejs/biome/pull/10710) [`0a0fbc1`](https://github.com/biomejs/biome/commit/0a0fbc15d67c410c80dfae398903f845544fcd65) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`useReactCompiler`](https://biomejs.dev/linter/rules/use-react-compiler/), which reports diagnostics from React Compiler lint mode. - [#&#8203;11251](https://github.com/biomejs/biome/pull/11251) [`ea9dd8a`](https://github.com/biomejs/biome/commit/ea9dd8a93e65f849840415e8e26cd668aa1af913) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved performance of [`noImportCycles`](https://biomejs.dev/linter/rules/no-import-cycles/). - [#&#8203;11247](https://github.com/biomejs/biome/pull/11247) [`52b44d6`](https://github.com/biomejs/biome/commit/52b44d6795741d051bf703bd69c6cb447af8fd1d) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noSvelteLegacyConst`](https://biomejs.dev/linter/rules/no-svelte-legacy-const/), which disallows legacy Svelte `{@const}` tags and recommends declaration tags with `$derived()`. Invalid: ```svelte {#each boxes as box} {@const area = box.width * box.height} <p>{area}</p> {/each} ``` Valid: ```svelte {#each boxes as box} {const area = $derived(box.width * box.height)} <p>{area}</p> {/each} ``` - [#&#8203;11252](https://github.com/biomejs/biome/pull/11252) [`d5f5704`](https://github.com/biomejs/biome/commit/d5f570414fdcdddf62372e35c05f6dababad9287) Thanks [@&#8203;Turtle-Hwan](https://github.com/Turtle-Hwan)! - Fixed [#&#8203;11250](https://github.com/biomejs/biome/issues/11250): [`useAwait`](https://biomejs.dev/linter/rules/use-await/) no longer reports async functions that contain an `await using` declaration. - [#&#8203;11143](https://github.com/biomejs/biome/pull/11143) [`6be7be1`](https://github.com/biomejs/biome/commit/6be7be1b147d7b4352ff5625a78bd54a48958950) Thanks [@&#8203;vznh](https://github.com/vznh)! - Fixed [#&#8203;11017](https://github.com/biomejs/biome/issues/11017): [`noUselessUndefined`](https://biomejs.dev/linter/rules/no-useless-undefined/) no longer reports `return undefined` when the enclosing function has a return type annotation other than `undefined` or `void`. - [#&#8203;11234](https://github.com/biomejs/biome/pull/11234) [`caefe39`](https://github.com/biomejs/biome/commit/caefe393c66340914c481f7ccfc82979cf76b61b) Thanks [@&#8203;subotac](https://github.com/subotac)! - Fixed [#&#8203;11228](https://github.com/biomejs/biome/issues/11228): CSS block comments between a declaration colon and value now preserve their source indentation. ```diff :root { --font-stack: -/* comment */ + /* comment */ system-ui; } ``` - [#&#8203;11285](https://github.com/biomejs/biome/pull/11285) [`bca1f73`](https://github.com/biomejs/biome/commit/bca1f73d939423056337bfd0a42cbdcb66bb1e3f) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed [#&#8203;11280](https://github.com/biomejs/biome/issues/11280): CSS formatting keeps comments inside functional pseudo-classes and pseudo-elements instead of moving them before the function name. ```diff -:/* comment */ where(div) {} +:where(/* comment */ div) {} ``` - [#&#8203;11080](https://github.com/biomejs/biome/pull/11080) [`af16a0b`](https://github.com/biomejs/biome/commit/af16a0bf884c48bad2caab70e7930096e81e1c99) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - HTML `style` attribute values are now parsed as CSS. All Biome CSS lint rules are applied to the `style` attributes. - [#&#8203;11195](https://github.com/biomejs/biome/pull/11195) [`6a85588`](https://github.com/biomejs/biome/commit/6a85588578725195625281984a47c9a8563bf103) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed Svelte files failing to parse when an expression begins with an object literal. Now the following snippet is correctly parsed: ```svelte <p>{{ a: true }}</p> <div class={{ active: isActive }}></div> ``` - [#&#8203;11173](https://github.com/biomejs/biome/pull/11173) [`481d008`](https://github.com/biomejs/biome/commit/481d008f6e8872a78749496fbbf1f9c761d9a770) Thanks [@&#8203;Austin1serb](https://github.com/Austin1serb)! - Fixed [#&#8203;10242](https://github.com/biomejs/biome/issues/10242): JavaScript GritQL patterns with multiple metavariables now match snippets consistently in WebAssembly. - [#&#8203;11187](https://github.com/biomejs/biome/pull/11187) [`23c0369`](https://github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Added the nursery rule [`noInvalidPropertyInitValue`](https://biomejs.dev/linter/rules/no-invalid-property-init-value/), which reports an `@property` whose `initial-value` does not match its `syntax` descriptor. For example, the following declaration triggers the rule because `red` is not a `<length>`: ```css @property --size { syntax: "<length>"; inherits: false; initial-value: red; } ``` - [#&#8203;11272](https://github.com/biomejs/biome/pull/11272) [`73896e6`](https://github.com/biomejs/biome/commit/73896e6712ba4c398ba21141829f8361ace45eb2) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the diagnostic emitted by [`noRootType`](https://biomejs.dev/linter/rules/no-root-type). - [#&#8203;11240](https://github.com/biomejs/biome/pull/11240) [`bd0b68d`](https://github.com/biomejs/biome/commit/bd0b68d418890059930074b46273aa616fbb735a) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11223](https://github.com/biomejs/biome/issues/11223): Improved the performance of [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) when analyzing async class methods that call other methods through `this`. - [#&#8203;11172](https://github.com/biomejs/biome/pull/11172) [`4a0bc5c`](https://github.com/biomejs/biome/commit/4a0bc5c46e6dbbefd17fa133ea426aa41f0a23f8) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Fixed [#&#8203;10806](https://github.com/biomejs/biome/issues/10806): [`noUselessFragments`](https://biomejs.dev/linter/rules/no-useless-fragments/) no longer causes Biome to panic when its unsafe fix removes a fragment used as a JSX attribute value. - [#&#8203;11227](https://github.com/biomejs/biome/pull/11227) [`4d603b0`](https://github.com/biomejs/biome/commit/4d603b072fae45a69bd291ab92f3379232cd34df) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Fixed [#&#8203;11178](https://github.com/biomejs/biome/issues/11178): [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) no longer reports Vue's built-in instance properties, such as `$slots` and `$attrs`, in template expressions or `$event` in inline event-handler expressions. The instance properties are still reported inside `<script setup>`, where they are not defined. - [#&#8203;11187](https://github.com/biomejs/biome/pull/11187) [`23c0369`](https://github.com/biomejs/biome/commit/23c0369c43b59284ca68c65883d6ede4228b6fb8) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the `syntax` descriptor of `@property` rules. ### [`v2.5.7`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#257) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.6...@biomejs/biome@2.5.7) ##### Patch Changes - [#&#8203;10822](https://github.com/biomejs/biome/pull/10822) [`c171b3b`](https://github.com/biomejs/biome/commit/c171b3bd513d49c35b66cdc74a5de0ca0766b6ef) Thanks [@&#8203;pkallos](https://github.com/pkallos)! - Added the option `ignoreIfStatements` to [useNullishCoalescing](https://biomejs.dev/linter/rules/use-nullish-coalescing/). Biome now flags `if` statements that only assign to a nullish variable (such as `if (!a) { a = b }`) and can rewrite them to `??=`. When enabled, Biome ignores those `if` statements. - [#&#8203;11136](https://github.com/biomejs/biome/pull/11136) [`e63354c`](https://github.com/biomejs/biome/commit/e63354cf280783fa6380951342bdacc3fd55e681) Thanks [@&#8203;AkashNaickar](https://github.com/AkashNaickar)! - Added a new nursery rule [`noExtendNative`](https://biomejs.dev/linter/rules/no-extend-native/), which reports extending the prototype of a built-in object. - [#&#8203;10094](https://github.com/biomejs/biome/pull/10094) [`e007143`](https://github.com/biomejs/biome/commit/e00714360807115210e549caca0f235431ca9a8a) Thanks [@&#8203;THEjacob1000](https://github.com/THEjacob1000)! - Added the nursery rule [`noTailwindArbitraryValue`](https://biomejs.dev/linter/rules/no-tailwind-arbitrary-value/). Biome now reports Tailwind CSS arbitrary values such as `w-[400px]`, including in HTML/JSX class attributes, configured utility functions, and tagged templates. - [#&#8203;11184](https://github.com/biomejs/biome/pull/11184) [`135f476`](https://github.com/biomejs/biome/commit/135f476de8b853f9dc2ff2679ea3525432e66e8e) Thanks [@&#8203;subotac](https://github.com/subotac)! - Fixed [#&#8203;11176](https://github.com/biomejs/biome/issues/11176): `noUnknownPseudoClass` now recognizes Vue's `:deep()` pseudo-class inside `.vue` style blocks. - [#&#8203;8239](https://github.com/biomejs/biome/pull/8239) [`a519f9d`](https://github.com/biomejs/biome/commit/a519f9d19e56015ec906efac4629fbb15708f5e2) Thanks [@&#8203;cormacrelf](https://github.com/cormacrelf)! - Fixed [#&#8203;8233](https://github.com/biomejs/biome/issues/8233), where Biome CLI in stdin mode didn't work correctly when handling files in projects with nested configurations. For example, with the following structure, `--stdin-file-path=subdirectory/...` would not use the nested configuration in `subdirectory/biome.json`: ``` ├── biome.json └── subdirectory ├── biome.json └── lib.js ``` ```shell biome format --write --stdin-file-path=subdirectory/lib.js < subdirectory/lib.js ``` Now, the nested configuration is correctly picked up and applied. In addition, Biome now shows a warning if `--stdin-file-path` is provided but that path is ignored and therefore not formatted or fixed. - [#&#8203;11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/): Biome now chooses the same function overload as TypeScript when an argument is a callback, so conditions that were previously missed are reported. The following code is now invalid, because a parameter typed `() => void` accepts an `async` callback and `schedule` therefore returns `string`: ```ts declare function schedule(handler: () => void): string; declare function schedule(handler: () => Promise<void>): string | undefined; schedule(async () => {}) ?? "fallback"; ``` The following code is also now invalid, because `map(() => 42)` returns `42`: ```ts type Mapper<T> = () => T; declare function map<T>(mapper: Mapper<T>): T; map(() => 42) || flag; ``` - [#&#8203;11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11087](https://github.com/biomejs/biome/issues/11087): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports optional chains and nullish coalescing whose receiver can be nullish. For example, the optional chain and fallback in the following code are no longer reported: ```ts declare const usage: { range: { startDate: string } } | null; const startDate = usage?.range.startDate ?? "N/A"; ``` - [#&#8203;11118](https://github.com/biomejs/biome/pull/11118) [`9c16840`](https://github.com/biomejs/biome/commit/9c16840801a806ba34fbba7da28b9724d250207a) Thanks [@&#8203;subotac](https://github.com/subotac)! - Fixed [#&#8203;11098](https://github.com/biomejs/biome/issues/11098): The HTML formatter now preserves the configured trailing newline when a file ends with a comment. ```diff -<!-- trailing comment --> \ No newline at end of file +<!-- trailing comment --> ``` - [#&#8203;11201](https://github.com/biomejs/biome/pull/11201) [`0e80610`](https://github.com/biomejs/biome/commit/0e8061069915651a6f7cbba918a0bde0dbc1491f) Thanks [@&#8203;Bishwas-py](https://github.com/Bishwas-py)! - Fixed [#&#8203;11182](https://github.com/biomejs/biome/issues/11182): suppression comments for [`noPositiveTabindex`](https://biomejs.dev/linter/rules/no-positive-tabindex/) now suppress the rule in HTML files when the attributes of the element span multiple lines. - [#&#8203;11079](https://github.com/biomejs/biome/pull/11079) [`607afd2`](https://github.com/biomejs/biome/commit/607afd2488efb30cff5ea4b27de4d98eca728e0f) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - The HTML formatter now lays out the `srcset` attribute of `<img>` and `<source>` as the list of candidates it is. Runs of whitespace between candidates collapse, and once the list no longer fits on one line each candidate goes on its own line with the descriptors aligned: ```diff - <img srcset="/visual@0.5.png 400w, /visual.png 805w, /visual@2x.png 1610w, /visual@3x.png 2415w" /> + <img + srcset=" + /visual@0.5.png 400w, + /visual.png 805w, + /visual@2x.png 1610w, + /visual@3x.png 2415w + " + /> ``` - [#&#8203;11156](https://github.com/biomejs/biome/pull/11156) [`fed72c7`](https://github.com/biomejs/biome/commit/fed72c7e8a2bff2942d5970f182262d18e049914) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Fixed [#&#8203;11129](https://github.com/biomejs/biome/issues/11129): [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) no longer reports Vue bindings as unused when they are assigned through automatically unwrapped template refs. - [#&#8203;11124](https://github.com/biomejs/biome/pull/11124) [`d890b39`](https://github.com/biomejs/biome/commit/d890b39c3ef21040bded453d9af91e1b301a0d67) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting of line comments between a declaration colon and value to preserve their source indentation. ```diff .test { background: - /////// foo - // bar + /////// foo + // bar radial-gradient(circle, #&#8203;000, transparent); } ``` - [#&#8203;11113](https://github.com/biomejs/biome/pull/11113) [`3d8ab73`](https://github.com/biomejs/biome/commit/3d8ab73619f1c62a2d544d41ffee16eab9307d51) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting of long block comments between comma-separated property values: ```diff .foo { box-shadow: - 1000px /* long long long long long long long long long long long long comment */ 1000px /* long long long long long long long long long comment */ 2px color(srgb 0.555555555 0.555555555 0.555555555), + 1000px + /* long long long long long long long long long long long long comment */ + 1000px /* long long long long long long long long long comment */ 2px + color(srgb 0.555555555 0.555555555 0.555555555), 1px 1px black; } ``` - [#&#8203;11127](https://github.com/biomejs/biome/pull/11127) [`da5c1a5`](https://github.com/biomejs/biome/commit/da5c1a539bac009eb1bc275b9bd8194f9ca7d5fa) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - The HTML formatter now picks the quote character for an attribute by counting the quotes in the value rather than looking only for a double quote. `&apos;` and `&quot;` count as the characters they stand for, and only the character that ends up as the delimiter stays escaped: ```diff - <div title='123 &apos;&quot; 456'></div> + <div title="123 '&quot; 456"></div> ``` Entities that are not quotes, such as `&amp;` or `&[#&#8203;39](https://github.com/biomejs/biome/issues/39);`, are left exactly as written. - [#&#8203;11193](https://github.com/biomejs/biome/pull/11193) [`77035bb`](https://github.com/biomejs/biome/commit/77035bb3777805c682eefa4cbed5464c94baccba) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed the HTML formatter collapsing the blank line between an element and the text that follows it. A blank line before text is now kept, the way one before another element already was: ```diff <div>foo</div> - text ``` - [#&#8203;11106](https://github.com/biomejs/biome/pull/11106) [`ad80f57`](https://github.com/biomejs/biome/commit/ad80f572c922fc2a80c90b8e26a66300dfb82d24) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - The HTML formatter now writes the HTML5 doctype in lowercase, matching Prettier: ```diff - <!DOCTYPE html> + <!doctype html> ``` This only applies to a plain `.html` file whose doctype stands alone. A doctype that names a DTD keeps the case it was written with, since the rest of the declaration is not lowercased either: ```html <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> ``` A `.vue`, `.svelte`, or `.astro` file keeps whatever the author wrote. - [#&#8203;11188](https://github.com/biomejs/biome/pull/11188) [`60679db`](https://github.com/biomejs/biome/commit/60679dbe6d53c9b78571042b0b8c906bd345e52d) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed the HTML formatter printing a comment twice when it ended the line of the last element in a document: ```diff - text<!-- a --><!-- a --> + text<!-- a --> ``` - [#&#8203;11077](https://github.com/biomejs/biome/pull/11077) [`4dcd0d9`](https://github.com/biomejs/biome/commit/4dcd0d99579650191696dc5fb8b16dd69d65c4ee) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed a bug where the HTML formatter collapsed the whitespace inside `<textarea>`, `<xmp>` and `<plaintext>`, changing what the page renders. ```diff - <textarea> - line one - line two </textarea> + <textarea>line one line two</textarea> ``` Biome now prints the content of these elements exactly as it appears in the source, matching the existing behavior for `<pre>`. - [#&#8203;11194](https://github.com/biomejs/biome/pull/11194) [`abfbb11`](https://github.com/biomejs/biome/commit/abfbb11da260852f0b4aa15f36207314ccfae436) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed the HTML formatter refusing to format a Svelte file containing an array pattern that skips a position: ```svelte {#each animals as [, value]} <p>{value}</p> {/each} ``` - [#&#8203;10094](https://github.com/biomejs/biome/pull/10094) [`e007143`](https://github.com/biomejs/biome/commit/e00714360807115210e549caca0f235431ca9a8a) Thanks [@&#8203;THEjacob1000](https://github.com/THEjacob1000)! - Fixed [`useSortedClasses`](https://biomejs.dev/linter/rules/use-sorted-classes/) to correctly detect unsorted classes in static member expression tagged templates (e.g. `tw.div\`...\`\`). Previously, these were silently skipped due to surrounding whitespace trivia not being stripped from the tag name. - [#&#8203;11078](https://github.com/biomejs/biome/pull/11078) [`10da30e`](https://github.com/biomejs/biome/commit/10da30e0013c35fe2f4d3e335b88a539ae6eb87a) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed Vue single-file components failing to parse when they contain a custom block such as `<i18n>` or `<docs>`, or a `<template>` written in another language. Their content is no longer read as HTML, so a block may hold whatever its own tooling expects: ```vue <docs> This block is prose, and it may mention a `<my-component>` without closing it. </docs> <template lang="pug"> .test #foo </template> ``` Previously both blocks produced a parse error and the whole file was left unformatted. Biome now prints their content unchanged while still formatting the opening tag. - [#&#8203;11231](https://github.com/biomejs/biome/pull/11231) [`4afd901`](https://github.com/biomejs/biome/commit/4afd901edd5d921d63a259a049c6a774269c7b82) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the performance of the following lint rules: - [`noArguments`](https://biomejs.dev/linter/rules/no-arguments/). - [`noGlobalAssign`](https://biomejs.dev/linter/rules/no-global-assign/). - [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/). - [`noRestrictedGlobals`](https://biomejs.dev/linter/rules/no-restricted-globals/). - [`noInvalidUseBeforeDeclaration`](https://biomejs.dev/linter/rules/no-invalid-use-before-declaration/). - [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/). - [`noRedeclare`](https://biomejs.dev/linter/rules/no-redeclare/). - [#&#8203;11134](https://github.com/biomejs/biome/pull/11134) [`2fa0a62`](https://github.com/biomejs/biome/commit/2fa0a62224af7a13869a28ef80aefa5ea75ebfd2) Thanks [@&#8203;yanthomasdev](https://github.com/yanthomasdev)! - Clarified the warning emitted when using the experimental `json` and `json-pretty` reporters. - [#&#8203;11198](https://github.com/biomejs/biome/pull/11198) [`ed88b13`](https://github.com/biomejs/biome/commit/ed88b13a6d95fe564aaee6c731651e7dec8266db) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Fixed [#&#8203;11171](https://github.com/biomejs/biome/issues/11171): variables referenced only inside a Svelte attachment (`{@attach ...}`) are no longer reported as unused by [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) and [`noUnusedImports`](https://biomejs.dev/linter/rules/no-unused-imports/). - [#&#8203;11155](https://github.com/biomejs/biome/pull/11155) [`6ee17ea`](https://github.com/biomejs/biome/commit/6ee17ea2df979a67df5d1263734f28f77c6512a6) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved performance when printing diagnostics to the console. - [#&#8203;11160](https://github.com/biomejs/biome/pull/11160) [`217f8ad`](https://github.com/biomejs/biome/commit/217f8adbc2f700ab4c92cb227434c2afba9f9611) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) by skipping type inference for assignment statements, which are always considered handled. - [#&#8203;11159](https://github.com/biomejs/biome/pull/11159) [`26c23d9`](https://github.com/biomejs/biome/commit/26c23d96ced1a6eca496955fbe93279da2747346) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Fixed [#&#8203;11144](https://github.com/biomejs/biome/issues/11144): [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) no longer reports already-awaited optional Promise values. - [#&#8203;11138](https://github.com/biomejs/biome/pull/11138) [`8c2c6bd`](https://github.com/biomejs/biome/commit/8c2c6bd96c035e506bc60b75448afb039e331fb1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;11121](https://github.com/biomejs/biome/issues/11121): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports conditions based on an inapplicable function overload. For example, the condition in the following code is no longer reported because `query({})` selects the overload that returns `boolean`: ```ts declare function query(options: { initial: string }): { isPending: false }; declare function query(options: { initial?: string }): { isPending: boolean }; const { isPending } = query({}); isPending || fallback; ``` - [#&#8203;11152](https://github.com/biomejs/biome/pull/11152) [`c4fc6a9`](https://github.com/biomejs/biome/commit/c4fc6a90777358905cf99b3261a479de73d7d383) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of collecting rule timings with `--profile-rules` in heavily multithreaded environments. - [#&#8203;11128](https://github.com/biomejs/biome/pull/11128) [`4d3ff76`](https://github.com/biomejs/biome/commit/4d3ff7689c36af5149142d9a4a23165154359655) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;7635](https://github.com/biomejs/biome/issues/7635): [`noDeprecatedImports`](https://biomejs.dev/linter/rules/no-deprecated-imports/) now detects deprecated ambient declarations that are exported separately. - [#&#8203;11117](https://github.com/biomejs/biome/pull/11117) [`01f7ef5`](https://github.com/biomejs/biome/commit/01f7ef58d4c19a587b01754c96b577a2a5a47418) Thanks [@&#8203;subotac](https://github.com/subotac)! - Fixed [#&#8203;11014](https://github.com/biomejs/biome/issues/11014): [`noDelete`](https://biomejs.dev/linter/rules/no-delete/) no longer reports `process.env["FOO"]` style property deletions. - [#&#8203;11168](https://github.com/biomejs/biome/pull/11168) [`9847e68`](https://github.com/biomejs/biome/commit/9847e680ff8bb891a6c910e881af98a4fffa33c2) Thanks [@&#8203;saberoueslati](https://github.com/saberoueslati)! - Added the nursery rule [`noNonScalableViewport`](https://biomejs.dev/linter/rules/no-non-scalable-viewport), which reports viewport metadata that disables user scaling with `user-scalable=no`. For example: ```html <meta name="viewport" content="width=device-width, user-scalable=no" /> ``` - [#&#8203;11154](https://github.com/biomejs/biome/pull/11154) [`a1d6b1f`](https://github.com/biomejs/biome/commit/a1d6b1fc544c6c6cc1dd38f87898d34738fbe97b) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of [`noImportCycles`](https://biomejs.dev/linter/rules/no-import-cycles/) by skipping graph traversals for imports that cannot be part of a cycle. - [#&#8203;11175](https://github.com/biomejs/biome/pull/11175) [`d96d6dd`](https://github.com/biomejs/biome/commit/d96d6dd07702828f7e7a5ce59f8fc00006f6ee46) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed CSS parsing of registered custom properties: Biome now correctly validates the `syntax` descriptor of `@property` rules. ### [`v2.5.6`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#256) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.5...@biomejs/biome@2.5.6) ##### Patch Changes - [#&#8203;11035](https://github.com/biomejs/biome/pull/11035) [`0e4b03b`](https://github.com/biomejs/biome/commit/0e4b03be71b32120c6326e58e046260bcf5d3231) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a performance regression in [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) that caused type inference to run repeatedly while linting a file. - [#&#8203;11043](https://github.com/biomejs/biome/pull/11043) [`22ec076`](https://github.com/biomejs/biome/commit/22ec076462d4590ea7c95f7693b69040c32a38aa) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting for multiline function arguments preceded by comments: ```diff .example { value: outer( 1, /* comment */ nested( - first, - second - ) + first, + second + ) ); } ``` - [#&#8203;11007](https://github.com/biomejs/biome/pull/11007) [`c9acb25`](https://github.com/biomejs/biome/commit/c9acb25acbce7a6f632b5041ec546a604aea4343) Thanks [@&#8203;BTF-Kabir-2020](https://github.com/BTF-Kabir-2020)! - Fixed [#&#8203;9195](https://github.com/biomejs/biome/issues/9195): [`useHookAtTopLevel`](https://biomejs.dev/linter/rules/use-hook-at-top-level/) no longer reports hooks in named `forwardRef` components that receive a `ref` parameter. - [#&#8203;10152](https://github.com/biomejs/biome/pull/10152) [`50a9bd8`](https://github.com/biomejs/biome/commit/50a9bd84df852de305e94a91fb57f6b3b1378187) Thanks [@&#8203;Zelys-DFKH](https://github.com/Zelys-DFKH)! - Fixed [#&#8203;10131](https://github.com/biomejs/biome/issues/10131): Biome now correctly parses curried arrow functions in ternary consequents when the inner arrow's parameters use a destructuring pattern, e.g. `cond ? (x) => ({ a, b }) => body : alt`. - [#&#8203;11105](https://github.com/biomejs/biome/pull/11105) [`8ffe2b9`](https://github.com/biomejs/biome/commit/8ffe2b9f2f9224921a0bad4a772e6611006351e5) Thanks [@&#8203;dadavidtseng](https://github.com/dadavidtseng)! - Fixed [#&#8203;11092](https://github.com/biomejs/biome/issues/11092): The [`noUselessTernary`](https://biomejs.dev/linter/rules/no-useless-ternary/) quick fix now preserves operator spacing when simplifying or inverting boolean ternary expressions. - [#&#8203;10533](https://github.com/biomejs/biome/pull/10533) [`5809875`](https://github.com/biomejs/biome/commit/580987506a32cdde2f5498e0f712e3493ef9adde) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Fixed [#&#8203;10515](https://github.com/biomejs/biome/issues/10515): `biome check --write` was not idempotent on Svelte files — multi-line template literals in `<script>` blocks and block comments in `<style>` blocks gained an extra indent level on every run. - [#&#8203;11040](https://github.com/biomejs/biome/pull/11040) [`0abb620`](https://github.com/biomejs/biome/commit/0abb620b2f0bd748bf272a2bc56aa02f5a6d0fee) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Fixed an issue where the HTML formatter would duplicate a comment placed directly before a Svelte `{@const ...}` or `{@debug ...}` block. The duplication compounded on every subsequent `--write`, causing the file to grow exponentially. - [#&#8203;10858](https://github.com/biomejs/biome/pull/10858) [`6d18204`](https://github.com/biomejs/biome/commit/6d182043b1de76f8668464bfa5c295161135ee0e) Thanks [@&#8203;ruidosujeira](https://github.com/ruidosujeira)! - Fixed [#&#8203;10839](https://github.com/biomejs/biome/issues/10839): Svelte `{#each}` array destructuring no longer includes spaces inside square brackets, and multiline bind function expressions now indent their getter, setter, and function body correctly. - [#&#8203;11009](https://github.com/biomejs/biome/pull/11009) [`2c36626`](https://github.com/biomejs/biome/commit/2c36626bed58e63e49ecca8a40c717adae4c91ac) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the accuracy of type-aware lint rules by resolving more inferred types. For example, [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) now detects floating Promises returned by aliased callbacks and arrays of Promises created by async mapping callbacks. The following statements are now reported: ```ts type AsyncCallback = () => Promise<void>; declare const callback: AsyncCallback; callback(); [1, 2, 3].map(async (value) => value); ``` - [#&#8203;10973](https://github.com/biomejs/biome/pull/10973) [`9cb044c`](https://github.com/biomejs/biome/commit/9cb044cf2c8971642942c302a6d2b0000964c2f0) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed false positives in [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) when generic-constraint, normalization, substitution, or structural return-type comparison cannot complete. The rule now suppresses diagnostics rather than suggesting a return type derived from partial information. For example, this unresolved return type is no longer reported: ```ts function unresolvedReturnType(): MissingType { return "value" as const; } ``` - [#&#8203;11071](https://github.com/biomejs/biome/pull/11071) [`15047a2`](https://github.com/biomejs/biome/commit/15047a2fff2aa2a5c0c096257b4718b0141431be) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - The HTML parser now accepts mixed-case `doctype` declarations. - [#&#8203;11030](https://github.com/biomejs/biome/pull/11030) [`cc90e65`](https://github.com/biomejs/biome/commit/cc90e65a6b14388a5fab1d893f782055fac34f91) Thanks [@&#8203;marschattha](https://github.com/marschattha)! - The `rdjson` reporter now populates the [severity](https://github.com/reviewdog/reviewdog/blob/master/proto/rdf/reviewdog.proto) field of each diagnostic (`ERROR`, `WARNING`, or `INFO`), so tools consuming Reviewdog Diagnostic Format output no longer need to assume a default severity. - [#&#8203;11009](https://github.com/biomejs/biome/pull/11009) [`2c36626`](https://github.com/biomejs/biome/commit/2c36626bed58e63e49ecca8a40c717adae4c91ac) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a performance regression in type-aware JavaScript lint rules by inferring only requested types and memoizing export resolution. - [#&#8203;11056](https://github.com/biomejs/biome/pull/11056) [`903b177`](https://github.com/biomejs/biome/commit/903b1770528040484b5f8b71f652130a8e6bd960) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added support for Svelte declaration tags using `let` and `const`. Biome can now parse, format, and lint bindings declared in these tags. - [#&#8203;11045](https://github.com/biomejs/biome/pull/11045) [`89c27c6`](https://github.com/biomejs/biome/commit/89c27c62541d2b628247563441e48f2303e53f4b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved the performance of Biome formatter up to \~7% across the board. - [#&#8203;9806](https://github.com/biomejs/biome/pull/9806) [`781d68d`](https://github.com/biomejs/biome/commit/781d68dae5df6ad188efc8afb0972112654614fe) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`noJsRestrictedProperties`](https://biomejs.dev/linter/rules/no-js-restricted-properties/), which ports ESLint's `no-restricted-properties` rule. Biome now flags restricted member access and object destructuring, and `biome migrate eslint` preserves the rule's options. ### [`v2.5.5`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#255) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.4...@biomejs/biome@2.5.5) ##### Patch Changes - [#&#8203;10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) for unions of bigint literals. The rule now reports missing bigint cases and compares bigint literals by value, including binary, octal, hexadecimal, and separator-containing spellings. For example, this switch now reports the missing `2n` case: ```ts declare const value: 1n | 2n; switch (value) { case 1n: break; } ``` - [#&#8203;10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed false positives in [`noBaseToString`](https://biomejs.dev/linter/rules/no-base-to-string/) and [`useNullishCoalescing`](https://biomejs.dev/linter/rules/use-nullish-coalescing/) when member, stringification, or nullish inference cannot complete. These rules now suppress diagnostics instead of reporting from partial type information. For example, neither expression is reported when a recursive type cannot be fully resolved: ```ts type Recursive = Recursive; declare const value: Recursive; String(value); value || "fallback"; ``` - [#&#8203;10977](https://github.com/biomejs/biome/pull/10977) [`0bf7486`](https://github.com/biomejs/biome/commit/0bf748653e488d0b959d39847641438cdb28188b) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10922](https://github.com/biomejs/biome/issues/10922): the action [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) no longer triggers for HTML instructions. - [#&#8203;10957](https://github.com/biomejs/biome/pull/10957) [`cf263c4`](https://github.com/biomejs/biome/commit/cf263c4700e9f24115e541d1f142934a9b2d878f) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [`noThenProperty`](https://biomejs.dev/linter/rules/no-then-property/) failing to detect `Object.fromEntries`, `Object.defineProperty`, and `Reflect.defineProperty` calls with comments between their tokens. - [#&#8203;10983](https://github.com/biomejs/biome/pull/10983) [`edc0ed7`](https://github.com/biomejs/biome/commit/edc0ed738ab8da3d512d527196684bd668090854) Thanks [@&#8203;ayaangazali](https://github.com/ayaangazali)! - Fixed [#&#8203;10980](https://github.com/biomejs/biome/issues/10980): [`useAriaPropsSupportedByRole`](https://biomejs.dev/linter/rules/use-aria-props-supported-by-role/) no longer reports false positives when the attribute that determines an element's implicit ARIA role is written as a shorthand attribute, such as `<a {href} aria-label="...">` in Astro and Svelte files. Shorthand attributes are now taken into account when computing the implicit role, so the anchor above correctly resolves to the `link` role instead of `generic`. - [#&#8203;10889](https://github.com/biomejs/biome/pull/10889) [`89526e3`](https://github.com/biomejs/biome/commit/89526e3858c437408ec9ff192c35a866ad991d1b) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatter casing for syntax-owned names while preserving author-defined names, including scoped keyframes and container scroll-state queries. ```diff - A:HOVER { COLOR: INITIAL; } + A:hover { color: initial; } - @KEYFRAMES :GLOBAL KeepFrames { FROM { COLOR: RED; } } + @keyframes :GLOBAL KeepFrames { from { color: RED; } } - @CONTAINER scroll-state((SCROLLED: TOP) AND (STUCK)) { A:HOVER { COLOR: RED; } } + @container scroll-state((SCROLLED: TOP) AND (STUCK)) { A:hover { color: RED; } } ``` - [#&#8203;10964](https://github.com/biomejs/biome/pull/10964) [`794ccd0`](https://github.com/biomejs/biome/commit/794ccd0528345c4eaa87af1d86f02475277a0a22) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed CSS formatting for comments between declaration values and `!important`. ```diff -a { color: /* before */ /* after */ red !important; } +a { color: /* before */ red /* after */ !important; } ``` - [#&#8203;10993](https://github.com/biomejs/biome/pull/10993) [`b7a9694`](https://github.com/biomejs/biome/commit/b7a969425d4292fc7c50440da7aea41ce5c9a9c2) Thanks [@&#8203;denbezrukov](https://github.com/denbezrukov)! - Fixed the CSS formatter to preserve comments on the correct side of selector combinators and before declaration blocks. ```diff -.before > /* comment */ .after {} +.before /* comment */ > .after {} ``` It now also keeps selectors with escaped newlines in attribute values inline when they fit. ```diff -div - span[foo="bar\ +div span[foo="bar\ value"] {} ``` - [#&#8203;10978](https://github.com/biomejs/biome/pull/10978) [`8ebafe1`](https://github.com/biomejs/biome/commit/8ebafe1c7489f1f7af379b8e52b8ad063c82d28a) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10870](https://github.com/biomejs/biome/issues/10870): [`noUnresolvedImports`](https://biomejs.dev/linter/rules/no-unresolved-imports/) no longer reports false positives such as `import type { NextRequest } from "next/server"`. - [#&#8203;10901](https://github.com/biomejs/biome/pull/10901) [`68c10e6`](https://github.com/biomejs/biome/commit/68c10e672fc886b31423b18be01e873d3bf77f43) Thanks [@&#8203;Socialpranker](https://github.com/Socialpranker)! - Fixed [#&#8203;10622](https://github.com/biomejs/biome/issues/10622): the HTML/Vue parser no longer panics on the argument-less `v-bind` shorthand (`:="props"`). This syntax is valid Vue and equivalent to `v-bind="props"`, so the parser now accepts it (along with the longhand `v-bind:="props"`) instead of crashing while building a diagnostic for a missing argument. - [#&#8203;10936](https://github.com/biomejs/biome/pull/10936) [`7df46f5`](https://github.com/biomejs/biome/commit/7df46f5be0880a02cb37453f01b83c1ba59b1e44) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved generic tuple inference for [`useIncludes`](https://biomejs.dev/linter/rules/use-includes/). The rule now recognizes specialised tuple element types returned through generic aliases. - [#&#8203;10941](https://github.com/biomejs/biome/pull/10941) [`f787725`](https://github.com/biomejs/biome/commit/f7877258271e20523d5c673e62912fce1d85cd56) Thanks [@&#8203;siketyan](https://github.com/siketyan)! - Fixed [`#10855`](https://github.com/biomejs/biome/issues/10855): Biome now supports parsing and formatting CSS custom media queries declared with [`@custom-media`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@custom-media). - [#&#8203;10969](https://github.com/biomejs/biome/pull/10969) [`72d309b`](https://github.com/biomejs/biome/commit/72d309b655cee70473e20b061f5a45112139688c) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an issue where Biome logs became too verbose, dumping information not relevant to user's operations. - [`e62f6b6`](https://github.com/biomejs/biome/commit/e62f6b61461227bbfd57fdf1b50b2dc8c01ea5a0) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10963](https://github.com/biomejs/biome/issues/10963): Biome no longer panics when a type-aware rule such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) checks a call to a function with multiple call signatures imported from another module. - [#&#8203;10931](https://github.com/biomejs/biome/pull/10931) [`899c60d`](https://github.com/biomejs/biome/commit/899c60d506115b3f62030236cbd0901bf294e6ab) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed `check --write` command. Now the command reports code frame of the formatted code, if the formatter is enabled. - [#&#8203;10904](https://github.com/biomejs/biome/pull/10904) [`ceee4f4`](https://github.com/biomejs/biome/commit/ceee4f43dabf88d86b87c9a4ce6051b6738869c2) Thanks [@&#8203;qzwxsaedc](https://github.com/qzwxsaedc)! - Fixed [#&#8203;10892](https://github.com/biomejs/biome/issues/10892): [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) no longer reports a false positive when checking a member of a discriminated union that is accessed through a default type-only namespace import. The following code is no longer flagged: ```ts import type Types from "./types"; declare function parse(): Types.Result<string>; const result = parse(); if (!result.success) { } ``` - [#&#8203;10962](https://github.com/biomejs/biome/pull/10962) [`f0a67f2`](https://github.com/biomejs/biome/commit/f0a67f2e56c0785595c5cf14a93dba5bb32acf2d) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Biome no longer removes embedded styles and scripts in HTML files. - [#&#8203;11000](https://github.com/biomejs/biome/pull/11000) [`5039a1e`](https://github.com/biomejs/biome/commit/5039a1ee35771d0193de65a6326781313ab77afb) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed a bug where closing one editor stopped a shared Biome daemon used by other editors. LSP proxy processes now exit when either the editor or daemon disconnects. - [#&#8203;10957](https://github.com/biomejs/biome/pull/10957) [`cf263c4`](https://github.com/biomejs/biome/commit/cf263c4700e9f24115e541d1f142934a9b2d878f) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of the [`noThenProperty`](https://biomejs.dev/linter/rules/no-then-property/) lint rule by about 50%. - [#&#8203;10992](https://github.com/biomejs/biome/pull/10992) [`4bf9b21`](https://github.com/biomejs/biome/commit/4bf9b21319df240e2c5ef2e5a9cb2e9582a0e1d1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/): The rule now reports Promise-returning callbacks where a synchronous callback is expected when calls use tuple spreads or tuple rest parameters, including generic and deeply nested tuples, and when constructor signatures come from interface or object types. Recursive or excessively nested tuple spreads use a conservative fallback so analysis terminates. For example, the following callback is now reported. ```ts declare function consume(...args: [number, () => void]): void; const prefix: [number] = [1]; consume(...prefix, async () => {}); ``` - [#&#8203;10915](https://github.com/biomejs/biome/pull/10915) [`b3b12b3`](https://github.com/biomejs/biome/commit/b3b12b3fe390feabbd9ba097922d6c7e56823406) Thanks [@&#8203;Functionhx](https://github.com/Functionhx)! - Added the rule [`noNegationInEqualityCheck`](https://biomejs.dev/linter/rules/no-negation-in-equality-check/). The rule flags negated expressions on the left side of strict equality checks like `!foo === bar` — due to operator precedence this evaluates as `(!foo) === bar` which is almost always a mistake for `foo !== bar`. The rule provides an unsafe fix that flips the operator. ```js // Invalid !foo === bar; !foo !== bar; // Valid foo !== bar; foo === bar; ``` - [#&#8203;10970](https://github.com/biomejs/biome/pull/10970) [`bd1038b`](https://github.com/biomejs/biome/commit/bd1038be1ad110aae60bcdbe9a154c6a2fc85c14) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Improved overload selection for [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/). Biome now handles overloaded calls, overloaded constructors, rest parameters, union arguments, and generic constraints without selecting an incompatible signature. For example, `noMisusedPromises` now reports the async callback passed to the synchronous overload: ```ts declare function consume(kind: "async", callback: () => Promise<void>): void; declare function consume(kind: "sync", callback: () => void): void; consume("sync", async () => {}); ``` - [#&#8203;10933](https://github.com/biomejs/biome/pull/10933) [`48a4abb`](https://github.com/biomejs/biome/commit/48a4abb99d41b1241b2a5812a12247b671d0dfed) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`useArrayFind`](https://biomejs.dev/linter/rules/use-array-find/) to recognize bigint zero indexes. - [#&#8203;10931](https://github.com/biomejs/biome/pull/10931) [`899c60d`](https://github.com/biomejs/biome/commit/899c60d506115b3f62030236cbd0901bf294e6ab) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed an orchestration issue that could lead to deadlocks when type-aware rules are enabled. - [#&#8203;10969](https://github.com/biomejs/biome/pull/10969) [`72d309b`](https://github.com/biomejs/biome/commit/72d309b655cee70473e20b061f5a45112139688c) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Hardened the Biome Language Server by improving its synchronisation logic. - [#&#8203;10972](https://github.com/biomejs/biome/pull/10972) [`ab8c21b`](https://github.com/biomejs/biome/commit/ab8c21b35e81708276e4283a4a0ff86ea815e345) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed false positives in [`noMisusedPromises`](https://biomejs.dev/linter/rules/no-misused-promises/) and [`useAwaitThenable`](https://biomejs.dev/linter/rules/use-await-thenable/) when Promise or thenable inference cannot complete. These rules now suppress diagnostics instead of treating incomplete type information as a definite result. For example, `useAwaitThenable` no longer reports `await value` when the value's thenability is unknown: ```ts declare const value: unknown; async function consume() { await value; } ``` ### [`v2.5.4`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#254) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.3...@biomejs/biome@2.5.4) ##### Patch Changes - [#&#8203;10665](https://github.com/biomejs/biome/pull/10665) [`55ff995`](https://github.com/biomejs/biome/commit/55ff995098148446b7e7fdfc19053902bb987122) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Improved the performance of the HTML parser slightly in our synthetic benchmarks. - [#&#8203;10894](https://github.com/biomejs/biome/pull/10894) [`f4fb10e`](https://github.com/biomejs/biome/commit/f4fb10e176e537e8ce2cac0c3fd4c38a77f91886) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;6392](https://github.com/biomejs/biome/issues/6392): On-type formatting no longer moves comments before an `if` statement into its body. - [#&#8203;10939](https://github.com/biomejs/biome/pull/10939) [`f2799db`](https://github.com/biomejs/biome/commit/f2799db38e3d8a644207d9b8f957abea6cb3d9fa) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10930](https://github.com/biomejs/biome/issues/10930): [`noLabelWithoutControl`](https://biomejs.dev/linter/rules/no-label-without-control/) now correctly detects text interpolation in Astro, Svelte & Vue as valid accessible content. - [#&#8203;10945](https://github.com/biomejs/biome/pull/10945) [`ae15d98`](https://github.com/biomejs/biome/commit/ae15d98bbf2222fbb34e3e31832cba9676a6d01c) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10942](https://github.com/biomejs/biome/issues/10942): Svelte directives don't throw an accidental debug log anymore. - [#&#8203;10842](https://github.com/biomejs/biome/pull/10842) [`5e1abfe`](https://github.com/biomejs/biome/commit/5e1abfee59155b5fdca8813314371ed54c06acfb) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;9196](https://github.com/biomejs/biome/issues/9196): `biome check --write --unsafe` no longer hangs forever when applying the [`noCommentText`](https://biomejs.dev/linter/rules/no-comment-text/) code fix. The rule's fix now wraps the comment in a real JSX expression container (`{/* comment */}`) instead of re-inserting the braces as plain JSX text, so the fixed code is no longer reported again by the same rule. - [#&#8203;10891](https://github.com/biomejs/biome/pull/10891) [`ecca79e`](https://github.com/biomejs/biome/commit/ecca79e8ff10f40aa676212c0db0a970c6091615) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [`#10885`](https://github.com/biomejs/biome/issues/10885): prevented a module-inference regression introduced by a housekeeping change. - [#&#8203;10886](https://github.com/biomejs/biome/pull/10886) [`60c8043`](https://github.com/biomejs/biome/commit/60c8043527f7ccc7b505471e1042f2a4324e4d31) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10727](https://github.com/biomejs/biome/issues/10727): Biome now breaks the arguments of curried `test.each`, `it.each`, `describe.each`, and `test.for` calls when they exceed the configured line width. ```diff - test.each([[1, 2]])("a description that is long enough to push the hugged opening line beyond the print width", (a, b) => { - expect(a).toBe(b); - }); + test.each([[1, 2]])( + "a description that is long enough to push the hugged opening line beyond the print width", + (a, b) => { + expect(a).toBe(b); + }, + ); ``` - [#&#8203;10895](https://github.com/biomejs/biome/pull/10895) [`01a85f0`](https://github.com/biomejs/biome/commit/01a85f04b09f0af05b16a15c137421e312ceada5) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Biome will now remove stale Unix daemon sockets from older Biome versions when starting a newer daemon. ### [`v2.5.3`](https://github.com/biomejs/biome/blob/HEAD/packages/@biomejs/biome/CHANGELOG.md#253) [Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.5.2...@biomejs/biome@2.5.3) ##### Patch Changes - [#&#8203;10815](https://github.com/biomejs/biome/pull/10815) [`86613d5`](https://github.com/biomejs/biome/commit/86613d5b01eb965b460ccefbf27f168d87774aaf) Thanks [@&#8203;WaterWhisperer](https://github.com/WaterWhisperer)! - Fixed a parser panic reported in [#&#8203;10708](https://github.com/biomejs/biome/issues/10708): Biome now recovers when unsupported CSS Modules `@value` rules or scoped `@keyframes` names end at EOF. - [#&#8203;10534](https://github.com/biomejs/biome/pull/10534) [`da9b403`](https://github.com/biomejs/biome/commit/da9b403b6bbacc8d75d56e327a46f4ed0285913e) Thanks [@&#8203;Mokto](https://github.com/Mokto)! - Fixed [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/) false positives in Svelte files: Svelte store subscriptions (`$store` references in templates now keep the underlying `store` binding from being flagged), and `$bindable()` props that are only written to in the script block (write-only is intentional for bindable props) are no longer reported as unused. - [#&#8203;10827](https://github.com/biomejs/biome/pull/10827) [`098ba41`](https://github.com/biomejs/biome/commit/098ba41c99e6efaac8eb182eec258a567bb00123) Thanks [@&#8203;Aqu1bp](https://github.com/Aqu1bp)! - Fixed [#&#8203;10698](https://github.com/biomejs/biome/issues/10698): The [`noUnsafeOptionalChaining`](https://biomejs.dev/linter/rules/no-unsafe-optional-chaining/) rule now reports unsafe optional chains wrapped in TypeScript `as`, `satisfies`, type assertion, and instantiation expressions, such as `new (value?.constructor as Constructor)()`. - [#&#8203;10773](https://github.com/biomejs/biome/pull/10773) [`3c6513d`](https://github.com/biomejs/biome/commit/3c6513d4e9a82a195785144caa9d96093c3861ff) Thanks [@&#8203;otkrickey](https://github.com/otkrickey)! - Fixed [#&#8203;10772](https://github.com/biomejs/biome/issues/10772): [`useVueValidVOn`](https://biomejs.dev/linter/rules/use-vue-valid-v-on/) no longer reports a missing handler for v-on directives using a verb modifier (`.stop` / `.prevent`) without an expression, e.g. `<div @click.stop></div>`. The rule also accepts the arg-less object syntax `<div v-on="$listeners"></div>` instead of reporting a missing event name. - [#&#8203;10721](https://github.com/biomejs/biome/pull/10721) [`d83c66b`](https://github.com/biomejs/biome/commit/d83c66b39a820703d94100f8a6502cc6dbad26a1) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved type-aware lint rule inference for built-in globals and indexed function calls. Biome now resolves `Error(...)`, `new Error(...)`, optional `Error#stack`, and calls through indexed function values such as `handlers[0]()` more accurately. - [#&#8203;10865](https://github.com/biomejs/biome/pull/10865) [`6450276`](https://github.com/biomejs/biome/commit/6450276764ee4794a0fcb46c139f95b68d892427) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [#&#8203;10845](https://github.com/biomejs/biome/issues/10845). Biome Language Server no longer goes in deadlock when the scanner is enabled. - [#&#8203;10853](https://github.com/biomejs/biome/pull/10853) [`93d8e53`](https://github.com/biomejs/biome/commit/93d8e5352454bccfbd179db03b3155776599c52c) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10840](https://github.com/biomejs/biome/issues/10840): Astro shorthand attribute syntax is now correctly being parsed from embedded nodes. - [#&#8203;10820](https://github.com/biomejs/biome/pull/10820) [`bba3092`](https://github.com/biomejs/biome/commit/bba30920715920142e933939f6270feedca933a5) Thanks [@&#8203;JamBalaya56562](https://github.com/JamBalaya56562)! - Fixed [#&#8203;10619](https://github.com/biomejs/biome/issues/10619): [`noProcessEnv`](https://biomejs.dev/linter/rules/no-process-env/) now also reports computed (bracket) member access. Previously only dot access was checked, so `process["env"]` and `env["NODE_ENV"]` (where `env` is imported from `node:process`) were missed. Both static and computed accesses are now reported. - [#&#8203;10835](https://github.com/biomejs/biome/pull/10835) [`3447b2f`](https://github.com/biomejs/biome/commit/3447b2f5a3c430efc8e917514260af5341c5509d) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10824](https://github.com/biomejs/biome/issues/10824): [`useDomQuerySelector`](https://biomejs.dev/linter/rules/use-dom-query-selector/) now supports an `ignore` option for receiver identifiers that should not be reported. - [#&#8203;10875](https://github.com/biomejs/biome/pull/10875) [`b12e486`](https://github.com/biomejs/biome/commit/b12e486d0f0b80d02d2208e239190f8756d39d48) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10795](https://github.com/biomejs/biome/issues/10795): `--profile-rules` now reports timings for each plugin separately as `plugin/<pluginName>`, matching the naming used by plugin suppressions, instead of aggregating all plugins under a single `plugin/plugin` entry. - [#&#8203;10877](https://github.com/biomejs/biome/pull/10877) [`d6bc447`](https://github.com/biomejs/biome/commit/d6bc4473a210758ee49f6cad41bc69587a7cf125) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Fixed [biome-zed#164](https://github.com/biomejs/biome-zed/issues/164): Biome no longer inserts stray whitespace when format-on-type runs after closing delimiters such as `)`, `]`, and `}`. - [#&#8203;10867](https://github.com/biomejs/biome/pull/10867) [`a21463e`](https://github.com/biomejs/biome/commit/a21463e5f616a2db5035b470cd206ac9da4d9423) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10864](https://github.com/biomejs/biome/issues/10864): Biome no longer crashes when checking or linting HTML files with unquoted attribute values such as `<textarea rows=4></textarea>`. </details> <details> <summary>cznic/sqlite (modernc.org/sqlite)</summary> ### [`v1.60.1`](https://gitlab.com/cznic/sqlite/compare/v1.60.0...v1.60.1) [Compare Source](https://gitlab.com/cznic/sqlite/compare/v1.60.0...v1.60.1) ### [`v1.60.0`](https://gitlab.com/cznic/sqlite/compare/v1.59.0...v1.60.0) [Compare Source](https://gitlab.com/cznic/sqlite/compare/v1.59.0...v1.60.0) </details> <details> <summary>haydenbleasel/ultracite (ultracite)</summary> ### [`v7.12.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.12.2) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.12.1...ultracite@7.12.2) ##### Patch Changes - [`0f192a7`](https://github.com/haydenbleasel/ultracite/commit/0f192a7): `ultracite init` no longer wipes an existing Biome config it can't read. Previously a `biome.json` or `biome.jsonc` with a syntax error, or a nested monorepo config with `"extends": "//"`, was treated as empty and replaced with just the Ultracite `extends`, losing every other setting. Now: - A config with a syntax error is left unchanged, with a warning asking you to fix it and re-run `init`. - A nested config that extends the root config (`"extends": "//"`) is left unchanged, since the Ultracite presets belong in the root config. - A string `extends` is turned into a list that also includes the Ultracite presets. - Updates edit the file in place, so comments and formatting in `biome.jsonc` are preserved. `ultracite doctor` and the `check`/`fix` resolution check now follow a nested config that extends `"//"` to the root config, instead of warning that the nested config doesn't extend `ultracite/biome/core`. - [`c68ba48`](https://github.com/haydenbleasel/ultracite/commit/c68ba48): `ultracite check` and `ultracite fix` handle their arguments and missing tools more reliably: - `check` now treats explicit files the way `fix` does. Oxlint only gets files it can lint, Prettier runs with `--ignore-unknown`, and oxfmt with `--no-error-on-unmatched-pattern`. Before, `ultracite check README.md` or `ultracite check Dockerfile src/index.ts` failed even though nothing was wrong. - Linter flags that take a value keep it, even when the value looks like a file: `--tsconfig tsconfig.json`, `-c .oxlintrc.json`, `--config-path biome.json`, `--only lint/suspicious/noDebugger`, `--since origin/main` and similar. Before, the value was treated as a lint target, so `ultracite fix --tsconfig tsconfig.json` skipped Oxlint entirely and only formatted `tsconfig.json`. Ultracite's own `--claude`, `--codex`, `--hook` and `--unsafe` never take a value, so the next argument is always a target. - `ultracite fix --unsafe` with the ESLint toolchain no longer fails with ESLint's "Invalid option '--unsafe'". ESLint has no unsafe fixes, so the flag is dropped with a warning. - A linter that isn't installed is reported with a plain message instead of a stack trace. The other tools still run first. Stylelint is optional in the ESLint toolchain, as `ultracite doctor` already said, so a project without it now skips CSS linting with a warning instead of failing. "No linter configuration found" is also printed without a stack trace. - Linters installed in the project's `node_modules/.bin` are found even when Ultracite isn't run through a package manager script, `npx` or `bunx`, for example `./node_modules/.bin/ultracite check`. - [`f61f393`](https://github.com/haydenbleasel/ultracite/commit/f61f393): `ultracite init` now looks for existing ESLint, Prettier and Stylelint configs in the same order the tools do, so when a project has more than one, init updates the one the tool actually loads. For example, Prettier reads `.prettierrc.json` before `prettier.config.mjs`, and ESLint reads `eslint.config.js` before `eslint.config.mjs`. Before, init could update a config the tool ignored and leave the active one in place. Stylelint's `.stylelintrc.ts` and `stylelint.config.ts` are now recognised too. - [`242cd2a`](https://github.com/haydenbleasel/ultracite/commit/242cd2a): `ultracite init` now updates an existing `.vscode/settings.json` or `.zed/settings.json` in place, so your comments and formatting are kept. Before, the file was re-serialised as plain JSON, which stripped every comment. A settings file with a syntax error is now left unchanged with a warning. Before, it was rewritten with whatever part the parser could recover, which dropped the rest. For the ESLint toolchain, init now also installs the Prettier VS Code extension (`esbenp.prettier-vscode`), since the settings it writes make Prettier the default formatter. Before, only the ESLint extension was installed, so format-on-save did nothing until you added Prettier yourself. - [`c273393`](https://github.com/haydenbleasel/ultracite/commit/c273393): `ultracite init` now checks every flag value before it changes anything in the project. An unknown value for `--linter`, `--pm`, `--frameworks`, `--editors`, `--agents`, `--hooks`, `--integrations` or `--js-plugins` stops init with a message listing the valid values. Previously a misspelled `--linter` (for example `--linter Biome`) deleted every existing Biome, ESLint, Prettier, Stylelint, Oxlint and oxfmt config file and then crashed. When `--linter` is not passed and init runs without prompts (because of `--quiet`, `CI`, or flags such as `--agents` or `--pm`), it now keeps the linter the project is already set up with and only falls back to Oxlint when there is none. Running `ultracite init --agents universal` on a Biome project no longer migrates it to Oxlint. The interactive linter prompt also preselects the detected linter. - [`3cb2e71`](https://github.com/haydenbleasel/ultracite/commit/3cb2e71): Clearer wording in the CLI: - `ultracite init --help` now lists the valid values for `--pm`, `--linter`, `--frameworks`, `--hooks` and `--integrations`, and explains what `--type-aware` does for Biome and for Oxlint. - The agent rules file says "Oxlint + Oxfmt will catch most mechanical issues automatically" instead of "Oxlint + Oxfmt's linter will catch…". - `init` and `upgrade` say "Using pnpm (detected from the project)" instead of "Detected lockfile", since the package manager can also come from `packageManager`. - `ultracite doctor` spells "unrecognized" consistently, formats commands as code, and describes warnings as "Some checks have warnings" instead of "optional improvements". - [`6ae8be8`](https://github.com/haydenbleasel/ultracite/commit/6ae8be8): The ESLint `nestjs` preset imports `@darraghor/eslint-plugin-nestjs-typed`, but `ultracite init --linter eslint --frameworks nestjs` never installed it, so ESLint failed to load the config with "Cannot find package". `init` now installs the plugin with the preset, and `ultracite upgrade` installs the plugins of every framework preset your `eslint.config.*` imports, so existing NestJS projects pick it up on their next upgrade. - [`a8e83bb`](https://github.com/haydenbleasel/ultracite/commit/a8e83bb): `ultracite init` now migrates an existing `.oxlintrc.json`, `.oxfmtrc.json` or `.oxfmtrc.jsonc` when it sets up Oxlint. Oxlint and oxfmt refuse to load any config when a JSON config sits next to `oxlint.config.ts` or `oxfmt.config.ts`, and init used to write the TS configs beside the JSON ones, so `ultracite check` and `ultracite fix` stopped working. Init now moves the JSON config's settings into the TS config and deletes the JSON file: - `rules`, `overrides`, `env`, `plugins` and other options become properties of the generated config. - `ignorePatterns`, `settings` and `jsPlugins` are added to the ones Ultracite generates instead of replacing them. - Ultracite `extends` entries become presets. Other `extends` paths can't be referenced from a TS config, so init names them in a warning. A JSON config that doesn't parse is left in place, and neither file is written. Re-running `ultracite init` also keeps what you added to `oxlint.config.ts` and `oxfmt.config.ts`: custom `rules`, `overrides`, `ignorePatterns`, `settings` and other properties, extra `extends` entries, your own imports and statements, and comments are carried over while the Ultracite parts are regenerated. Before, both files were regenerated from scratch. A config that doesn't parse is now left unchanged with a warning instead of being overwritten. `ultracite doctor` now fails when a JSON config and a TS config for Oxlint or oxfmt sit side by side, and suggests running `init` to migrate a lone `.oxfmtrc.json`. - [`981ef2f`](https://github.com/haydenbleasel/ultracite/commit/981ef2f): `ultracite init --linter oxlint` no longer adds `"type": "module"` to `package.json`. That field changes how Node loads every `.js` file in the package, so CommonJS files such as a `next.config.js`, `postcss.config.js` or `jest.config.js` using `module.exports` stopped working after init. Instead, init writes the Oxlint and oxfmt configs as `oxlint.config.mts` and `oxfmt.config.mts` when the package isn't an ES module package (no `"type"` or `"type": "commonjs"`). A `.mts` file always loads as an ES module, with no `MODULE_TYPELESS_PACKAGE_JSON` warning on every run, and it works under `"type": "commonjs"`. ES module packages (`"type": "module"`) still get `oxlint.config.ts` and `oxfmt.config.ts`. Re-running init updates an existing config under the name it already has. The one exception is a `.ts` config in a `"type": "commonjs"` package, which Node can't load: init renames it to `.mts` and says so. `ultracite doctor`, linter detection and the stale-config cleanup all recognise the `.mts` names. `doctor` fails a `.ts` config in a CommonJS package, and fails when a `.ts` and an `.mts` config sit side by side. Requires oxfmt >= 0.59.0, the first release that finds `oxfmt.config.mts` on its own. - [`9a9beb0`](https://github.com/haydenbleasel/ultracite/commit/9a9beb0): `ultracite init` is gentler with `package.json`: - It keeps the file's key order, indentation and line endings. Before, every write moved `devDependencies` to the top and pushed keys like `private`, `main` and `exports` to the end. - It no longer overwrites a `check` or `fix` script the project already has (for example `"check": "tsc --noEmit"`). It prints a warning instead, and it only adds the scripts that are missing. Existing scripts that already run Ultracite with extra flags are left as they are. - When switching linters, it only removes the previous linter's packages from `devDependencies`. Packages in `dependencies` and `peerDependencies` stay, such as `prettier` used at runtime or `eslint` as the peer of a published plugin. - With `--skip-install`, the final message now says the dependencies were added to `package.json` instead of claiming they were installed. - [`c3027a5`](https://github.com/haydenbleasel/ultracite/commit/c3027a5): Re-running `ultracite init` no longer silently discards changes to an ESLint, Prettier or Stylelint config that builds on Ultracite's: - `eslint.config.*`: the framework presets it already spreads are kept alongside any newly selected ones, together with your own config objects, imports and a `defineConfig(...)` wrapper. Before, the file was regenerated from the selected frameworks only, dropping earlier presets and every custom rule. - `prettier.config.*`: your options, imports and extra plugins are kept. Framework plugins are added, and `prettier-plugin-tailwindcss` stays last. - Stylelint: a config that already uses `ultracite/stylelint`, including one in `package.json`, is left as it is. A config that doesn't use Ultracite's presets is still replaced, but init now prints a warning naming the file (or the `package.json` key) it replaced. A config that doesn't parse is left unchanged with a warning. With the ESLint toolchain, a `"prettier"` or `"stylelint"` key in `package.json` is now handled by these updates (and reported when replaced) instead of being deleted silently during migration. - [`44d6997`](https://github.com/haydenbleasel/ultracite/commit/44d6997): `ultracite init` no longer creates directories for agent rule files or agent hook configs (such as `.claude/` or `.cursor/`) before checking that the path stays inside the project. When one of those directories was a symlink to somewhere outside the project, init created the missing directories there before it refused to write the file. - [`33a1ccd`](https://github.com/haydenbleasel/ultracite/commit/33a1ccd): `ultracite init --integrations husky --skip-install` no longer replaces an existing `prepare` script in `package.json`. It adds `husky` to the script, as the installing path already did (for example `"prepare": "svelte-kit sync && husky"`). The Lefthook setup messages now name the config file init actually updates or creates, such as `.lefthook.yaml`, instead of always saying `lefthook.yml`. - [`923667b`](https://github.com/haydenbleasel/ultracite/commit/923667b): `ultracite init` no longer overrides a tsconfig that turns `strictNullChecks` off. It leaves an explicit `"strictNullChecks": false`, whether set in the file or in a config it extends, as it is and prints a warning. It also follows `extends`, whether a relative path or a package such as `@tsconfig/strictest`, so a tsconfig that already inherits `strict` or `strictNullChecks` is no longer given a redundant `"strictNullChecks": true`. - [`199974c`](https://github.com/haydenbleasel/ultracite/commit/199974c): `ultracite init` and `ultracite upgrade` now work in Yarn 2+ monorepos. The root install used to pass Yarn 1's `-W` flag, which Yarn 2+ rejects with "Unsupported option name", whenever the Yarn version wasn't named in `package.json`'s `packageManager` field. That happened with `--pm yarn`, with lockfile-only detection, and always in the second half of `upgrade`, which re-ran the new CLI with a bare `--pm yarn`. Ultracite now tells Yarn 2+ apart from Yarn 1 by `.yarnrc.yml` or the lockfile format. `upgrade` only forwards `--pm` to the newly installed CLI when you passed it. `ultracite doctor` (and the check at the end of `upgrade`) no longer fails in Yarn Plug'n'Play projects just because it can't find Ultracite or the tools in `node_modules`. It warns that it can't verify them there instead. - [`c33158d`](https://github.com/haydenbleasel/ultracite/commit/c33158d): Agent hooks set up by `ultracite init --hooks` work in more places and no longer double up. - **GitHub Copilot:** `.github/hooks/ultracite.json` is now written in the format the Copilot CLI and Copilot cloud agent read: `"version": 1` and a camelCase `postToolUse` event. VS Code reads this format too. The previous file, with a PascalCase `PostToolUse` and no `version`, was only picked up by VS Code. Re-running init moves an existing Ultracite hook to the new format instead of keeping both. - **`fix --hook` with Copilot:** the file path is now read from Copilot payloads: `toolArgs.path` from the Copilot CLI (including when `toolArgs` is a JSON string), `tool_input.filePath` from VS Code's edit tools, every file of a `multi_replace_string_in_file` edit, and the file headers of an `apply_patch`. So only the edited files are fixed, not the whole project. These hosts run the hook after every tool, so tools that edit nothing (such as `read_file`, `view` or `bash`) now skip the fix instead of fixing the whole project. - **Re-running init no longer adds a second hook** next to one generated by Ultracite 7.8.2 or earlier: `pnpm fix …`, `bun fix …`, `yarn fix …`, or `npm run fix --skip=…`. That older hook is updated in place, so it stops running a whole-project fix after every edit. - **A hook is now added** even when the settings file mentions `ultracite` somewhere else, such as a Claude Code permission rule like `Bash(npx ultracite check)`. Only existing hook commands are checked. - `fix --hook` now fixes a file at the project root whose name starts with `..`, instead of treating it as outside the project. - **Zed:** the `includePackageJsonAutoImports` preference is now set for vtsls, Zed's default TypeScript and JavaScript language server (`lsp.vtsls.settings`), for both TypeScript and JavaScript. It was previously set under `typescript-language-server`, which Zed doesn't use by default. - [`dc5e18e`](https://github.com/haydenbleasel/ultracite/commit/dc5e18e): Re-running `ultracite init` now updates the Ultracite rules in `AGENTS.md`, `.claude/CLAUDE.md`, `GEMINI.md` and the other shared rule files in place, instead of appending another full copy. - Previously a copy was appended whenever the linter, the package manager or the rules text changed. For example, switching from Biome to Oxlint left instructions for both engines side by side. Duplicate copies written by earlier versions are now removed, and your own content before and after the block is kept. - Files with CRLF line endings keep them, and are no longer duplicated on every run. - The commands in the rules now run the project's installed CLI (`npx ultracite fix`, `yarn ultracite fix`, `pnpm exec ultracite fix`, `bunx ultracite fix`) instead of a dlx runner. For Deno they read `deno run -A npm:ultracite fix`; previously the broken `deno run -A npm: ultracite fix` was written. - **Firebender:** rules are now written to `.firebender/rules/ultracite.mdc` with `alwaysApply: true`, where Firebender reads project rules. They were previously written as Markdown into `firebender.json`, which made that file invalid JSON and overwrote an existing Firebender config. A `firebender.json` that still holds only those Markdown rules is reset to `{}`. - [`2ad7704`](https://github.com/haydenbleasel/ultracite/commit/2ad7704): Fixes for `ultracite fix --claude` and `ultracite fix --codex`: - On a terminal, the ✓/✗ result for every issue is now kept once a file is done. Previously a file with more issues than the terminal had rows kept only the last screenful of results. - In CI logs and other piped output, lint messages are no longer cut off at 80 columns. - The prompt is now sent to the agent CLI on stdin (`claude -p`, `codex exec -`) instead of as a command-line argument. On Windows, an npm-installed CLI runs through a `.cmd` shim, which can cut an argument off at its first newline, so the agent received only the prompt's first line and never saw the file or its issues. - `--codex` now passes `--skip-git-repo-check`, so it also works in a project that isn't a git repository. Previously `codex exec` refused to run there and every file failed. - [`0b0775e`](https://github.com/haydenbleasel/ultracite/commit/0b0775e): The Husky pre-commit hook written by `ultracite init --integrations husky` is more robust. - The hook now runs the project's installed tools (`npx`, `yarn`, `pnpm exec`, `bunx`) instead of `yarn dlx` / `pnpm dlx`. `yarn dlx` does not exist in Yarn 1, so every commit failed with "Ultracite found issues that could not be auto-fixed", and `pnpm dlx` downloaded the latest release instead of the version the project pins. Husky itself is also initialised with the installed binary. - Installing Husky now chains `husky` onto an existing `prepare` script (for example SvelteKit's `svelte-kit sync || echo ''`) instead of replacing it. Choosing Husky and lefthook together no longer leaves only one of them in `prepare`. - When nothing is staged, the hook no longer exits early, so commands you keep after the Ultracite section still run. - Re-running init replaces the Ultracite section of a hook saved with CRLF line endings instead of appending a second one. It also no longer drops the last line of a hook that only mentions "# ultracite" in a comment. Commands after a lint-staged section written by an older version are kept. - [`3862221`](https://github.com/haydenbleasel/ultracite/commit/3862221): `ultracite init --integrations lint-staged` no longer damages or shadows an existing lint-staged config. - An extension-less `.lintstagedrc` written in YAML (which is how lint-staged reads it) is now edited as YAML. Previously it was overwritten with a JSON file holding only the Ultracite task, deleting the user's own tasks, and single-quoted YAML was silently skipped. - YAML configs are edited through the `yaml` Document API, so comments and the rest of the file are kept. - TypeScript configs (`.lintstagedrc.ts`, `.mts`, `.cts` and `lint-staged.config.ts`, `.mts`, `.cts`) and the `lint-staged` key of `package.yaml` are now recognised. Previously init created a `.lintstagedrc.json` next to them, and because lint-staged uses only the first config in a directory, the user's config silently stopped running. - When a config can't be edited automatically (a function-based entry, a CommonJS module that can't be loaded, a syntax error), init now leaves it untouched and prints the command to add, instead of writing a second config file that would replace it. - When both exist, the dedicated config file is updated rather than the `package.json` key, matching the file lint-staged actually uses. - A single command already mapped to the same glob is kept alongside `ultracite fix` instead of being replaced. - The task now runs the project's installed Ultracite (`npx`, `yarn`, `pnpm exec`, `bunx`) instead of `yarn dlx` / `pnpm dlx`, which don't exist in Yarn 1 or download the latest release instead of the pinned one. Re-running init upgrades a `dlx` command written by an earlier version. - [`bffb8dd`](https://github.com/haydenbleasel/ultracite/commit/bffb8dd): Corrected the bundled Ultracite agent skill (`skills/ultracite/SKILL.md`): - It said Oxlint has `github` and `sonarjs` presets that init includes by default. Neither exists. The GitHub, SonarJS and React Doctor rules live in the `ultracite/oxlint/js-plugins` preset (plus `next/js-plugins` and `tanstack/js-plugins`), next to the `anti-slop` and `shadcn` presets, and all of them are opt-in. - The `--js-plugins` init flag is now documented. - The skill now tells agents to run the project's installed CLI (`npx`, `pnpm exec`, `yarn`, `bunx`) rather than `pnpx` or `yarn dlx`. - [`da2934a`](https://github.com/haydenbleasel/ultracite/commit/da2934a): Installing the Ultracite skill from `ultracite init` now works when init runs in a normal terminal. Init runs `skills add haydenbleasel/ultracite` without a terminal attached. When the `skills` CLI needed to ask which agents to install to, or whether to install into the project or globally, it could not show the prompt: - In some cases it cancelled the prompt and exited successfully with nothing installed, so init said "Ultracite skill installed." when the skill wasn't there. - In others it failed, so the install never happened. Init now passes `--yes` and names the agents to install for, so `skills` installs without asking. The skill always goes to the shared `.agents/skills` directory, which Codex, Cursor, GitHub Copilot, Gemini CLI, Amp, Cline, OpenCode and other agents read. It also goes to the skills directory of any agent whose project folder exists (for example `.claude`, `.windsurf`, `.codebuddy` or `.roo`, which init creates when you choose those agents). Init names the agents because otherwise, in a project where `skills` detects no agent, `--yes` would install for every agent it knows. That also created a `.claude/skills` link and a second copy in a top-level `agent/` directory (for the Eve framework). The "install it later" hint still shows the interactive `skills add haydenbleasel/ultracite` command. - [`4941883`](https://github.com/haydenbleasel/ultracite/commit/4941883): `ultracite init` now edits `.pre-commit-config.yaml` and lefthook configs through the `yaml` Document API instead of splicing text, so the result is always valid YAML and comments are kept. - **pre-commit:** a `repos:` list written flush with its key (`- repo:`, the style `pre-commit sample-config` generates) or with four-space indentation no longer turns into invalid YAML that breaks every commit. The file's sequence style is kept. - **lefthook:** a four-space indented `pre-commit:` block, a compact `jobs:` list, or a column-0 comment inside the block no longer produce invalid YAML or a duplicate `jobs:` key. A hook that uses `commands:` gets a `jobs:` list next to it. - **lefthook:** init now finds an existing `.lefthook.yml`, `lefthook.yaml`, `.config/lefthook.yml` (and the other names lefthook reads) and edits it. Previously it created `lefthook.yml`, which lefthook picks first, so the user's own config silently stopped running. A JSON or TOML config is left alone with instructions. - **lefthook:** the job's globs are now `*.js`, `*.ts`, and so on. With lefthook's default matcher, the previous `**/*.js` form skipped root-level files such as `package.json` or `index.ts`. Projects that set `glob_matcher: doublestar` get `**/*.js`. - **lefthook:** re-running init with a different package manager updates the existing job instead of adding a second one. - Both now run the project's installed Ultracite (`npx`, `yarn`, `pnpm exec`, `bunx`) instead of `yarn dlx` / `pnpm dlx`. Re-running init upgrades a hook or job written by an earlier version. - `lefthook install` runs the project's installed lefthook, and the `prepare` script is chained onto an existing one (e.g. `svelte-kit sync || echo '' && lefthook install`) instead of replacing it. - [`9c30c15`](https://github.com/haydenbleasel/ultracite/commit/9c30c15): Raise the `oxlint` peer dependency to `^1.82.0`. The core Oxlint preset configures `no-unmodified-loop-condition` with `checkConditionalExpressions`, an option Oxlint 1.79 to 1.81 reject, so those releases failed with "Failed to parse oxlint configuration file" even though the old `^1.79.0` range allowed them. `ultracite doctor` and your package manager now flag the too-old version instead. Requires oxlint >= 1.82.0 - [`47303f4`](https://github.com/haydenbleasel/ultracite/commit/47303f4): The Biome `jest` preset now declares Jest's globals (`describe`, `it`, `test`, `expect`, `jest`, `beforeEach` and the rest of `globals.jest`) for test files. Jest injects them without imports, so `noUndeclaredVariables` from the core preset reported every one of them in idiomatic Jest tests. The ESLint `jest` preset already declared them. The route-file exemptions in the Biome `remix` and `tanstack` presets (`useFilenamingConvention` off in `routes/`) now cover `.js` and `.jsx` route files as well as `.ts` and `.tsx`. - [`8f236ee`](https://github.com/haydenbleasel/ultracite/commit/8f236ee): The ESLint core preset now lints `.jsx`, `.tsx`, `.mts` and `.cts` files. Its main block previously matched only `.js`, `.mjs`, `.cjs`, `.ts`, `.json` and `.html`, so ESLint skipped `.mts` and `.cts` files entirely ("File ignored because no matching configuration was supplied"), and `.jsx` and `.tsx` files received only the framework preset's rules. `.tsx` files were also parsed by espree, so any TypeScript syntax in them was a parse error. Every TypeScript extension now uses `@typescript-eslint/parser` with type information, and the core rules apply to all of them. Type information now comes from the TypeScript project service (`parserOptions.projectService: true`) instead of a fixed `project: "./tsconfig.json"`. Solution-style tsconfigs (`"files": []` plus `references`, as in the Vite templates) and monorepo packages now resolve their own tsconfig, where previously every file failed to parse. A file that no tsconfig includes still has to be added to one; typescript-eslint reports it as "not found by the project service" (see <https://typescript-eslint.io/troubleshooting/typed-linting/#i-get-errors-telling-me-was-not-found-by-the-project-service-consider-either-including-it-in-the-tsconfigjson-or-including-it-in-allowdefaultproject>). The JavaScript block no longer matches `**/*.json`. espree cannot parse JSON, so every `package.json` and `tsconfig.json` failed with `Parsing error: Unexpected token :`. The ESLint preset does not lint JSON, matching the Oxlint preset. - [`94722fa`](https://github.com/haydenbleasel/ultracite/commit/94722fa): The `eslint.config.mjs` that `ultracite init` writes no longer fails its own lint. Every ESLint preset exported a default named `config`, so `import core from "ultracite/eslint/core"` (and each framework import) tripped `import-x/no-rename-default` twice per preset. Each preset's default export is now named after the identifier the generated config imports it as (`core`, `react`, `tanstack`, …). - [`d9803a6`](https://github.com/haydenbleasel/ultracite/commit/d9803a6): Fix ESLint presets that crashed the whole run or never reached the files they target. - **TanStack:** `@tanstack/start/no-async-client-component` and `@tanstack/start/no-client-code-in-server-component` need type information and aborted ESLint ("You have used a rule which requires type information") on the first `.jsx` or `.tsx` file. They now run only on TypeScript files. The Query, Router and Start rules also apply to plain `.ts`/`.js` modules, where query and mutation options are usually declared, instead of only to `.jsx` and `.tsx`. `sort-keys` is off, and `no-use-before-define` and `unicorn/filename-case` are off in `routes/` directories, matching the Oxlint and Biome TanStack presets (alphabetical option keys break TanStack's type inference, and file routes are mutually recursive and encode the URL in the filename). - **Qwik:** `qwik/valid-lexical-scope` needs type information and crashed ESLint on `.jsx` files. It now runs only on `.tsx` files. - **Jest:** `jest/no-deprecated-functions` threw "Unable to detect Jest version" and crashed ESLint when the `jest` package was not resolvable from the plugin, for example in bun:test projects. The preset now reads the Jest version from the project and falls back to the latest major. - **Cypress:** the block used `globals.cypress`, which does not exist in the `globals` package, so `cy`, `Cypress`, `describe` and `it` were reported by `no-undef`. It now uses `eslint-plugin-cypress`'s own globals config. It also matched only `*.cy.js`, and now covers `*.cy.*` for every JS and TS extension plus files under `cypress/`. - **Storybook:** the block matched only `*.stories.js` and `*.stories.ts`. It now covers `*.stories.*` and `*.story.*` for every JS and TS extension, including `.tsx` and `.jsx`. - [`d6ee272`](https://github.com/haydenbleasel/ultracite/commit/d6ee272): The ESLint `vue`, `svelte` and `astro` presets now parse their files. They registered only the plugin and its rules, never a parser, so ESLint read every `.vue`, `.svelte` and `.astro` file with espree and reported a parse error (`Unexpected token <`) instead of linting it. Each preset now starts from its plugin's own base config (`flat/base` in `eslint-plugin-vue`, `eslint-plugin-svelte` and `eslint-plugin-astro`), which registers `vue-eslint-parser`, `svelte-eslint-parser` or `astro-eslint-parser` from the plugin's dependencies, and parses `<script lang="ts">` blocks with `@typescript-eslint/parser`. The Svelte preset also covers `.svelte.js` and `.svelte.ts` rune modules. In Astro files, client-side `<script>` tags are linted without type information, because those in-memory virtual files cannot be type-checked. - [`f7599ef`](https://github.com/haydenbleasel/ultracite/commit/f7599ef): The ESLint core preset no longer re-enables formatting rules that `eslint-config-prettier` turns off. The unicorn rule set was spread after `eslint-config-prettier`, which switched `unicorn/number-literal-case`, `unicorn/template-indent` and `unicorn/empty-brace-spaces` back on. `unicorn/number-literal-case` demands `0xABCD` while Prettier prints `0xabcd`, so `prettier/prettier` and the unicorn rule reported every hex literal and `eslint --fix` could not satisfy both. `eslint-config-prettier` now applies after every plugin, so `unicorn/number-literal-case` and `unicorn/template-indent` are off. `unicorn/empty-brace-spaces` stays on (Prettier prints empty braces as `{}` too), matching the Oxlint preset. - [`efa80e8`](https://github.com/haydenbleasel/ultracite/commit/efa80e8): The ESLint core preset no longer reports the same problem two or three times on TypeScript files, and no longer flags ambient type-only globals. - `no-undef` and `sonarjs/no-reference-error` are off for `.ts`, `.tsx`, `.mts` and `.cts` files. TypeScript already reports unresolved identifiers, and both rules flagged valid ambient types such as `NodeJS.Timeout` (see the [typescript-eslint FAQ](https://typescript-eslint.io/troubleshooting/faqs/eslint#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors)). - The base `class-methods-use-this`, `consistent-return`, `no-unused-private-class-members`, `prefer-destructuring` and `prefer-promise-reject-errors` rules are off for TypeScript files, because their `@typescript-eslint` extension rules are enabled there. The base rules duplicated every report and ignored the extensions' TypeScript-aware options. - `unused-imports/no-unused-vars` is off. It is a copy of `no-unused-vars` / `@typescript-eslint/no-unused-vars`, which stay on as in the Oxlint preset, so every unused variable was reported twice. `unused-imports/no-unused-imports` stays on for its autofix. - `@typescript-eslint/max-params` is off, matching `max-params` being off in the core presets. It was on with its default limit of 3 parameters for TypeScript files only. - [`9ae95d1`](https://github.com/haydenbleasel/ultracite/commit/9ae95d1): Fix false positives in the ESLint `vue`, `svelte` and `astro` presets that appeared once their files were actually parsed. - `vue/block-lang` and `svelte/block-lang` rejected every `<script lang="ts">`, because with no options they only allow blocks without a `lang` attribute. They now allow TypeScript scripts, and `less` and `scss` styles, as well as blocks without `lang`. - Astro's client-side `<script>` tags are linted as virtual files named `1_1.ts`, `2_1.js` and so on, which `github/filenames-match-regex` reported on every page with a script tag. Filename rules are now off for those virtual files. - The Astro preset passes `@typescript-eslint/parser` for the frontmatter explicitly. ESLint's config merge dropped the copy in `eslint-plugin-astro`'s base config, so frontmatter TypeScript parsed only when `@typescript-eslint/parser` happened to resolve from the working directory, and failed with `The keyword 'interface' is reserved` otherwise. - `ultracite init` now installs `eslint-plugin-jsx-a11y` for Astro projects using ESLint. The preset enables `eslint-plugin-astro`'s `astro/jsx-a11y/*` rules, which load that package and reported "you need to install eslint-plugin-jsx-a11y" on every `.astro` file when it was missing. - [`e88e76d`](https://github.com/haydenbleasel/ultracite/commit/e88e76d): The Prettier preset now sets `tailwindFunctions` to `clsx`, `cva`, `tw`, `twMerge`, `cn`, `twJoin` and `tv`, so `prettier-plugin-tailwindcss` sorts Tailwind classes passed to those helpers anywhere in a file, for example `const button = cva("p-4 flex")`. Previously only class strings inside `class`/`className` attributes were sorted with Prettier, while the Oxfmt (`sortTailwindcss.functions`) and Biome (`useSortedClasses`) presets already sorted these helpers. See <https://github.com/tailwindlabs/prettier-plugin-tailwindcss#sorting-classes-in-function-calls>. - [`3a5885e`](https://github.com/haydenbleasel/ultracite/commit/3a5885e): `github/filenames-match-regex` now accepts file-based routing filenames in the ESLint preset too, and Next.js's special pages in both presets. - The page-route regex (Oxlint `js-plugins` and now ESLint `core`) allows a leading underscore, so the Next.js pages-router files `_app`, `_document` and `_error`, which cannot be renamed, are no longer reported. Other names in `pages/` (`BadPage.ts`) and camelCase route params (`[postId]`, which `unicorn/filename-case` rejects too) are still reported. - The ESLint `core` preset now carries the same route exemptions as the Oxlint `js-plugins` preset ([#&#8203;799](https://github.com/haydenbleasel/ultracite/issues/799), [#&#8203;804](https://github.com/haydenbleasel/ultracite/issues/804)). Previously it applied the plain kebab-case regex everywhere and reported SvelteKit's `+page.ts` and `+server.ts`, TanStack Router and React Router files such as `posts.$postId.ts`, and page routes such as `[slug].json.ts` and `[...auth].ts`. - The route-directory exemptions (`github/filenames-match-regex` in Oxlint `js-plugins` and ESLint `core`, plus `unicorn/filename-case` and `no-use-before-define` in the Oxlint and ESLint `tanstack` presets) now cover `.js` and `.jsx` route files as well as `.ts` and `.tsx`. - [`ad2adb0`](https://github.com/haydenbleasel/ultracite/commit/ad2adb0): The Stylelint preset now handles Tailwind CSS v4, SCSS and Less, and skips build output. - **Tailwind CSS v4:** `@theme`, `@utility`, `@variant`, `@custom-variant`, `@slot`, `@plugin` and `@config` are allowed by `at-rule-no-unknown`, alongside the Tailwind v3 at-rules and `@source` and `@reference`. `at-rule-prelude-no-invalid` no longer rejects every `@apply` (or the other Tailwind at-rules' preludes). `custom-property-pattern` accepts theme namespace resets (`--color-*: initial`) and sub-properties (`--text-xl--line-height`). `declaration-property-value-no-unknown` and `function-no-unknown` accept `--spacing()`, `--alpha()`, `--value()`, `--modifier()` and `theme()`. `media-query-no-invalid` accepts `theme()` breakpoints, and `nesting-selector-no-missing-scoping-root` allows `&` inside `@custom-variant`, `@variant` and `@utility`. See <https://tailwindcss.com/docs/functions-and-directives>. - **`import-notation`** is now `"string"`. `stylelint-config-standard`'s `"url"` autofix rewrote `@import "tailwindcss"` to `@import url("tailwindcss")`. - **SCSS and Less:** `.scss` files are parsed with `postcss-scss` and `.less` files with `postcss-less`. Previously every SCSS and Less file failed with `CssSyntaxError` (for example on `//` comments or mixin calls). The CSS-only rules that cannot understand preprocessor syntax (unknown at-rules such as `@use`, `@include` and `@mixin`, `$variable` and `@variable` values, Sass and Less built-in functions, `//` comments) are relaxed for those files. `ultracite init` now installs `postcss-scss` and `postcss-less` with the ESLint toolchain. - **`.sass`:** the indented Sass syntax has no maintained PostCSS parser, so `ultracite check` and `ultracite fix` no longer pass `.sass` files to Stylelint, where every one failed to parse. - **Ignores:** `ignoreFiles` now uses the shared ignore list (`dist`, `build`, `.next`, `coverage`, `storybook-static` and so on). Stylelint does not read `.gitignore`, so it previously linted generated CSS. - **Prettier:** `prettier/prettier` is now enabled. The preset loaded `stylelint-prettier` but never turned its rule on. - `ultracite check` and `ultracite fix` now escape glob characters in directory arguments before passing them to Stylelint. A directory such as `app/(marketing)` previously matched no files. - [`89989df`](https://github.com/haydenbleasel/ultracite/commit/89989df): Test-file overrides in every preset now match `.mts`, `.cts`, `.mjs` and `.cjs` test files as well as `.ts`, `.tsx`, `.js` and `.jsx`. The globs were `**/*.{test,spec,test-d,spec-d}.{ts,tsx,js,jsx}` and `**/__tests__/**/*.{ts,tsx,js,jsx}`, so a `sum.test.mts` file got none of the test-file relaxations and none of the Jest or Vitest rules. For example, `test.only` in a `.test.mts` file was not reported by `vitest/no-focused-tests` or `jest/no-focused-tests`. This covers the Oxlint `core`, `js-plugins`, `jest` and `vitest` presets, the Biome `core` preset, and the ESLint `core`, `jest` and `vitest` presets. - [`4d28cf9`](https://github.com/haydenbleasel/ultracite/commit/4d28cf9): The Oxlint `vue` preset now lists every non-nursery Vue rule Oxlint implements, like the other framework presets. It previously enabled 18 of them. Among the 27 newly enabled rules are `vue/valid-define-props`, `vue/valid-define-emits`, `vue/no-export-in-script-setup`, `vue/no-lifecycle-after-await`, `vue/no-arrow-functions-in-watch`, `vue/no-side-effects-in-computed-properties`, `vue/require-typed-ref`, `vue/define-props-destructuring` and the `vue/no-deprecated-*` rules. `vue/max-props` is off in both the Oxlint and ESLint presets, because its default allows a single prop per component. The Oxlint `vitest` preset now enables `vitest/consistent-test-it`, the one Vitest rule it was missing (the ESLint preset already had it). Vue files whose names Nuxt and file-based Vue Router require (`pages/**`, `layouts/**`, `error.vue` and `app.vue`) are exempt from `useVueMultiWordComponentNames` in the Biome preset and from `vue/multi-word-component-names` in the ESLint preset. Previously `pages/index.vue`, `layouts/default.vue` and `error.vue` were always reported. ### [`v7.12.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.12.1) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.12.0...ultracite@7.12.1) ##### Patch Changes - [`00dd547`](https://github.com/haydenbleasel/ultracite/commit/00dd547): Agent hooks now fix only the file the agent edited. The generated hook command passes a new `--hook` flag, and `ultracite fix --hook` reads the agent's payload from stdin: Claude Code and CodeBuddy (`tool_input.file_path`), Cursor (`file_path`) and Windsurf (`tool_info.file_path`). A file outside the project, one that no longer exists, or one the project's linters do not handle is skipped. A payload with no readable file path keeps the previous whole-project run. Re-running `ultracite init` rewrites a hook from an earlier init to the new command, including one generated before this change or for a different package manager or linter. - [`300a814`](https://github.com/haydenbleasel/ultracite/commit/300a814): Update `@biomejs/biome` to 2.5.14. Releases 2.5.13 and 2.5.14 add only nursery rules (14 of them, including `noReturnInFinally`, `noSvelteAtHtmlTags` and `useValidTestTitle`), with no stable-group additions, removals or promotions. The Biome presets deliberately leave nursery rules off, so they are unchanged. - [`b8b183b`](https://github.com/haydenbleasel/ultracite/commit/b8b183b): Update dependencies (`@clack/prompts` 1.8, `empathic` 2.1, `magicast`, `nypm`, `string-width` 8.3, `yaml` and `zod` 4.6). - [`b59b8aa`](https://github.com/haydenbleasel/ultracite/commit/b59b8aa): Update oxfmt to 0.70.0 and re-target the markdown `:::` fence patch. Releases 0.68 through 0.70 change no options; they fix suppression-comment handling, comment placement around operators and `as`/`satisfies`, and several YAML and CSS edge cases. oxfmt 0.69 also ships a native markdown formatter, but `.md` files still go through the Prettier-based path, so the fence patch still applies. - [`548c8b0`](https://github.com/haydenbleasel/ultracite/commit/548c8b0): Update oxlint to 1.85.0. Releases 1.83 through 1.85 add and remove no rules and change no options, so the presets are unchanged. Note that `jest/prefer-strict-equal`, `vitest/prefer-strict-equal`, `vitest/prefer-to-be-truthy` and `vitest/prefer-to-be-falsy` now offer suggestions instead of fixes, so `ultracite fix` reports them rather than rewriting them. `unicorn/consistent-function-scoping` also now catches functions that only capture variables from an outer ancestor scope. - [`0bc6cd6`](https://github.com/haydenbleasel/ultracite/commit/0bc6cd6): Update the ESLint family: `eslint` 10.11, `eslint-plugin-unicorn` 76, `@typescript-eslint/*` 8.70.1, `eslint-plugin-jsdoc` 64.5, `eslint-plugin-astro` 3.2, `eslint-plugin-n` 18.4, `eslint-plugin-vue` 10.11.1, `@tanstack/eslint-plugin-query` 5.104, `@next/eslint-plugin-next` 16.3.6, `@darraghor/eslint-plugin-nestjs-typed` 7.5.6, `eslint-plugin-qwik` 1.20.1, `eslint-plugin-html` 8.2.1 and `eslint-plugin-react-doctor` / `oxlint-plugin-react-doctor` 0.9.14. The ESLint core preset picks up unicorn's ten new JavaScript rules automatically: `no-async-iterator-callback`, `no-unused-builtin-method-return` (which replaces the now-deprecated `no-unused-array-method-return`), `no-unused-iterator-helper`, `no-useless-set-construction`, `no-using-resource-escape`, `prefer-combined-guards`, `prefer-iterator-zip`, `prefer-json-import`, `prefer-temporal-conversion` and `prefer-uint8array-hex`. The CSS-only unicorn rules added in v75 stay off for JavaScript files. unicorn 76 makes `no-immediate-mutation` skip conditional mutations and `no-break-in-nested-loop` skip `continue` by default; the preset keeps those defaults because oxlint's `no-immediate-mutation` behaves the same way and checking `continue` would contradict `prefer-continue`. - [`0bcb2c6`](https://github.com/haydenbleasel/ultracite/commit/0bcb2c6): Update `prettier-plugin-astro` to 1.1.0 (the version `ultracite init` installs for Astro projects with Prettier) and refresh the transitive Prettier lock to 3.9.9. Prettier 3.9.7 through 3.9.9 are formatting fixes with no option changes, so the Prettier preset is unchanged. prettier-plugin-astro 1.1 makes `astroAllowShorthand` tri-state. When it is unset, which is how Ultracite's generated config leaves it, attributes now stay as written instead of `{value}` being expanded to `value={value}`. Set `astroAllowShorthand: false` in your Prettier config to keep the 1.0 behaviour. - [`8b39375`](https://github.com/haydenbleasel/ultracite/commit/8b39375): Update `@shadcn/lint` to 0.2.0 (the version `ultracite init` installs for the opt-in `ultracite/oxlint/shadcn` preset). The release adds Vue and Svelte support and fixes theme, barrel and class-site discovery; the rules and their options are unchanged, so the preset is too. Under Oxlint the plugin reads only the `<script>` blocks of `.vue` and `.svelte` files, not their templates. - [`0bc6cd6`](https://github.com/haydenbleasel/ultracite/commit/0bc6cd6): Update `eslint-plugin-sonarjs` to 4.2.1. The ESLint preset adopts its 16 new rules automatically (Vue, Cypress, Playwright, Testing Library, Vitest, Lodash, jQuery and Axios checks). The `ultracite/oxlint/js-plugins` preset now enables every sonarjs rule that does not need type information, adding 35 rules. These include the 15 new non-type-aware rules and nine test rules that older versions of oxlint's JS plugin bridge could not load. sonarjs 4.2.1 also raised the `no-nested-functions` default threshold from 4 to 5; both presets pin `threshold: 4` to keep the previous strictness. ### [`v7.12.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.12.0) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.11.1...ultracite@7.12.0) ##### Minor Changes - [`1f427d7`](https://github.com/haydenbleasel/ultracite/commit/1f427d7): Add an opt-in `ultracite/oxlint/shadcn` preset for [`@shadcn/lint`](https://github.com/shadcn-ui/lint), shadcn's agent-first linter for Tailwind v4 design systems. All six rules (`no-restyle`, `no-raw-colors`, `no-arbitrary-values`, `no-inline-styles`, `no-unknown-classes`, `require-static-classes`) run at `error` with the upstream `allow: ["layout"]` policy, and the component-authoring rules are relaxed inside `**/components/ui/**`. Enable it with `ultracite init --linter oxlint --js-plugins @shadcn/lint`, or extend it alongside `ultracite/oxlint/core` after installing `@shadcn/lint`. ##### Patch Changes - [`600e991`](https://github.com/haydenbleasel/ultracite/commit/600e991): Accept file-based page route filenames in `github/filenames-match-regex`. Files under `pages/` (Astro, Next.js pages router) now match a bracket-aware pattern, so dynamic, rest and optional parameters such as `[slug].astro`, `[...slug].ts` and `[[...slug]].tsx` pass while non-route names like `BadPage.ts` are still rejected. - [`66f97bb`](https://github.com/haydenbleasel/ultracite/commit/66f97bb): Allow top-level `return` in Astro frontmatter. The core preset now turns off `unicorn/prefer-module` for `**/*.astro` files (the rule cannot be configured to allow only `return`), and keeps `require()`, `module.exports`, `__dirname` and `__filename` flagged there via `import/no-commonjs` and `no-restricted-globals`. ### [`v7.11.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.11.1) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.11.0...ultracite@7.11.1) ##### Patch Changes - [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update oxfmt to 0.67.0 and re-target the markdown `:::` fence patch to the new dist chunk. The release changes no options; it fixes CSS/SCSS/Less comment preservation and a few JSDoc-cast edge cases in member chains. - [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update oxlint to 1.82.0. The release adds and removes no rules, so the presets are unchanged apart from one new option: `no-unmodified-loop-condition` now runs with `checkConditionalExpressions: true` in the oxlint and ESLint core presets, so each branch of a ternary in a loop condition must be modified inside the loop rather than only the expression as a whole. - [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Update the ESLint family: `@angular-eslint/eslint-plugin` 22.5, `@typescript-eslint/*` 8.70, `eslint-plugin-solid` 0.18, `eslint-plugin-vue` 10.11, `eslint-plugin-jsdoc` 64.3.8, `eslint-plugin-cypress` 7.0.2, `@darraghor/eslint-plugin-nestjs-typed` 7.5.2 and `prettier-plugin-astro` 1.0. The dynamic presets pick up the seven new rules automatically: `@typescript-eslint/no-generated-empty-object-type`, `@angular-eslint/reactive-context-must-read-signal`, `vue/no-shadow-native-events`, and Solid's `no-boolean-enumerated-attribute`, `no-store-mutation-outside-setter`, `no-unused-signal` and `no-write-in-pure-computation`. Note that `prettier-plugin-astro` 1.0 is a rewrite on the Astro 7 Rust compiler (Node 22.12+); expect whitespace diffs on first run and mirror any custom `compressHTML` via its new `astroCompressHTML` option. - [`24b2797`](https://github.com/haydenbleasel/ultracite/commit/24b2797): Refresh the stylelint lock to 17.15.0 and enable its new `selector-no-unmatchable` rule, which flags selectors that can never match (for example `label:checked`, `::before:first-child` or `:is(::before)`). - [`a71dda4`](https://github.com/haydenbleasel/ultracite/commit/a71dda4): Stop sorting object keys across the whole TanStack presets, not just route files. TanStack Query mutation options are order-sensitive too: TypeScript infers the `onMutate` context from context-sensitive callbacks in source order, so moving `onError`/`onSettled` above `onMutate` turns the context into `{}` and `ultracite fix` broke type-correct code (`TS2339: Property '...' does not exist on type '{}'`). Mutation and query options live anywhere (hooks, components, colocated files), so the route-file exemption could not cover them. `ultracite/oxlint/tanstack` now sets `sort-keys` to `off` and `ultracite/biome/tanstack` now sets `useSortedKeys` to `off` for all files. - [`a9db61c`](https://github.com/haydenbleasel/ultracite/commit/a9db61c): Disable `github/filenames-match-regex` for file-based route directories (`**/routes/**`) in the oxlint js-plugins preset, matching the existing `unicorn/filename-case` exemption in the TanStack preset. TanStack Router filenames such as `__root.tsx`, `$.tsx`, and `posts.$postId.tsx` no longer fail the GitHub filename rule. Resolves [#&#8203;799](https://github.com/haydenbleasel/ultracite/issues/799). ### [`v7.11.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.11.0) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.8...ultracite@7.11.0) ##### Minor Changes - [`d5d241f`](https://github.com/haydenbleasel/ultracite/commit/d5d241f): Add `ultracite upgrade`, and make version drift between Ultracite and its linter visible instead of a crash. Bumping `ultracite` without bumping the linter fails on the next `check`/`fix` with Biome's `Found an unknown key` error (and the equivalent for ESLint and Oxlint), because each release enables rules from a specific linter version. - `ultracite upgrade` installs the latest `ultracite`, prints a release-notes link for the versions you crossed, then hands off to the freshly installed CLI to reinstall your toolchain at the versions that release was verified with: Biome; ESLint, Prettier, Stylelint and the plugins the preset imports; or Oxlint and Oxfmt. Optional extras already in your `package.json` (framework plugins, Oxlint JS plugins, `oxlint-tsgolint`) are bumped as well. Config files are never rewritten, and the run ends with the same diagnostics as `doctor`. - `ultracite doctor` now checks the installed Biome, ESLint, Prettier, Stylelint, Oxlint and Oxfmt versions against the range this release supports. Too old fails the check and points at `ultracite upgrade`; newer than the verified range only warns. - The supported ranges are declared as optional peer dependencies so package managers warn when they drift: `@biomejs/biome ^2.5.0`, `eslint ^10.0.0`, `prettier ^3.0.0`, `stylelint ^17.0.0`, `oxlint ^1.79.0`, `oxfmt >=0.40.0`. `ultracite init` now installs Prettier and Stylelint from those ranges instead of `latest`. Requires Biome >= 2.5.0, ESLint >= 10.0.0, Prettier >= 3.0.0, Stylelint >= 17.0.0, Oxlint >= 1.79.0 and Oxfmt >= 0.40.0. ##### Patch Changes - [`27d06f2`](https://github.com/haydenbleasel/ultracite/commit/27d06f2): Update dependencies (`@clack/prompts`, `semver`, `zod`, ESLint plugins). - [`d322691`](https://github.com/haydenbleasel/ultracite/commit/d322691): Default `ultracite init` to Oxlint + Oxfmt when `--linter` is omitted in quiet or non-interactive mode - [`c677cf5`](https://github.com/haydenbleasel/ultracite/commit/c677cf5): Recommend Oxlint + Oxfmt in the `ultracite init` linter prompt and list it first - [`c5be848`](https://github.com/haydenbleasel/ultracite/commit/c5be848): Disable `no-use-before-define` in TanStack Router route files for the oxlint tanstack preset. File routes are mutually recursive (`Route` references the component, and the component calls `Route.useParams()`), so no declaration order could satisfy the rule. ### [`v7.10.8`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.8) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.7...ultracite@7.10.8) ##### Patch Changes - [`2a43fdd`](https://github.com/haydenbleasel/ultracite/commit/2a43fdd): Turn off `unicorn/prefer-reflect-apply` in the `ultracite/oxlint/anti-slop` preset. When extended after `ultracite/oxlint/core`, the core rule recommended rewriting `Function#apply()` to `Reflect.apply()`, which anti-slop's `no-reflect-apply` then rejected, leaving no way to satisfy both. Direct-call guidance for `.apply()` still comes from `eslint/prefer-spread` and `eslint/no-useless-call`. - [`03196df`](https://github.com/haydenbleasel/ultracite/commit/03196df): Update `@biomejs/biome` to 2.5.12. Releases 2.5.10 through 2.5.12 only add nursery rules, which the Biome presets exclude, so the presets are unchanged. The releases also carry linter and formatter fixes, including fewer `noUnusedVariables` false positives on merged interfaces, namespaces, and overload type parameters, an unsafe-by-default fix for `noThisInStatic`, and a large batch of Astro expression parsing fixes. - [`031b867`](https://github.com/haydenbleasel/ultracite/commit/031b867): Update oxfmt to 0.66.0. The 0.65 and 0.66 releases are formatter fixes only, mainly around comment placement between a statement head and its body, suppressed statements (decorators, typecast parens, semicolons), custom side-effect groups in `sortImports`, CommonMark list interruption in JSDoc, and trailing whitespace in YAML block scalars. The `:::` container-directive fence patch is re-targeted to the new markdown bundle; the patched code itself is unchanged. - [`54affee`](https://github.com/haydenbleasel/ultracite/commit/54affee): Update oxlint to 1.81.0. The 1.80 and 1.81 releases add no rules and remove none, so the presets are unchanged and the peer range stays at ^1.79.0. Notable fixes carried in: `no-use-before-define` now runs on JS and JSX files, `object-shorthand` preserves `__proto__` semantics, `unicorn/prefer-math-min-max` no longer applies an unsafe autofix, and JS plugin diagnostics with invalid or reversed locations are clamped instead of crashing. - [`0b058d1`](https://github.com/haydenbleasel/ultracite/commit/0b058d1): Fix `ultracite fix --codex` failing on recent Codex CLI releases. The Codex adapter invoked `codex exec --full-auto`, a flag Codex has since removed, so every attempt failed at argument parsing. It now runs `codex exec --sandbox workspace-write`, the equivalent non-interactive, workspace-scoped mode, which is also accepted by older Codex versions. Resolves [#&#8203;794](https://github.com/haydenbleasel/ultracite/issues/794). - [`e2346bb`](https://github.com/haydenbleasel/ultracite/commit/e2346bb): Update the ESLint family to latest: eslint 10.9.1, typescript-eslint 8.69.0, eslint-plugin-unicorn 74, eslint-plugin-solid 0.17, eslint-plugin-jsdoc 64.3.5, eslint-plugin-react-doctor and oxlint-plugin-react-doctor 0.9.13, globals 17.12, and the angular, nestjs-typed, next, tanstack-query, cypress, html, jest and storybook plugins. The dynamic presets pick up the new rules automatically: the solid preset gains the eleven rules added in eslint-plugin-solid 0.16 and 0.17 (`removed-api`, `no-single-arg-create-effect`, `no-accessor-as-prop`, `valid-use-server`, `require-async-server-function`, `no-invalid-server-capture`, `no-browser-globals-in-server-function`, `no-module-scope-reactive-primitive`, `no-restated-default-options`, `prefer-onSettled-for-side-effects`, `prefer-structured-class`), which only report Solid 2.0 issues when `settings.solid.version` is set to 2 and stay silent on Solid 1.x code; the nestjs preset gains `forward-ref-injection-should-use-wrapper-type`, `swagger-file-upload-should-be-documented` and `uploaded-file-should-be-validated`. The curated jsdoc and react-doctor lists are unchanged. No enabled rule was removed or deprecated, and the ESLint/oxlint parity check still passes. - [`7b0456e`](https://github.com/haydenbleasel/ultracite/commit/7b0456e): `ultracite fix` now runs lint fixes before the formatter: oxlint before oxfmt, and ESLint then Stylelint before Prettier. A fixer can insert unformatted code, such as the braces `curly` adds, the imports `consistent-type-specifier-style` splits, or the font names Stylelint requotes, and running the formatter first left that code unformatted until the next run. Fixer-inserted code is now formatted in the same run. The `--claude` and `--codex` agent passes follow the same order. `unicorn/no-nested-ternary` is now off in the oxlint and ESLint presets: its fixer adds parentheses that oxfmt and Prettier remove, so the two tools rewrote the file on every run. The core `no-nested-ternary` rule still reports nested ternaries. - [`8ddc078`](https://github.com/haydenbleasel/ultracite/commit/8ddc078): Enable three rules added in Stylelint 17 in the Stylelint preset: `selector-no-deprecated` and `selector-no-invalid` report selectors that CSS has dropped or that cannot parse, and `relative-selector-nesting-notation` is set to `explicit`, so nested relative selectors are written `& > b` rather than `> b`. The `property-layout-mappings`, `unit-layout-mappings` and `value-keyword-layout-mappings` rules are deliberately left off, since they reject every physical property, unit and keyword and can only autofix with a per-project `languageOptions.directionality` setting. The repo's own Stylelint lock is refreshed from 16.26.1 to 17.14.1, which the config packages already required; `ultracite init` already installs `stylelint@latest` so users are unaffected by the lock change. - [`4609d79`](https://github.com/haydenbleasel/ultracite/commit/4609d79): Update the vendored `anti-slop` Oxlint plugin to upstream v0.1.2 (commit `e8c4880`). The rule set is unchanged; this picks up a round of correctness fixes: `no-known-value-widening` now also reports known values passed into local `unknown`-typed type predicates, `no-object-parameters`, `no-unknown-parameters`, `no-unknown-returns` and `no-unknown-type-aliases` resolve scoped and transparent generic aliases (including block-scoped aliases and forward references), `no-unknown-returns` covers `PromiseLike<unknown>`, `no-unsafe-dictionary-type` allows generic constraints such as `T extends Record<string, unknown>`, `no-runtime-typeof` always allows existence probes against `"undefined"`, `no-shape-in-symbol-names` allows static member reads such as Zod's `schema.shape`, and `require-safety-comment-for-type-assertion` rejects empty justifications and gains a `markers` option (default `["SAFETY"]`). Upstream also added a separate opt-in `anti-slop-effect` plugin for Effect projects, which is not vendored. ### [`v7.10.7`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.7) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.6...ultracite@7.10.7) ##### Patch Changes - [`15f7ae0`](https://github.com/haydenbleasel/ultracite/commit/15f7ae0): Add support for the Aube package manager: `ultracite init --pm aube` is now accepted and projects with an `aube-lock.yaml` lockfile are detected automatically - [`1afc8fe`](https://github.com/haydenbleasel/ultracite/commit/1afc8fe): Re-declare selected Oxlint JS plugins on the root config so dependency analyzers see them. `ultracite init --linter oxlint --js-plugins ...` now generates `const jsPlugins = selectJsPlugins([...])` and adds `jsPlugins: jsPlugins.jsPlugins` to the root config (also when the full `ultracite/oxlint/js-plugins` preset is extended). Knip only resolves `jsPlugins` from the root Oxlint config and never walks `extends`, so `eslint-plugin-github`, `eslint-plugin-sonarjs`, and `oxlint-plugin-react-doctor` were reported as unused devDependencies. Oxlint dedupes the plugin between the root and the extended preset, so linting is unchanged. Also fix `ultracite update` dropping the `js-plugins` preset from `extends` when the config used the documented `import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"` form: the import parser only matched bare default imports. The regenerated full-preset config keeps `settings: jsPluginSettings` on the root as well. - [`20b06bf`](https://github.com/haydenbleasel/ultracite/commit/20b06bf): Ignore `.alchemy` across all linters and formatters. Alchemy (alchemy.run) writes local state and generated bindings to a `.alchemy` directory. It is now part of the shared ignore patterns synced into Biome's `files.includes` and imported by oxlint, oxfmt, and ESLint, and the Stylelint preset ignores it via `ignoreFiles`. Prettier needs no change: it already respects `.gitignore`/`.prettierignore`. - [`6e9286c`](https://github.com/haydenbleasel/ultracite/commit/6e9286c): Run `lefthook install` during `ultracite init` through the same spawn adapter as every other tool invocation instead of `execSync`, so it no longer goes through a shell and gets the same Windows command resolution as `husky`, the linters, and editor extension installs. - [`8b24f34`](https://github.com/haydenbleasel/ultracite/commit/8b24f34): Add support for the Nub package manager: `ultracite init --pm nub` is now accepted and projects with a `nub.lock` lockfile are detected automatically (requires nypm ^0.6.9) - [`240cb6b`](https://github.com/haydenbleasel/ultracite/commit/240cb6b): Install into the workspace root correctly for Nub and Aube monorepos: nypm emits no root selector for them, so `nub add` ran without `-w` and was refused. Ultracite now hands nypm pnpm's flag set for these pnpm-compatible CLIs, producing `nub add --workspace-root --save-dev ultracite` - [`44ecbba`](https://github.com/haydenbleasel/ultracite/commit/44ecbba): Add Vitest type-test files (`**/*.{test-d,spec-d}.{ts,tsx,js,jsx}`) to the test-file globs so the shared test relaxations and the Vitest rule overrides apply to them, and enable the Vitest plugin's `typecheck` setting in the ESLint preset so `expectTypeOf`/`assertType` count as assertions. - [`7ba6bb8`](https://github.com/haydenbleasel/ultracite/commit/7ba6bb8): Package the reusable Ultracite agent skill with the npm distribution. ### [`v7.10.6`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.6) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.5...ultracite@7.10.6) ##### Patch Changes - [`972b946`](https://github.com/haydenbleasel/ultracite/commit/972b946): Update the oxlint presets for oxlint 1.79: replace the removed `react/react-compiler` rule with the 22 new React Compiler rules in the react preset, add `jsdoc/no-blank-blocks` and `one-var` to the core preset (mirrored in the ESLint presets), and require oxlint ^1.79.0 - [`2d5bbdb`](https://github.com/haydenbleasel/ultracite/commit/2d5bbdb): Declare the `jsPluginSettings` named export in the `ultracite/oxlint/js-plugins` type declarations, so the documented (and `ultracite init`-generated) `import jsPlugins, { jsPluginSettings } from "ultracite/oxlint/js-plugins"` type-checks ([#&#8203;773](https://github.com/haydenbleasel/ultracite/issues/773)) - [`56aef65`](https://github.com/haydenbleasel/ultracite/commit/56aef65): Refresh the toolchain versions that `ultracite init` installs into projects: `@biomejs/biome` 2.5.9, the ESLint plugin family (including eslint-plugin-cypress 7, eslint-plugin-jsdoc 64, eslint-plugin-solid 0.15, and eslint-plugin-unicorn 73 — the dynamic presets adopt their new rules automatically), and `prettier-plugin-svelte` 4.1.1 / `prettier-plugin-tailwindcss` 0.8.1 ### [`v7.10.5`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.5) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.4...ultracite@7.10.5) ##### Patch Changes - [`8df6ad0`](https://github.com/haydenbleasel/ultracite/commit/8df6ad0): Offer the vendored `anti-slop` Oxlint preset during `ultracite init` — it now appears in the JS-plugins prompt when you pick Oxlint, and non-interactive setup accepts it via `--js-plugins anti-slop`. Selecting it adds `ultracite/oxlint/anti-slop` to the generated config's `extends`; since the preset is vendored inside Ultracite, nothing extra is installed. - [`cd229e9`](https://github.com/haydenbleasel/ultracite/commit/cd229e9): Bump the `oxlint-plugin-react-doctor` pin from `^0.7.1` to `^0.9.12`, so `ultracite init` installs the current plugin. All react-doctor rules enabled by the js-plugins presets still exist in 0.9.12, and the ported rules run in curated mode via the settings shipped alongside this release ([#&#8203;771](https://github.com/haydenbleasel/ultracite/issues/771)). - [`e1ac886`](https://github.com/haydenbleasel/ultracite/commit/e1ac886): Pin React Doctor's ported rules to their framework-aware "curated" mode ([#&#8203;771](https://github.com/haydenbleasel/ultracite/issues/771)). react-doctor 0.9.x rewrote its ported oxc/react-refresh rules — notably `only-export-components` — with a stripped-down default mode: no framework detection, no route-file skipping, and `allowConstantExport` off, so Next.js route-segment exports like `export const dynamic = "force-static"` or `metadata` were flagged as non-component exports in every route file. The ESLint react preset now sets `settings["react-doctor"].portedRuleMode: "curated"`, and generated oxlint configs apply a new `jsPluginSettings` export from `ultracite/oxlint/js-plugins` on the root config (oxlint does not merge `settings` from extended configs, so the setting cannot ride along inside the preset). If you extend the js-plugins preset manually, add `settings: jsPluginSettings` to your root oxlint config. - [`c27fe36`](https://github.com/haydenbleasel/ultracite/commit/c27fe36): Generate oxlint configs that enable a subset of the JS plugins via a new `selectJsPlugins` export from `ultracite/oxlint/js-plugins`, instead of inlining the filtering logic into the generated file. The inlined block contained a `typeof` check that user-side lint presets flagged (`anti-slop/no-runtime-typeof`, [#&#8203;770](https://github.com/haydenbleasel/ultracite/issues/770)); the generated config is now a one-line extend, is emitted already formatted (including the previously missing blank line after imports), and re-running `ultracite init` migrates existing configs with the old inlined block automatically. - [`0616523`](https://github.com/haydenbleasel/ultracite/commit/0616523): Update the vendored `anti-slop` Oxlint plugin to upstream commit `446268e`, picking up fixes to `no-object-parameters` and `no-unknown-returns` (respect lexical type binders in alias resolution) and a new `allowInTypeGuards` option on `no-runtime-typeof`. The `ultracite/oxlint/anti-slop` preset enables `allowInTypeGuards`, so `typeof` checks inside type predicate functions (`(x): x is T`) no longer need disable comments — predicates are the named-boundary pattern the rule pushes toward ([dmmulroy/anti-slop#10](https://github.com/dmmulroy/anti-slop/issues/10)). ### [`v7.10.4`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.4) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.3...ultracite@7.10.4) ##### Patch Changes - [`417a85a`](https://github.com/haydenbleasel/ultracite/commit/417a85a): Add an opt-in `ultracite/oxlint/anti-slop` preset that ships a vendored, self-contained build of the [anti-slop](https://github.com/dmmulroy/anti-slop) Oxlint plugin — fifteen rules that reject low-evidence TypeScript and JavaScript patterns (unjustified type assertions, `unknown` leaking through signatures, `Reflect`-based access, module mocking, and more). Extend it alongside `ultracite/oxlint/core`; nothing extra to install. The preset also turns off two core rules that conflict with anti-slop's widening checks (`typescript/consistent-indexed-object-style` and `unicorn/no-immediate-mutation`) when extended after core. - [`4d3fab8`](https://github.com/haydenbleasel/ultracite/commit/4d3fab8): Move `suspicious/useArraySortCompare` from the Biome core config to the opt-in type-aware config. The rule is in Biome's `types` domain — it type-infers the receiver of every method call before checking the method name, which made `ultracite check` up to \~260x slower on projects with expensive library types (zod, better-auth, Prisma). It now only runs when type-aware linting is explicitly enabled, alongside the other type/project-domain rules. Fixes [#&#8203;768](https://github.com/haydenbleasel/ultracite/issues/768). ### [`v7.10.3`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.3) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.2...ultracite@7.10.3) ##### Patch Changes - [`a1fa9c4`](https://github.com/haydenbleasel/ultracite/commit/a1fa9c4): Replace the hand-rolled package `exports` map matching in the config-resolution doctor check with the resolve.exports library, which implements Node's full `PACKAGE_TARGET_RESOLVE` algorithm (wildcard patterns, key-order precedence, conditional exports, and array fallbacks). The manual `node_modules` walk is kept intentionally — it exists to avoid Bun's auto-install cache resolving specifiers the project's own `node_modules` can't. - [`414ea80`](https://github.com/haydenbleasel/ultracite/commit/414ea80): Replace the hand-rolled monorepo workspace scan in framework detection with the find-workspaces library. Workspace declarations from package.json (array and yarn-classic object form) and pnpm-workspace.yaml — including negated globs — are now resolved by the library instead of manual pattern collection and globbing, and lerna/bolt monorepos are picked up as well. - [`a9a1989`](https://github.com/haydenbleasel/ultracite/commit/a9a1989): Replace the hand-rolled upward directory walks in `findNearestFile` and `detectLinter` with the empathic library's `find.any`, which checks candidate names in order within each directory before moving to the parent — the same per-directory precedence the previous implementation enforced manually. - [`27b2707`](https://github.com/haydenbleasel/ultracite/commit/27b2707): Use magicast to update ESM lint-staged config files during `ultracite init`. The config is now edited as an AST instead of being imported and re-serialized, so comments and function-valued entries elsewhere in the config survive the update, and the user's config code is no longer executed. If the Ultracite glob pattern is already owned by a non-array value, or the config isn't a mergeable object literal (e.g. `defineConfig(...)`), init warns and leaves the file untouched instead of rewriting it. CommonJS configs keep the previous behavior. - [`f2529b8`](https://github.com/haydenbleasel/ultracite/commit/f2529b8): Rewrite the agent-fix progress renderer on top of log-update, cli-truncate, and string-width. log-update now owns the in-place block rewriting that was previously done with manual cursor-up/clear-line escape sequences, and line truncation is measured by display width instead of code units — so lint messages containing emoji or CJK text can no longer overflow the terminal row and corrupt the animated block. - [`277b9d6`](https://github.com/haydenbleasel/ultracite/commit/277b9d6): Replace the hand-rolled child-process handling in the agent fix runner with execa. The timeout → SIGTERM → grace period → SIGKILL escalation, stderr capture, and spawn-failure handling now use execa's `timeout` and `forceKillAfterDelay` options, which are battle-tested across platforms (including Windows kill semantics the manual implementation didn't cover). Behavior is unchanged: agent runs still time out after 5 minutes, escalate to SIGKILL after a 10-second grace period, and report a capped stderr tail. - [`1614a80`](https://github.com/haydenbleasel/ultracite/commit/1614a80): Drop the direct cross-spawn dependency: all synchronous process spawning (linter runs, tool version checks, editor extension installs, skill installs) now goes through a small adapter over execa's sync API, which owns the Windows spawn semantics cross-spawn provided. The adapter preserves the spawnSync result shape (`status`/`signal`/`error`/`stdout`), always disables shell interpretation, and always decodes output as UTF-8. execa was already a dependency for the agent fix runner, so this consolidates on one process-spawning library. - [`ac114b4`](https://github.com/haydenbleasel/ultracite/commit/ac114b4): Replace the glob dependency with fast-glob for the tsconfig.json scan during init. fast-glob was already in the dependency tree via find-workspaces, so this drops glob's transitive dependencies (minipass, path-scurry, etc.) from the install without changing behavior. ### [`v7.10.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.2) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.1...ultracite@7.10.2) ##### Patch Changes - [`1c48c68`](https://github.com/haydenbleasel/ultracite/commit/1c48c68): Enable Tailwind CSS class sorting (`sortTailwindcss`) in the Oxfmt preset. Classes in `class`/`className` attributes and in `clsx`, `cva`, `tw`, `twMerge`, `cn`, `twJoin`, and `tv` calls are now sorted using the same algorithm as `prettier-plugin-tailwindcss`, matching the behavior of the Prettier preset (which always loads the Tailwind plugin) and the Biome preset's `useSortedClasses` rule. Projects without Tailwind installed are unaffected beyond class strings being sorted against the default theme, and oxfmt versions older than 0.35.0 ignore the option. - [`dc78be4`](https://github.com/haydenbleasel/ultracite/commit/dc78be4): Stop sorting TanStack route option keys in route files. TanStack Router's route option types are order-sensitive (`head`/`component` infer `loaderData` from properties declared before them), so the Biome `useSortedKeys` source action rewrote `createFileRoute` literals into an order that breaks type inference (`loaderData` becomes `never`). The Biome TanStack preset now disables `useSortedKeys` for route files, and the oxlint TanStack preset disables `sort-keys` there so route files aren't caught between it and `react-doctor/tanstack-start-route-property-order`. ### [`v7.10.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.1) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.10.0...ultracite@7.10.1) ##### Patch Changes - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix several agent fix mode (`fix --claude`/`--codex`) issues: runs no longer abort with ENOBUFS when linter JSON output exceeds 1MB, user-supplied format/reporter flags can no longer override the JSON reporter and break parsing, a stuck agent process is force-killed 10 seconds after the timeout instead of hanging forever, and the progress renderer no longer garbles TTY output when file paths and rule names exceed the terminal width. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Biome config migration leaving the legacy bare `"extends": ["ultracite"]` form in place, which breaks Biome's module resolution since the package has no root export. It's now mapped to `ultracite/biome/core`. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite doctor` reporting spurious failures: config checks now walk up parent directories (matching `check`/`fix` and the linters themselves) so monorepo packages inheriting a root config pass, `.oxlintrc.json` is accepted as a valid oxlint config (with a migration suggestion), and Prettier/Stylelint configs declared via `package.json` keys are recognized. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite init` corrupting existing Prettier/Stylelint/ESLint configs by writing an ESM module into JSON/YAML/TOML/CJS config files (e.g. `.prettierrc`, `eslint.config.cjs`). Updates now write the default `.mjs` config instead and remove the incompatible file so it can't shadow the new one. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite check`/`fix` misrouting space-separated flag values (e.g. `--max-warnings 10`) into the file list, which scrambled the underlying linter invocation and made formatters fail on bogus targets. Positional files listed before a `--` separator are also kept as lint targets instead of being reclassified as passthrough, which could silently widen formatter runs to the whole project. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Lefthook and pre-commit YAML updates silently doing nothing on common config shapes: the Lefthook job is now inserted correctly when `jobs:` isn't the first key under `pre-commit:` (and no longer matches a `jobs:` key in a different hook), `repos: []` in `.pre-commit-config.yaml` is handled, and shapes that can't be safely edited produce a warning instead of writing the file back unchanged. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix the Husky integration overwriting an existing `.husky/pre-commit` hook: `ultracite init` ran `husky init`, which unconditionally replaces the hook with `npm test`. It now runs plain `husky` to set up the hooks infrastructure without touching the hook file. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix `ultracite init` destroying user files it couldn't parse or merge: unparseable `tsconfig.json` files are no longer replaced with a minimal config, unparseable `.vscode`/`.zed` settings are no longer overwritten wholesale, and lint-staged configs with function-valued entries are left untouched — all now warn and skip instead. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix re-running `ultracite init` on an oxlint setup silently enabling the full js-plugins preset — the previously selected JS plugins are now preserved when no new selection is made. Init also no longer flips an explicit `"type": "commonjs"` in package.json to `"module"`; it warns instead. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix switching linters removing `storybook` from the project's dependencies. It was swept into the removal set as a peer of `eslint-plugin-storybook`, but it's a user-facing tool a project may use independently of linting. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix Stylelint target generation dropping directories with a dot in their name (e.g. `app.web`) and producing non-matching globs from Windows-style backslash paths. Framework detection also handles negated workspace patterns (`!packages/legacy`) again. - [`d018b7f`](https://github.com/haydenbleasel/ultracite/commit/d018b7f): Fix the CLI becoming a silent no-op (exiting 0 without linting anything) when a generic `TEST` environment variable is set, as is common in CI matrices. The internal test guard now uses `ULTRACITE_TEST`. - [`36c7b80`](https://github.com/haydenbleasel/ultracite/commit/36c7b80): Move [@&#8203;typescript-eslint/utils](https://github.com/typescript-eslint/utils) from dependencies to devDependencies. It was accidentally shipped as a runtime dependency in 7.9.0, pulling eslint and the typescript-eslint packages into every consumer's install (including oxlint-only setups) via npm's automatic peer dependency installation. Nothing in the published package imports it — it only exists to support the workspace-internal rule-parity script. ### [`v7.10.0`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.10.0) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.4...ultracite@7.10.0) ##### Minor Changes - [`cd0a36c`](https://github.com/haydenbleasel/ultracite/commit/cd0a36c): Add `--claude` and `--codex` flags to `ultracite fix`. After the normal autofix pass, remaining diagnostics are handed to the Claude Code or Codex CLI non-interactively, one agent run per affected file, with a live per-issue spinner that flips to ✓/✗ once the fix is verified by a re-lint. Fixes that don't survive verification are retried (up to 3 attempts per file) with the fresh diagnostics and feedback that the previous approach failed. Works with all three linter modes (Oxlint, Biome, ESLint); exits non-zero if any issues remain, matching the plain `fix` contract. - [`e089510`](https://github.com/haydenbleasel/ultracite/commit/e089510): Scope React Doctor's framework-specific rules to per-framework add-on presets ([#&#8203;752](https://github.com/haydenbleasel/ultracite/issues/752)) The `ultracite/oxlint/js-plugins` preset no longer enables React Doctor's `nextjs-*` and TanStack (`query-*`, `tanstack-start-*`) rules for every consumer. Rules like `nextjs-no-img-element` and `tanstack-start-no-anchor-element` fire on plain `<img>`/`<a>` JSX and recommend framework replacements, which falsely errored in Vite + React and other non-Next/non-TanStack projects. Those rules now live in two new add-on presets: - `ultracite/oxlint/next/js-plugins` - `ultracite/oxlint/tanstack/js-plugins` `ultracite init` wires the matching add-on automatically when you select the framework together with `oxlint-plugin-react-doctor`. If you manage `oxlint.config.ts` by hand and use Next.js or TanStack, add the matching add-on preset to `extends` alongside `js-plugins` to keep those rules — or re-run `npx ultracite init`. Also fixes re-running `init` on a config that already extends `js-plugins` producing a duplicate `import jsPlugins` declaration. ##### Patch Changes - [`3320cd8`](https://github.com/haydenbleasel/ultracite/commit/3320cd8): Update Biome to 2.5.6. No stable (non-nursery) rules were added, removed, or promoted between 2.5.3 and 2.5.6, so the preset configs are unchanged. - [`477cd6e`](https://github.com/haydenbleasel/ultracite/commit/477cd6e): Update ESLint to 10.8.0 and all ESLint plugins to their latest versions. Highlights: - `eslint-plugin-react-doctor` 0.9.3: the react preset expands from 149 to 417 rules, adopting the upstream `recommended` set (react-router, three.js/r3f, ink, motion, remotion, zustand/valtio/mobx, and more) while excluding rules that duplicate already-enabled `react`, `react-hooks`, and `jsx-a11y` rules. The next preset gains `nextjs-async-dynamic-api-not-awaited` and `nextjs-metadata-url-consistency`; the tanstack preset gains `tanstack-start-missing-scripts`, `query-floating-mutate-async`, and `query-no-mutation-in-effect-as-read`. - `eslint-plugin-unicorn` 72: adds `no-missing-local-resource`, `no-multiple-promise-resolver-calls`, `no-shorthand-property-overrides`, `no-transition-all`, `no-unnecessary-string-trim`, `no-useless-re-export`, `prefer-then-catch`, and `require-frontmatter-fields`. CSS-only rules are excluded from the preset since they fail config validation for JS files. - `eslint-plugin-sonarjs` 4.2: adds 11 rules including `no-fixed-wait-in-tests`, `parameterized-tests`, `assertions-in-test-cases`, `prefer-native-lodash-alternative`, and `explicit-test-skip`. - `typescript-eslint` 8.65: `@typescript-eslint/no-loop-func` and `@typescript-eslint/no-restricted-imports` were deprecated upstream in favor of the base rules, which now apply to TypeScript files. - `eslint-plugin-astro` 3: removes `astro/no-omitted-end-tags` and `astro/valid-compile`. - `eslint-plugin-svelte` 3.22: adds `no-bind-value-on-checkable-inputs` and `no-conflicting-module-names`; `no-restricted-html-elements` is now off because its schema requires a user-supplied element list. - `@angular-eslint/eslint-plugin` 22.1: adds `inject-at-top` and `prefer-service-decorator`. - [`b81578b`](https://github.com/haydenbleasel/ultracite/commit/b81578b): Fix the useSortedPackageJson action not being executed by turning on assist actions for package.json-like files. - [`9ec454a`](https://github.com/haydenbleasel/ultracite/commit/9ec454a): Update oxlint to 1.76.0 and oxfmt to 0.61.0. New stable rules added to the presets: `oxc/bad-match-all-arg`, `id-denylist`, `node/exports-style` (core), `react/function-component-definition` with arrow-function components (react), and `vitest/padding-around-test-blocks` (vitest). `node/no-top-level-await` is off — top-level await is idiomatic in ESM, Astro frontmatter, and build scripts — and the ESLint preset's `n/no-top-level-await` is now off to match. No rules were removed or promoted out of nursery. - [`ba61c02`](https://github.com/haydenbleasel/ultracite/commit/ba61c02): Fix generated oxlint.config.ts accessing plugin.name on ExternalPluginEntry without narrowing the string form, which caused a TypeScript error in projects that type-check the config ([#&#8203;753](https://github.com/haydenbleasel/ultracite/issues/753)) ### [`v7.9.4`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.4) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.3...ultracite@7.9.4) ##### Patch Changes - [`f480c12`](https://github.com/haydenbleasel/ultracite/commit/f480c12): Upgrade Biome to 2.5.3 to fix the LSP scanner deadlock ([#&#8203;10845](https://github.com/biomejs/biome/issues/10845)) where editors get stuck on "Biome is scanning the project". - [`1d70c40`](https://github.com/haydenbleasel/ultracite/commit/1d70c40): Fail fast with an actionable message when Biome can't resolve `ultracite/biome/core`. Biome resolves that config out of the project's `node_modules`, so it errors with an opaque "module not found" whenever Ultracite isn't installed there — a state `npx ultracite check` / `bunx ultracite check` hide, because they run the CLI from a temp cache regardless. `check` and `fix` now detect it before invoking Biome and say what's actually wrong, and `doctor` verifies that Ultracite resolves rather than just appearing in `package.json` ([#&#8203;750](https://github.com/haydenbleasel/ultracite/issues/750)). - [`38d10bc`](https://github.com/haydenbleasel/ultracite/commit/38d10bc): Move Biome's `noUnknownAttribute` rule out of the core preset and into the `react` preset. The rule only recognises React's JSX attribute names, so projects using Solid, Svelte, Vue, or Qwik were incorrectly flagged for framework-standard attributes such as `class`. - [`cf723bd`](https://github.com/haydenbleasel/ultracite/commit/cf723bd): Add interactive and non-interactive selection for optional Oxlint JS plugins during init. ### [`v7.9.3`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.3) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.2...ultracite@7.9.3) ##### Patch Changes - [`dc6d760`](https://github.com/haydenbleasel/ultracite/commit/dc6d760): Disable the `n/no-unpublished-import` rule in the ESLint core config. This rule flags imports of packages that aren't listed as published dependencies, but it produces a lot of false positives in practice, so it's now turned off. - [`15ecfba`](https://github.com/haydenbleasel/ultracite/commit/15ecfba): Fix `ultracite init --linter eslint` installing an unusable toolchain. The generated ESLint config imports `eslint-plugin-storybook` unconditionally (which requires the `storybook` peer) and the generated Stylelint config extends `stylelint-config-standard` / `stylelint-config-idiomatic-order` / `stylelint-prettier`, but none of those packages were installed — so a fresh ESLint setup failed to load with "Cannot find package 'storybook'" or "Could not find stylelint-config-standard". These four packages are now installed with the ESLint linter. - [`2f73a41`](https://github.com/haydenbleasel/ultracite/commit/2f73a41): Upgrade to oxlint 1.73.0 and oxfmt 0.58.0, and enable the new lint rules they introduce: `no-unreachable-loop`, `unicorn/explicit-timer-delay`, and `unicorn/no-confusing-array-with`. - [`83b2783`](https://github.com/haydenbleasel/ultracite/commit/83b2783): Add an `[astro]` formatter mapping (`astro-build.astro-vscode`) to the oxlint VS Code editor settings generated by `ultracite init`, since oxfmt doesn't format `.astro` files. - [`d186c53`](https://github.com/haydenbleasel/ultracite/commit/d186c53): Move every JS-plugin-based rule set out of the Oxlint core and framework presets and into a single opt-in `ultracite/oxlint/js-plugins` preset. This covers `eslint-plugin-github` and `eslint-plugin-sonarjs` (previously in core) as well as `oxlint-plugin-react-doctor` (previously bundled into the `react`, `next`, and `tanstack` presets). The core, `react`, `next`, and `tanstack` presets now run entirely on Oxlint's native Rust rules, so new setups no longer install those dependencies and no longer pay the slower JS-plugin lint pass. To keep the extra ESLint-parity and React Doctor rules, install `eslint-plugin-github`, `eslint-plugin-sonarjs`, and `oxlint-plugin-react-doctor` and extend `ultracite/oxlint/js-plugins` alongside `core` (and your framework preset). - [`057753e`](https://github.com/haydenbleasel/ultracite/commit/057753e): Add performance benchmarks for `ultracite check` / `ultracite fix` across all three providers (oxlint, biome, eslint). A new CI job builds the PR and its base branch on the same runner, benchmarks them interleaved, and fails on a statistically significant regression (median ratio > 1.25x with Mann-Whitney U p < 0.05) so config changes can't silently slow the linters down again. ### [`v7.9.2`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.2) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.1...ultracite@7.9.2) ##### Patch Changes - [`c335a1f`](https://github.com/haydenbleasel/ultracite/commit/c335a1f): Add `**/node_modules` and `**/.git` to the shared ignore patterns. oxlint only skips `node_modules` when a `.gitignore` lists it, so in projects without one, `ultracite fix` would lint and autofix files inside `node_modules` — corrupting installed packages (e.g. rewriting `var` enum wrappers in `typescript/lib/typescript.js` to self-referencing `const`, causing "Cannot access 'Comparison' before initialization" when oxlint loads eslint-plugin-sonarjs). Fixes [#&#8203;737](https://github.com/haydenbleasel/ultracite/issues/737). ### [`v7.9.1`](https://github.com/haydenbleasel/ultracite/releases/tag/ultracite%407.9.1) [Compare Source](https://github.com/haydenbleasel/ultracite/compare/ultracite@7.9.0...ultracite@7.9.1) ##### Patch Changes - [`ecd10cc`](https://github.com/haydenbleasel/ultracite/commit/ecd10cc): Disable `sonarjs/no-implicit-dependencies` and `github/no-implicit-buggy-globals` in the oxlint and ESLint presets. Both produce false positives through oxlint's JS plugin bridge: `no-implicit-dependencies` has no dependency-manifest resolution so it flags builtin (`bun:test`) and workspace imports as missing dependencies, and `no-implicit-buggy-globals` misreads module-scoped declarations such as Astro frontmatter as implicit globals. - [`c76f59d`](https://github.com/haydenbleasel/ultracite/commit/c76f59d): Disable `sonarjs/file-name-differ-from-class` in the oxlint and ESLint presets. It fires on any file whose name differs from an exported class, which is noise for the many config and module files that export objects rather than classes. - [`29e30ce`](https://github.com/haydenbleasel/ultracite/commit/29e30ce): Fold the github and sonarjs rules into the oxlint core preset. The standalone `ultracite/oxlint/github` and `ultracite/oxlint/sonarjs` presets are removed — ultracite ships framework presets, not individual plugins. Their rules now live in `ultracite/oxlint/core`, so every oxlint setup gets eslint-plugin-github and eslint-plugin-sonarjs through oxlint's JS plugin bridge, matching how the ESLint preset already bundles them into core. This is a breaking change to generated configs: `ultracite/oxlint/github` and `ultracite/oxlint/sonarjs` no longer exist. Re-run `ultracite init` to regenerate `oxlint.config.ts`. Also fixed: nine sonarjs rules (`async-test-assertions`, `hooks-before-test-cases`, `no-duplicate-test-title`, `no-empty-test-title`, `no-floating-point-equality`, `no-forced-browser-interaction`, `no-trivial-assertions`, `prefer-specific-assertions`, `super-linear-regex`) that exist in eslint-plugin-sonarjs but that oxlint's JS plugin bridge does not register. Naming them made oxlint hard-fail config parsing, which broke `ultracite fix`/`check` for oxlint projects using the sonarjs preset. They are omitted from oxlint core (still enabled in the ESLint preset), and a test now runs oxlint against core to catch this class of regression. The React Doctor, github, and sonarjs plugins are installed into your project's devDependencies at init (as the ESLint plugins already were), rather than bundled as dependencies of ultracite — oxlint resolves JS plugin specifiers from the project root, so they must be installed there directly. - [`8a4291f`](https://github.com/haydenbleasel/ultracite/commit/8a4291f): Upgrade to Oxlint 1.72.0 and Oxfmt 0.57.0. Oxfmt 0.57 adds native CSS and GraphQL formatters. The five new non-nursery Oxlint rules from the 1.71/1.72 releases are already covered by the presets (`node/no-sync`, `node/no-mixed-requires`, `unicorn/prefer-number-coercion`, `unicorn/max-nested-calls`, `vue/no-async-in-computed-properties`). The markdown `:::` container-directive fence patch (which keeps `proseWrap: "never"` from folding fences into prose) was regenerated against the 0.57 bundle. </details> --- ### Configuration 📅 **Schedule**: (in timezone Europe/Warsaw) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 👻 **Immortal**: This PR will be recreated if closed unmerged. Get [config help](https://github.com/renovatebot/renovate/discussions) if that's undesired. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC43NC4wIiwidXBkYXRlZEluVmVyIjoiNDQuNzQuMCIsInRhcmdldEJyYW5jaCI6ImRldiIsImxhYmVscyI6WyJkZXBzLWNvZGUiLCJyZW5vdmF0ZSJdfQ==-->
renovate Bot added 1 commit 2026-10-08 04:04:31 +00:00
fix(deps): update code dependencies
renovate/stability-days Updates have met minimum release age requirement
970f02a3ef
renovate Bot scheduled this pull request to auto merge when all checks succeed 2026-10-08 04:04:31 +00:00

ℹ️ Artifact update notice

File name: backend/go.mod

In order to perform the update(s) described in the table above, Renovate ran the go get command, which resulted in the following additional change(s):

  • 2 additional dependencies were updated

Due to Go's usage of Minimal Version Selection (MVS), these packages have been updated to the minimum version available, so will still abide by minimumReleaseAge=3 days

Details:

Package Change
golang.org/x/sys v0.47.0 -> v0.48.0
modernc.org/libc v1.75.7 -> v1.77.1
### ℹ️ Artifact update notice ##### File name: backend/go.mod In order to perform the update(s) described in the table above, Renovate ran the `go get` command, which resulted in the following additional change(s): - 2 additional dependencies were updated Due to Go's usage of [Minimal Version Selection (MVS)](https://go.dev/ref/mod#minimal-version-selection), these packages have been updated to the minimum version available, so will still abide by `minimumReleaseAge=3 days` Details: | **Package** | **Change** | | :----------------- | :--------------------- | | `golang.org/x/sys` | `v0.47.0` -> `v0.48.0` | | `modernc.org/libc` | `v1.75.7` -> `v1.77.1` |
renovate Bot merged commit 82cb8f90a7 into dev 2026-10-08 04:04:33 +00:00
renovate Bot deleted branch renovate/dev-code-dependencies 2026-10-08 04:04:33 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: open/lodge#3