Skip to content

fix(assist): useSortedAttributes no longer corrupts nested JSX attributes#10163

Merged
ematipico merged 4 commits into
biomejs:mainfrom
jiwon79:fix/issue-9884
Apr 30, 2026
Merged

fix(assist): useSortedAttributes no longer corrupts nested JSX attributes#10163
ematipico merged 4 commits into
biomejs:mainfrom
jiwon79:fix/issue-9884

Conversation

@jiwon79

@jiwon79 jiwon79 commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Claude Code assist to writing code and I review all about it

Summary

Fixes #9884

  • The useSortedAttributes auto-fix previously rewrote the attribute list slot-by-slot via replace_node_discard_trivia. When a nested JSX-valued attribute also had an unsorted list, the inner sort propagated upward and collided with the outer slot-level changes during batch commit, producing a duplicated attribute and a dropped one.
  • The fix builds the new attribute list once with AstNodeListExt::splice and registers a single list-level replacement. Conflicts with mutations from nested elements now happen at the list node, where each candidate is a complete valid list, so the output is always parseable and convergent across passes.
  • Signals changed from Box<[PropGroup]> to Option<SortedAttrList> (one signal per attribute list). Multiple unsorted groups within the same JSX element split by spread/shorthand are now consolidated into a single diagnostic with one fix.

Test Plan

  • Added a regression fixture under tests/specs/source/useSortedAttributes/unsorted.jsx reproducing the nested case from the issue.
  • Existing unsorted.jsx.snap and with-comments.jsx.snap were regenerated to reflect the consolidated single-diagnostic-per-list output.

Docs

jiwon79 added 3 commits April 29, 2026 23:51
Captures the scenario from biomejs#9884 where both an outer JSX element and a
nested JSX-valued attribute have unsorted attributes.
…utes

Fixes biomejs#9884. When both an outer JSX element and a nested JSX-valued
attribute had unsorted attributes, the slot-by-slot replace_node loop
in action() produced changes that conflicted at batch commit time with
the inner sort propagating upward. The result was a duplicated
attribute and a dropped one on the outer element.

Replace the entire JsxAttributeList in a single mutation via
AstNodeListExt::splice. A list-level replacement does not compete with
slot-level mutations from nested elements, so the two fixes coexist
correctly across passes.
@changeset-bot

changeset-bot Bot commented Apr 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 58ebb07

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 13 packages
Name Type
@biomejs/biome Patch
@biomejs/cli-win32-x64 Patch
@biomejs/cli-win32-arm64 Patch
@biomejs/cli-darwin-x64 Patch
@biomejs/cli-darwin-arm64 Patch
@biomejs/cli-linux-x64 Patch
@biomejs/cli-linux-arm64 Patch
@biomejs/cli-linux-x64-musl Patch
@biomejs/cli-linux-arm64-musl Patch
@biomejs/wasm-web Patch
@biomejs/wasm-bundler Patch
@biomejs/wasm-nodejs Patch
@biomejs/backend-jsonrpc Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added A-Linter Area: linter L-JavaScript Language: JavaScript and super languages labels Apr 30, 2026
@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 827976fa-e25e-47fa-bf1e-3b776e0a1b4a

📥 Commits

Reviewing files that changed from the base of the PR and between e28f1cd and 58ebb07.

📒 Files selected for processing (1)
  • .changeset/fix-sorted-attributes-nested-jsx.md
✅ Files skipped from review due to trivial changes (1)
  • .changeset/fix-sorted-attributes-nested-jsx.md

Walkthrough

The assist for useSortedAttributes was rewritten to snapshot an element's full JsxAttributeList into slot-indexed data and compute a single sorted_slots mapping. The fix now replaces the entire attribute-list node by splicing attributes according to that mapping, rather than mutating attributes in-place. Sorting groups are split at spread/shorthand boundaries and multiple unsorted groups within the same element are collapsed into a single diagnostic. A new SortedAttrList type was added and PropElement was made non-public. Tests updated with a nested-unsorted JSX case.

Possibly related PRs

Suggested labels

A-Tooling

Suggested reviewers

  • dyc3
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarises the main fix—preventing corruption of nested JSX attributes in the useSortedAttributes assist.
Description check ✅ Passed The description clearly relates to the changeset, explaining the root cause, solution approach, signal changes, and test additions.
Linked Issues check ✅ Passed All coding requirements from issue #9884 are met: the fix prevents attribute duplication/loss, uses AstNodeListExt::splice for atomic list replacement, consolidates diagnostics, and adds regression tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the useSortedAttributes assist corruption bug; no extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.changeset/fix-sorted-attributes-nested-jsx.md (1)

5-5: ⚡ Quick win

Keep the changeset entry fully user-facing.

Great fix note overall — I’d trim the internal “single mutation / slot-level collision” implementation detail and keep this line strictly about observable behaviour.

Proposed wording
-Fixed [`#9884`](https://github.com/biomejs/biome/issues/9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts the source when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same fix pass. The fix now replaces the entire attribute list as a single mutation, so it does not collide at the slot level with mutations propagated up from nested elements. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic.
+Fixed [`#9884`](https://github.com/biomejs/biome/issues/9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both outer and nested JSX elements have unsorted attributes in the same pass. It also now reports a single diagnostic when unsorted groups in the same JSX element are separated by spread or shorthand attributes.

As per coding guidelines, ".changeset/**: Changeset descriptions should focus on user-facing changes only; internal refactoring without user-visible behavior changes does not require a changeset".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.changeset/fix-sorted-attributes-nested-jsx.md at line 5, The changeset
message currently includes internal implementation details; update the
.changeset entry text describing the fix for useSortedAttributes so it only
states the observable user-facing behavior (e.g., that auto-fix no longer
corrupts source when outer and nested JSX elements both have unsorted
attributes, and multiple unsorted groups separated by spreads/shorthands are
reported as a single diagnostic) and remove phrases about “single mutation” or
“slot-level collision”; ensure the symbol name useSortedAttributes remains
referenced and the description is concise and user-facing only.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.changeset/fix-sorted-attributes-nested-jsx.md:
- Line 5: The changeset message currently includes internal implementation
details; update the .changeset entry text describing the fix for
useSortedAttributes so it only states the observable user-facing behavior (e.g.,
that auto-fix no longer corrupts source when outer and nested JSX elements both
have unsorted attributes, and multiple unsorted groups separated by
spreads/shorthands are reported as a single diagnostic) and remove phrases about
“single mutation” or “slot-level collision”; ensure the symbol name
useSortedAttributes remains referenced and the description is concise and
user-facing only.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f2e98504-58e5-4a37-85c1-1f913f6ba17e

📥 Commits

Reviewing files that changed from the base of the PR and between d62b331 and e28f1cd.

⛔ Files ignored due to path filters (2)
  • crates/biome_js_analyze/tests/specs/source/useSortedAttributes/unsorted.jsx.snap is excluded by !**/*.snap and included by **
  • crates/biome_js_analyze/tests/specs/source/useSortedAttributes/with-comments.jsx.snap is excluded by !**/*.snap and included by **
📒 Files selected for processing (3)
  • .changeset/fix-sorted-attributes-nested-jsx.md
  • crates/biome_js_analyze/src/assist/source/use_sorted_attributes.rs
  • crates/biome_js_analyze/tests/specs/source/useSortedAttributes/unsorted.jsx

@codspeed-hq

codspeed-hq Bot commented Apr 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 58 untouched benchmarks
⏩ 196 skipped benchmarks1


Comparing jiwon79:fix/issue-9884 (58ebb07) with main (9c81c79)

Open in CodSpeed

Footnotes

  1. 196 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@ematipico ematipico merged commit 6867e96 into biomejs:main Apr 30, 2026
30 checks passed
@github-actions github-actions Bot mentioned this pull request Apr 30, 2026
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Client that referenced this pull request May 4, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.13` -> `2.4.14`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.13/2.4.14) |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#2414)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14)

##### Patch Changes

- [#&#8203;9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top) in the `test` domain. The rule flags lifecycle hooks (`beforeEach`, `beforeAll`, `afterEach`, `afterAll`) that appear after test cases in the same block, enforcing that hooks are defined before any test case.

- [#&#8203;10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;7882](biomejs/biome#7882): The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as `<br></br>`. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags.

- [#&#8203;10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to `: object`.

  A function annotated `: object` returning an object literal:

  ```ts
  function f(): object {
    return { retry: true };
  }
  ```

- [#&#8203;10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;6201](biomejs/biome#6201): [`noUselessEscapeInRegex`](https://biomejs.dev/linter/rules/no-useless-escape-in-regex/) no longer flags an escaped backslash followed by `-` as a useless escape. Patterns like `/[\\-]/` are now considered valid because the second `\` is the escaped backslash, not an unnecessary escape of the trailing dash.

- [#&#8203;10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;9097](biomejs/biome#9097): [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) no longer adds a blank line between a never-matched group and a matched group.

  Given the following `organizeImports` options:

  ```json
  {
    "groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"]
  }
  ```

  The following code...

  ```js
  // Comment
  import "package";
  import "./file.js";
  ```

  ...was organized as:

  ```diff
  +
    // Comment
    import "package";
  +
    import "./file.js";
  ```

  A blank line was added even though the group ':NODE:' doesn't match any imports here.
  `:BLANK_LINE:` between never-matched groups and matched groups are now ignored.
  The code is now organized as:

  ```diff
    // Comment
    import "package";
  +
    import "./file.js";
  ```

- [#&#8203;10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed Vue `v-for` handling for [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/). Biome now recognizes variables declared by `v-for` directives and references to iterated values in Vue templates.

- [#&#8203;10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns.

- [#&#8203;9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`noReactStringRefs`](https://biomejs.dev/linter/rules/no-react-string-refs/), which disallows legacy React string refs such as `ref="hello"` and `this.refs.hello`.

  Biome also reports template-literal refs such as ``ref={`hello`}``, so React code can consistently migrate to callback refs, `createRef()`, or `useRef()`.

- [#&#8203;10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed a bug in the LSP file watcher registration so Biome now watches `.biome.json` and `.biome.jsonc` configuration files and reloads workspace settings when they change.

- [#&#8203;10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10011](biomejs/biome#10011): The [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) rule no longer reports `this` when it is used as the constructor target in `new this(...)`, which is required for inherited static factory methods.

- [#&#8203;10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;9884](biomejs/biome#9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic.

- [#&#8203;10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@&#8203;Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@&#8203;const}` blocks. Assignments in `{@&#8203;const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions.

- [#&#8203;10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@&#8203;Damix48](https://github.com/Damix48)! - Fixed parsing of closing parentheses in Svelte `{#each}` block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys.

  For example, the following snippets are now parsed correctly:

  ```svelte
  {#each numbers as number, index (number.toString())}
    <p>{number}</p>
  {/each}

  {#each numbers as number (key(number))}
    <p>{number}</p>
  {/each}
  ```

- [#&#8203;10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@&#8203;solithcy](https://github.com/solithcy)! - Fixed [#&#8203;10135](biomejs/biome#10135): Biome no longer crashes on missing Svelte template expressions.

  The following code snippet longer panics:

  ```svelte
  {#if }
   <p>^ this would previously crash</p>
  {/if}
  {@&#8203;const }
  <p>    ^ this would also crash</p>
  ```

- [#&#8203;10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;9997](biomejs/biome#9997): [`noDuplicateSelectors`](https://biomejs.dev/linter/rules/no-duplicate-selectors/) no longer reports false positives for selectors inside `@scope` queries. Biome now treats `@scope` as a separate at-rule context, like `@media`, `@supports`, `@container`, and `@starting-style`.

  The following snippet is no longer flagged as a duplicate:

  ```css
  .Example {
    padding: 0;
  }

  @&#8203;scope (.theme-dark) {
    .Example {
      color: white;
    }
  }
  ```

- [#&#8203;9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery lint rule [`useMathMinMax`](https://biomejs.dev/linter/rules/use-math-min-max/), which prefers `Math.min()` and `Math.max()` over equivalent ternary comparisons.

  For example, this code:

  ```js
  const min = a < b ? a : b;
  ```

  is much more readable when rewritten as:

  ```js
  const min = Math.min(a, b);
  ```

- [#&#8203;10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now flags missing `true`/`false` cases for `boolean` discriminants, including when `boolean` is a union variant.

- [#&#8203;10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@&#8203;bmish](https://github.com/bmish)! - Fixed a resolver bug where packages that define a typed entry point through `package.json`'s `main` field but omit `types` were ignored during type-aware resolution. Type-aware rules such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) can now inspect imports from those packages.

- [#&#8203;10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@&#8203;denizdogan](https://github.com/denizdogan)! - Added support for the `corner-shape` family of CSS properties and the `superellipse()`/`squircle()` value functions, so [`noUnknownProperty`](https://biomejs.dev/linter/rules/no-unknown-property/) and [`noUnknownFunction`](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flag them as unknown.

  New known properties: `corner-shape`, `corner-block-end-shape`, `corner-block-start-shape`, `corner-bottom-left-shape`, `corner-bottom-right-shape`, `corner-bottom-shape`, `corner-end-end-shape`, `corner-end-start-shape`, `corner-inline-end-shape`, `corner-inline-start-shape`, `corner-left-shape`, `corner-right-shape`, `corner-start-end-shape`, `corner-start-start-shape`, `corner-top-left-shape`, `corner-top-right-shape`, `corner-top-shape`.

  New known value functions: `superellipse()`, `squircle()`.

- [#&#8203;8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately.

- [#&#8203;10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@&#8203;guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements.

- [#&#8203;9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9099](biomejs/biome#9099): the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children.

  For example, the following Svelte snippet is now preserved instead of being collapsed to `<div>{name}<!-- comment --></div>`:

  ```svelte
  <div>
    {name}<!-- comment -->
  </div>
  ```

  Similarly, HTML elements like `<span>` inside a `<div>` are now preserved when written on their own line:

  ```html
  <div>
    <span>text</span>
  </div>
  ```

- [#&#8203;10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;10039](biomejs/biome#10039): [`useReadonlyClassProperties`](https://biomejs.dev/linter/rules/use-readonly-class-properties/) now detects unreassigned private members in class expressions and export default classes, not only in class declarations.

  The following patterns are now correctly flagged:

  ```ts
  const AnonClass = class {
    #prop = 123;
    constructor() {
      console.log(this.#prop);
    }
  };

  export default class {
    #prop = 123;
    constructor() {
      console.log(this.#prop);
    }
  }
  ```

- [#&#8203;10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) to detect conditions that are always truthy because they check built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.

- [#&#8203;10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`.

- [#&#8203;10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;10045](biomejs/biome#10045): the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as `:not(:where(...))`, `:is(:where(...))`, and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including `:nth-child(... of ...)`, `::part(...)`, and `:active-view-transition-type(...)`.
  The following snippet is now correctly formatted, matching Prettier.

  ```css
  input:not(
    :where(
      [type="submit"],
      [type="checkbox"],
      [type="radio"],
      [type="button"],
      [type="reset"]
    )
  ) {
    inline-size: 100%;
  }
  ```

- [#&#8203;10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes.

- [#&#8203;10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) to detect `object` return annotations that hide built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.

- [#&#8203;10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Added two new options to [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/), both defaulting to `true` to match typescript-eslint's behavior.

  Fixed [#&#8203;9482](biomejs/biome#9482): Added `ignoreFunctionTypeParameterNameValueShadow` option. When enabled, parameter names inside function type annotations (e.g. `(options: unknown) => void`) are not flagged as shadowing outer variables.

  Fixed [#&#8203;7812](biomejs/biome#7812): Added `ignoreTypeValueShadow` option. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript.

- [#&#8203;9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@&#8203;Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#&#8203;6316](biomejs/biome#6316): Biome now resolves Svelte `$store` references to the underlying `store` binding in semantic analysis, preventing false `noUndeclaredVariables` diagnostics when the store is declared.

- [#&#8203;10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noExcessiveNestedCallbacks`](https://biomejs.dev/linter/rules/no-excessive-nested-callbacks/), which disallows callbacks nested deeper than the configured maximum.

- [#&#8203;9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9450](biomejs/biome#9450): the HTML formatter now correctly preserves multiline formatting for nested `<template>` elements (e.g. `<template #body>`) when the source has children on separate lines. Previously, the children were collapsed onto a single line.

  ```diff
   <template>
     <UModal>
  -    <template #body> <p>content</p> </template>
  +    <template #body>
  +      <p>content</p>
  +    </template>
     </UModal>
   </template>
  ```

- [#&#8203;10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10024](biomejs/biome#10024): `biome migrate eslint` correctly migrates `eslint` rules that belong to multiple Biome rules.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

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

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Client/pulls/2
OIRNOIR pushed a commit to OIRNOIR/YouTube-Helper-Server that referenced this pull request May 5, 2026
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@biomejs/biome](https://biomejs.dev) ([source](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome)) | imports | patch | [`2.4.13` -> `2.4.14`](https://renovatebot.com/diffs/npm/@biomejs%2fbiome/2.4.13/2.4.14) |

---

### Release Notes

<details>
<summary>biomejs/biome (@&#8203;biomejs/biome)</summary>

### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@&#8203;biomejs/biome/CHANGELOG.md#2414)

[Compare Source](https://github.com/biomejs/biome/compare/@biomejs/biome@2.4.13...@biomejs/biome@2.4.14)

##### Patch Changes

- [#&#8203;9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery rule [`useTestHooksOnTop`](https://biomejs.dev/linter/rules/use-test-hooks-on-top) in the `test` domain. The rule flags lifecycle hooks (`beforeEach`, `beforeAll`, `afterEach`, `afterAll`) that appear after test cases in the same block, enforcing that hooks are defined before any test case.

- [#&#8203;10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;7882](biomejs/biome#7882): The HTML parser will now emit better diagnostics when it encounters a void element with a closing tag, such as `<br></br>`. Previously, the parser would emit multiple diagnostics with conflicting advice. Now it emits a single diagnostic that clearly states that void elements should not have closing tags.

- [#&#8203;10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer misses widening from concrete object types, class instances, object literals, tuples, functions, and regular expressions to `: object`.

  A function annotated `: object` returning an object literal:

  ```ts
  function f(): object {
    return { retry: true };
  }
  ```

- [#&#8203;10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;6201](biomejs/biome#6201): [`noUselessEscapeInRegex`](https://biomejs.dev/linter/rules/no-useless-escape-in-regex/) no longer flags an escaped backslash followed by `-` as a useless escape. Patterns like `/[\\-]/` are now considered valid because the second `\` is the escaped backslash, not an unnecessary escape of the trailing dash.

- [#&#8203;10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@&#8203;Conaclos](https://github.com/Conaclos)! - Fixed [#&#8203;9097](biomejs/biome#9097): [`organizeImports`](https://biomejs.dev/assist/actions/organize-imports/) no longer adds a blank line between a never-matched group and a matched group.

  Given the following `organizeImports` options:

  ```json
  {
    "groups": [":NODE:", ":BLANK_LINE:", ":PACKAGE:", ":BLANK_LINE:", ":PATH:"]
  }
  ```

  The following code...

  ```js
  // Comment
  import "package";
  import "./file.js";
  ```

  ...was organized as:

  ```diff
  +
    // Comment
    import "package";
  +
    import "./file.js";
  ```

  A blank line was added even though the group ':NODE:' doesn't match any imports here.
  `:BLANK_LINE:` between never-matched groups and matched groups are now ignored.
  The code is now organized as:

  ```diff
    // Comment
    import "package";
  +
    import "./file.js";
  ```

- [#&#8203;10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed Vue `v-for` handling for [`noUndeclaredVariables`](https://biomejs.dev/linter/rules/no-undeclared-variables/) and [`noUnusedVariables`](https://biomejs.dev/linter/rules/no-unused-variables/). Biome now recognizes variables declared by `v-for` directives and references to iterated values in Vue templates.

- [#&#8203;10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) no longer reports false positives when a union return type's `boolean` variant is covered by both `true` and `false` returns.

- [#&#8203;9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the new nursery rule [`noReactStringRefs`](https://biomejs.dev/linter/rules/no-react-string-refs/), which disallows legacy React string refs such as `ref="hello"` and `this.refs.hello`.

  Biome also reports template-literal refs such as ``ref={`hello`}``, so React code can consistently migrate to callback refs, `createRef()`, or `useRef()`.

- [#&#8203;10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed a bug in the LSP file watcher registration so Biome now watches `.biome.json` and `.biome.jsonc` configuration files and reloads workspace settings when they change.

- [#&#8203;10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10011](biomejs/biome#10011): The [`noThisInStatic`](https://biomejs.dev/linter/rules/no-this-in-static/) rule no longer reports `this` when it is used as the constructor target in `new this(...)`, which is required for inherited static factory methods.

- [#&#8203;10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;9884](biomejs/biome#9884): The [`useSortedAttributes`](https://biomejs.dev/assist/actions/use-sorted-attributes/) auto-fix no longer corrupts source code when both an outer JSX element and a nested JSX-valued attribute have unsorted attributes in the same pass. Multiple unsorted groups separated by spread or shorthand attributes within the same JSX element are now reported as a single diagnostic.

- [#&#8203;10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@&#8203;Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@&#8203;const}` blocks. Assignments in `{@&#8203;const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions.

- [#&#8203;10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@&#8203;Damix48](https://github.com/Damix48)! - Fixed parsing of closing parentheses in Svelte `{#each}` block key expressions. Biome now correctly parses method calls and other parenthesised expressions used as keys.

  For example, the following snippets are now parsed correctly:

  ```svelte
  {#each numbers as number, index (number.toString())}
    <p>{number}</p>
  {/each}

  {#each numbers as number (key(number))}
    <p>{number}</p>
  {/each}
  ```

- [#&#8203;10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@&#8203;solithcy](https://github.com/solithcy)! - Fixed [#&#8203;10135](biomejs/biome#10135): Biome no longer crashes on missing Svelte template expressions.

  The following code snippet longer panics:

  ```svelte
  {#if }
   <p>^ this would previously crash</p>
  {/if}
  {@&#8203;const }
  <p>    ^ this would also crash</p>
  ```

- [#&#8203;10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;9997](biomejs/biome#9997): [`noDuplicateSelectors`](https://biomejs.dev/linter/rules/no-duplicate-selectors/) no longer reports false positives for selectors inside `@scope` queries. Biome now treats `@scope` as a separate at-rule context, like `@media`, `@supports`, `@container`, and `@starting-style`.

  The following snippet is no longer flagged as a duplicate:

  ```css
  .Example {
    padding: 0;
  }

  @&#8203;scope (.theme-dark) {
    .Example {
      color: white;
    }
  }
  ```

- [#&#8203;9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added the nursery lint rule [`useMathMinMax`](https://biomejs.dev/linter/rules/use-math-min-max/), which prefers `Math.min()` and `Math.max()` over equivalent ternary comparisons.

  For example, this code:

  ```js
  const min = a < b ? a : b;
  ```

  is much more readable when rewritten as:

  ```js
  const min = Math.min(a, b);
  ```

- [#&#8203;10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - [`useExhaustiveSwitchCases`](https://biomejs.dev/linter/rules/use-exhaustive-switch-cases/) now flags missing `true`/`false` cases for `boolean` discriminants, including when `boolean` is a union variant.

- [#&#8203;10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@&#8203;bmish](https://github.com/bmish)! - Fixed a resolver bug where packages that define a typed entry point through `package.json`'s `main` field but omit `types` were ignored during type-aware resolution. Type-aware rules such as [`noFloatingPromises`](https://biomejs.dev/linter/rules/no-floating-promises/) can now inspect imports from those packages.

- [#&#8203;10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@&#8203;denizdogan](https://github.com/denizdogan)! - Added support for the `corner-shape` family of CSS properties and the `superellipse()`/`squircle()` value functions, so [`noUnknownProperty`](https://biomejs.dev/linter/rules/no-unknown-property/) and [`noUnknownFunction`](https://biomejs.dev/linter/rules/no-unknown-function/) no longer flag them as unknown.

  New known properties: `corner-shape`, `corner-block-end-shape`, `corner-block-start-shape`, `corner-bottom-left-shape`, `corner-bottom-right-shape`, `corner-bottom-shape`, `corner-end-end-shape`, `corner-end-start-shape`, `corner-inline-end-shape`, `corner-inline-start-shape`, `corner-left-shape`, `corner-right-shape`, `corner-start-end-shape`, `corner-start-start-shape`, `corner-top-left-shape`, `corner-top-right-shape`, `corner-top-shape`.

  New known value functions: `superellipse()`, `squircle()`.

- [#&#8203;8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately.

- [#&#8203;10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@&#8203;guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements.

- [#&#8203;9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9099](biomejs/biome#9099): the HTML formatter collapsing non-text children (inline elements, Svelte expressions, comments) onto a single line when the source had them on separate lines. Biome now preserves the user's intended line breaks for exclusively non-text children.

  For example, the following Svelte snippet is now preserved instead of being collapsed to `<div>{name}<!-- comment --></div>`:

  ```svelte
  <div>
    {name}<!-- comment -->
  </div>
  ```

  Similarly, HTML elements like `<span>` inside a `<div>` are now preserved when written on their own line:

  ```html
  <div>
    <span>text</span>
  </div>
  ```

- [#&#8203;10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;10039](biomejs/biome#10039): [`useReadonlyClassProperties`](https://biomejs.dev/linter/rules/use-readonly-class-properties/) now detects unreassigned private members in class expressions and export default classes, not only in class declarations.

  The following patterns are now correctly flagged:

  ```ts
  const AnonClass = class {
    #prop = 123;
    constructor() {
      console.log(this.#prop);
    }
  };

  export default class {
    #prop = 123;
    constructor() {
      console.log(this.#prop);
    }
  }
  ```

- [#&#8203;10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noUnnecessaryConditions`](https://biomejs.dev/linter/rules/no-unnecessary-conditions/) to detect conditions that are always truthy because they check built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.

- [#&#8203;10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`.

- [#&#8203;10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@&#8203;jiwon79](https://github.com/jiwon79)! - Fixed [#&#8203;10045](biomejs/biome#10045): the CSS formatter no longer compounds indentation inside nested functional pseudo-classes such as `:not(:where(...))`, `:is(:where(...))`, and similar combinations. The same fix also removes one level of unnecessary indentation that was added inside any pseudo-class function whose argument list wrapped onto multiple lines, including `:nth-child(... of ...)`, `::part(...)`, and `:active-view-transition-type(...)`.
  The following snippet is now correctly formatted, matching Prettier.

  ```css
  input:not(
    :where(
      [type="submit"],
      [type="checkbox"],
      [type="radio"],
      [type="button"],
      [type="reset"]
    )
  ) {
    inline-size: 100%;
  }
  ```

- [#&#8203;10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes.

- [#&#8203;10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@&#8203;minseong0324](https://github.com/minseong0324)! - Improved [`noMisleadingReturnType`](https://biomejs.dev/linter/rules/no-misleading-return-type/) to detect `object` return annotations that hide built-in global class instances such as `Date`, `Map`, `Set`, `WeakMap`, and `Error`.

- [#&#8203;10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@&#8203;ematipico](https://github.com/ematipico)! - Added two new options to [`noShadow`](https://biomejs.dev/linter/rules/no-shadow/), both defaulting to `true` to match typescript-eslint's behavior.

  Fixed [#&#8203;9482](biomejs/biome#9482): Added `ignoreFunctionTypeParameterNameValueShadow` option. When enabled, parameter names inside function type annotations (e.g. `(options: unknown) => void`) are not flagged as shadowing outer variables.

  Fixed [#&#8203;7812](biomejs/biome#7812): Added `ignoreTypeValueShadow` option. When enabled, a value binding that shares its name with a type-only declaration (type alias or interface) is not flagged, since types and values occupy separate namespaces in TypeScript.

- [#&#8203;9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@&#8203;Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#&#8203;6316](biomejs/biome#6316): Biome now resolves Svelte `$store` references to the underlying `store` binding in semantic analysis, preventing false `noUndeclaredVariables` diagnostics when the store is declared.

- [#&#8203;10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Added a new nursery rule [`noExcessiveNestedCallbacks`](https://biomejs.dev/linter/rules/no-excessive-nested-callbacks/), which disallows callbacks nested deeper than the configured maximum.

- [#&#8203;9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@&#8203;dyc3](https://github.com/dyc3)! - Fixed [#&#8203;9450](biomejs/biome#9450): the HTML formatter now correctly preserves multiline formatting for nested `<template>` elements (e.g. `<template #body>`) when the source has children on separate lines. Previously, the children were collapsed onto a single line.

  ```diff
   <template>
     <UModal>
  -    <template #body> <p>content</p> </template>
  +    <template #body>
  +      <p>content</p>
  +    </template>
     </UModal>
   </template>
  ```

- [#&#8203;10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@&#8203;Netail](https://github.com/Netail)! - Fixed [#&#8203;10024](biomejs/biome#10024): `biome migrate eslint` correctly migrates `eslint` rules that belong to multiple Biome rules.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

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

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjAuMiIsInVwZGF0ZWRJblZlciI6IjQzLjE2MC4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Reviewed-on: https://git.oirnoir.dev/OIRNOIR/YouTube-Helper-Server/pulls/10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Linter Area: linter L-JavaScript Language: JavaScript and super languages

Projects

None yet

2 participants