fix(10024): eslint generation#10118
Conversation
🦋 Changeset detectedLatest commit: 3c18774 The changes in this PR will be included in the next version bump. This PR includes changesets to release 13 packages
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 |
Parser conformance results onjs/262
jsx/babel
markdown/commonmark
symbols/microsoft
ts/babel
ts/microsoft
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThis PR makes the ESLint→Biome migration generator handle cases where a single ESLint rule maps to multiple Biome rules by aggregating, deduplicating and emitting multi-mapping code paths in Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
xtask/codegen/src/generate_migrate_eslint.rs (1)
12-84:⚠️ Potential issue | 🟠 MajorPlease lock this down with a regression test.
This rewires the generator in a bug-fix path, but the PR does not include coverage for either “one ESLint rule enables multiple Biome rules” or the mixed
same()/inspired()case above. That’s a very easy regression to reintroduce. As per coding guidelines, "All code changes MUST include appropriate tests: lint rules require snapshot tests in 'tests/specs/{group}/{rule}/', formatters require snapshot tests with valid/invalid cases, parsers require test files covering valid and error cases, and bug fixes require tests that reproduce and validate the fix."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@xtask/codegen/src/generate_migrate_eslint.rs` around lines 12 - 84, Add a regression test that verifies migrate_eslint_any_rule behavior for (a) one ESLint rule mapping to multiple Biome rules and (b) a mixed same()/inspired() mapping so the generator change doesn't regress; create snapshot tests under tests/specs/<group>/<rule>/ that call migrate_eslint_any_rule (the generated function created by generate_migrate_eslint) with a Rules instance and MigrationOptions toggling include_inspired and include_nursery, asserting MigrationResults contains the expected sequence (Migrated/Inspired/Nursery/Unsupported) and that the corresponding biome_configuration::Rules entries (accessed via group.unwrap_group_as_mut().<rule_ident>) have the expected levels after migration; ensure the test constructs RuleMapping-like inputs via the EslintLintRulesVisitor registry entries or by invoking the generator path that produces those mappings so the test reproduces the exact multi-rule and mixed same()/inspired() scenarios.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@xtask/codegen/src/generate_migrate_eslint.rs`:
- Around line 20-58: The generated guard blocks currently call `return false`
(from the `check_inspired` and `check_nursery` quote blocks) which
short-circuits remaining mappings for the same `eslint_name`; instead, change
the generated guards to record the result (e.g., `results.add(eslint_name,
...Inspired)` / `...Nursery`) and set a local skip flag (like `let mut skip =
false; skip = true;`) rather than returning; then wrap the mapping application
(the code that inserts into `rules.#group_ident` and sets the level) in `if
!skip { ... }` so later mappings (such as a `same()` mapping) can still run for
the same `eslint_name`. Ensure you update the `check_inspired` and
`check_nursery` quote blocks and the inner quoted block that uses
`#name_ident`/`#group_ident` accordingly.
---
Outside diff comments:
In `@xtask/codegen/src/generate_migrate_eslint.rs`:
- Around line 12-84: Add a regression test that verifies migrate_eslint_any_rule
behavior for (a) one ESLint rule mapping to multiple Biome rules and (b) a mixed
same()/inspired() mapping so the generator change doesn't regress; create
snapshot tests under tests/specs/<group>/<rule>/ that call
migrate_eslint_any_rule (the generated function created by
generate_migrate_eslint) with a Rules instance and MigrationOptions toggling
include_inspired and include_nursery, asserting MigrationResults contains the
expected sequence (Migrated/Inspired/Nursery/Unsupported) and that the
corresponding biome_configuration::Rules entries (accessed via
group.unwrap_group_as_mut().<rule_ident>) have the expected levels after
migration; ensure the test constructs RuleMapping-like inputs via the
EslintLintRulesVisitor registry entries or by invoking the generator path that
produces those mappings so the test reproduces the exact multi-rule and mixed
same()/inspired() scenarios.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e0f4d412-a022-4ec5-b7a8-887e08a84d53
⛔ Files ignored due to path filters (1)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**
📒 Files selected for processing (4)
.changeset/weak-kiwis-post.mdcrates/biome_html_analyze/src/lint/a11y/no_access_key.rscrates/biome_js_analyze/src/lint/a11y/no_access_key.rsxtask/codegen/src/generate_migrate_eslint.rs
0c54eb8 to
9ad9e03
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (1)
xtask/codegen/src/generate_migrate_eslint.rs (1)
24-43:⚠️ Potential issue | 🟠 MajorThe
return falsestill short-circuits processing of subsequent mappings.When multiple Biome rules map to the same ESLint source with different
source_kindvalues (e.g., rule X =inspired, rule Y =same), processing X first withinclude_inspired=falsecauses an early return before Y is ever evaluated—even though Y should migrate successfully.The generated code expands all rules sequentially via
#(#rules)*, but any individual block hittingreturn falseexits the entire match arm prematurely.Consider tracking whether any rule migrated successfully rather than returning early, e.g.:
♻️ Sketch of alternative approach
- if !options.include_inspired { - results.add(eslint_name, eslint_to_biome::RuleMigrationResult::Inspired); - return false; - } + if !options.include_inspired { + results.add(eslint_name, eslint_to_biome::RuleMigrationResult::Inspired); + } else { + // ... enable rule ... + migrated = true; + }Then return based on whether
migratedwas ever set totrue.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@xtask/codegen/src/generate_migrate_eslint.rs` around lines 24 - 43, The generated per-rule checks (the check_inspired and check_nursery blocks) must not use `return false` because that short-circuits evaluation of subsequent mappings; instead introduce a local `migrated: bool` (initialized false) in the surrounding match arm and change both `check_inspired` and `check_nursery` expansions to set `results.add(..., RuleMigrationResult::...)` and continue without returning (e.g., leave `migrated` unchanged when skipped), and when a rule actually migrates set `migrated = true`. After the expanded `#( `#rules` )*` loop, return the final boolean based on `migrated`. Update any uses of `eslint_to_biome::RuleMigrationResult` and `results.add` accordingly so they no longer rely on `return false`.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@xtask/codegen/src/generate_migrate_eslint.rs`:
- Around line 24-43: The generated per-rule checks (the check_inspired and
check_nursery blocks) must not use `return false` because that short-circuits
evaluation of subsequent mappings; instead introduce a local `migrated: bool`
(initialized false) in the surrounding match arm and change both
`check_inspired` and `check_nursery` expansions to set `results.add(...,
RuleMigrationResult::...)` and continue without returning (e.g., leave
`migrated` unchanged when skipped), and when a rule actually migrates set
`migrated = true`. After the expanded `#( `#rules` )*` loop, return the final
boolean based on `migrated`. Update any uses of
`eslint_to_biome::RuleMigrationResult` and `results.add` accordingly so they no
longer rely on `return false`.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 57204e29-2e3a-470d-a19d-604fc2f0592d
⛔ Files ignored due to path filters (2)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonc.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (5)
.changeset/weak-kiwis-post.mdcrates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonccrates/biome_html_analyze/src/lint/a11y/no_access_key.rscrates/biome_js_analyze/src/lint/a11y/no_access_key.rsxtask/codegen/src/generate_migrate_eslint.rs
✅ Files skipped from review due to trivial changes (4)
- .changeset/weak-kiwis-post.md
- crates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonc
- crates/biome_html_analyze/src/lint/a11y/no_access_key.rs
- crates/biome_js_analyze/src/lint/a11y/no_access_key.rs
Merging this PR will not alter performance
Comparing Footnotes
|
158ce26 to
32cd0f7
Compare
32cd0f7 to
e40dacb
Compare
| for ((eslint_name, source_kind), (group_name, rule_metadata)) in visitor.0 { | ||
| let name = rule_metadata.name; | ||
| let name_ident = format_ident!("{}", Case::Snake.convert(name)); | ||
| fn generate_multi_mapping(eslint_name: Box<str>, mapped_rules: Vec<RuleMapping>) -> TokenStream { |
There was a problem hiding this comment.
Made 2 generators, due linting errors on the blocked & migrated variable if it was as single rule without nursery & inspired. As the value was only read and never changed
There was a problem hiding this comment.
And those variables are dragged to a higher level to prevent an early exit
There was a problem hiding this comment.
🧹 Nitpick comments (1)
xtask/codegen/src/generate_migrate_eslint.rs (1)
24-39: A single ESLint rule can be recorded in multiple status sets, inflating the summary count.When an ESLint rule maps to multiple Biome targets (multi-mapping), the generated code produces multiple sequential blocks, each with independent
results.add()calls. If bothinclude_inspiredandinclude_nurseryare disabled, the same rule can be recorded in both theinspiredandnurserysets. Sincerule_count()sums all set lengths without deduplication across sets, a rule in two sets counts twice in the summary output.Example:
@typescript-eslint/explicit-function-return-typehas two blocks (lines 635–670), each callingresults.add(eslint_name, Inspired/Nursery). With both flags disabled, the rule ends up in both sets and inflates the count.Refactor to accumulate the blocked status locally and emit once per rule after checking all mappings, or deduplicate across sets when computing the summary.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@xtask/codegen/src/generate_migrate_eslint.rs` around lines 24 - 39, The generated code currently emits multiple sequential blocks (check_inspired, check_nursery) that each call results.add(eslint_name, eslint_to_biome::RuleMigrationResult::...), causing duplicate recordings for multi-mapped rules; change the logic in generate_migrate_eslint.rs to compute the blocked status locally per rule (collecting reasons like Inspired and Nursery into a temporary set/bitfield) and then call results.add once with each distinct RuleMigrationResult for that rule (or alternatively ensure rule_count() deduplicates across sets when summarizing); update the code that builds check_inspired/check_nursery so they only set local flags rather than calling results.add directly and emit the results.add(eslint_name, ...) calls after all checks for the current eslint_name are evaluated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@xtask/codegen/src/generate_migrate_eslint.rs`:
- Around line 24-39: The generated code currently emits multiple sequential
blocks (check_inspired, check_nursery) that each call results.add(eslint_name,
eslint_to_biome::RuleMigrationResult::...), causing duplicate recordings for
multi-mapped rules; change the logic in generate_migrate_eslint.rs to compute
the blocked status locally per rule (collecting reasons like Inspired and
Nursery into a temporary set/bitfield) and then call results.add once with each
distinct RuleMigrationResult for that rule (or alternatively ensure rule_count()
deduplicates across sets when summarizing); update the code that builds
check_inspired/check_nursery so they only set local flags rather than calling
results.add directly and emit the results.add(eslint_name, ...) calls after all
checks for the current eslint_name are evaluated.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4162d4c0-8179-440b-a146-924f2a408bd5
⛔ Files ignored due to path filters (2)
crates/biome_cli/src/execute/migrate/eslint_any_rule_to_biome.rsis excluded by!**/migrate/eslint_any_rule_to_biome.rsand included by**crates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonc.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (5)
.changeset/weak-kiwis-post.mdcrates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonccrates/biome_html_analyze/src/lint/a11y/no_access_key.rscrates/biome_js_analyze/src/lint/a11y/no_access_key.rsxtask/codegen/src/generate_migrate_eslint.rs
✅ Files skipped from review due to trivial changes (4)
- .changeset/weak-kiwis-post.md
- crates/biome_cli/tests/specs/migrate_eslint/typescriptExplicitFunctionReturnType/basic.jsonc
- crates/biome_js_analyze/src/lint/a11y/no_access_key.rs
- crates/biome_html_analyze/src/lint/a11y/no_access_key.rs
Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
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 (@​biomejs/biome)</summary> ### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@​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 - [#​9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@​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. - [#​10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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. - [#​10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@​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 }; } ``` - [#​10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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. - [#​10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​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"; ``` - [#​10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@​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. - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​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. - [#​9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@​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()`. - [#​10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@​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. - [#​10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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. - [#​10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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. - [#​10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@​const}` blocks. Assignments in `{@​const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions. - [#​10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@​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} ``` - [#​10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​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} {@​const } <p> ^ this would also crash</p> ``` - [#​10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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; } @​scope (.theme-dark) { .Example { color: white; } } ``` - [#​9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@​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); ``` - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​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. - [#​10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@​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. - [#​10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@​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()`. - [#​8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately. - [#​10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@​guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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> ``` - [#​10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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); } } ``` - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​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`. - [#​10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`. - [#​10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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%; } ``` - [#​10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes. - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​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`. - [#​10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@​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 [#​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 [#​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. - [#​9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@​Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#​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. - [#​10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@​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. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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> ``` - [#​10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​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
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 (@​biomejs/biome)</summary> ### [`v2.4.14`](https://github.com/biomejs/biome/blob/HEAD/packages/@​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 - [#​9393](biomejs/biome#9393) [`491b171`](biomejs/biome@491b171) Thanks [@​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. - [#​10157](biomejs/biome#10157) [`eefc5ab`](biomejs/biome@eefc5ab) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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. - [#​10054](biomejs/biome#10054) [`0e9f569`](biomejs/biome@0e9f569) Thanks [@​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 }; } ``` - [#​10116](biomejs/biome#10116) [`53269eb`](biomejs/biome@53269eb) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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. - [#​10092](biomejs/biome#10092) [`33d8543`](biomejs/biome@33d8543) Thanks [@​Conaclos](https://github.com/Conaclos)! - Fixed [#​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"; ``` - [#​10138](biomejs/biome#10138) [`a10b6c1`](biomejs/biome@a10b6c1) Thanks [@​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. - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​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. - [#​9922](biomejs/biome#9922) [`7acf1e0`](biomejs/biome@7acf1e0) Thanks [@​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()`. - [#​10010](biomejs/biome#10010) [`f3e76ab`](biomejs/biome@f3e76ab) Thanks [@​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. - [#​10176](biomejs/biome#10176) [`8a40ef8`](biomejs/biome@8a40ef8) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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. - [#​10163](biomejs/biome#10163) [`6867e96`](biomejs/biome@6867e96) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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. - [#​10079](biomejs/biome#10079) [`d29dd19`](biomejs/biome@d29dd19) Thanks [@​Damix48](https://github.com/Damix48)! - Fixed false positive in `noAssignInExpressions` for Svelte `{@​const}` blocks. Assignments in `{@​const name = value}` are now correctly recognized as declarations rather than accidental assignments in expressions. - [#​10080](biomejs/biome#10080) [`5d8fdac`](biomejs/biome@5d8fdac) Thanks [@​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} ``` - [#​10140](biomejs/biome#10140) [`e7024b9`](biomejs/biome@e7024b9) Thanks [@​solithcy](https://github.com/solithcy)! - Fixed [#​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} {@​const } <p> ^ this would also crash</p> ``` - [#​10111](biomejs/biome#10111) [`7818009`](biomejs/biome@7818009) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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; } @​scope (.theme-dark) { .Example { color: white; } } ``` - [#​9926](biomejs/biome#9926) [`d62b331`](biomejs/biome@d62b331) Thanks [@​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); ``` - [#​10115](biomejs/biome#10115) [`d428d76`](biomejs/biome@d428d76) Thanks [@​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. - [#​10125](biomejs/biome#10125) [`a55a0b6`](biomejs/biome@a55a0b6) Thanks [@​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. - [#​10117](biomejs/biome#10117) [`895e809`](biomejs/biome@895e809) Thanks [@​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()`. - [#​8620](biomejs/biome#8620) [`8df8f73`](biomejs/biome@8df8f73) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​8062](biomejs/biome#8062): Added support for parsing Vue `v-for` directives more accurately. - [#​10191](biomejs/biome#10191) [`aa055cd`](biomejs/biome@aa055cd) Thanks [@​guney](https://github.com/guney)! - Now the rule [`noStaticElementInteractions`](https://biomejs.dev/linter/rules/no-static-element-interactions/) doesn't trigger custom elements. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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> ``` - [#​10105](biomejs/biome#10105) [`e7c1a6d`](biomejs/biome@e7c1a6d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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); } } ``` - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​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`. - [#​10178](biomejs/biome#10178) [`7b05a89`](biomejs/biome@7b05a89) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10177](biomejs/biome#10177): The HTML parser no longer reports lowercase `html` or `doctype` text as invalid after void elements such as `<br>`. - [#​10155](biomejs/biome#10155) [`0d4595d`](biomejs/biome@0d4595d) Thanks [@​jiwon79](https://github.com/jiwon79)! - Fixed [#​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%; } ``` - [#​10112](biomejs/biome#10112) [`6f0251e`](biomejs/biome@6f0251e) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​10110](biomejs/biome#10110): Biome's parser now accepts surrogate code points in JavaScript string `\u{...}` escapes. - [#​10141](biomejs/biome#10141) [`46a77d0`](biomejs/biome@46a77d0) Thanks [@​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`. - [#​10083](biomejs/biome#10083) [`4a664c1`](biomejs/biome@4a664c1) Thanks [@​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 [#​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 [#​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. - [#​9286](biomejs/biome#9286) [`52695cf`](biomejs/biome@52695cf) Thanks [@​Hugo-Polloli](https://github.com/Hugo-Polloli)! - Fixed [#​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. - [#​10188](biomejs/biome#10188) [`ae659dd`](biomejs/biome@ae659dd) Thanks [@​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. - [#​9757](biomejs/biome#9757) [`2c62594`](biomejs/biome@2c62594) Thanks [@​dyc3](https://github.com/dyc3)! - Fixed [#​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> ``` - [#​10118](biomejs/biome#10118) [`c6edcb4`](biomejs/biome@c6edcb4) Thanks [@​Netail](https://github.com/Netail)! - Fixed [#​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
Summary
Closes #10024
Ref Discord
Test Plan
Docs