diff --git a/.github/workflows/pr-build-artifacts.yml b/.github/workflows/pr-build-artifacts.yml
new file mode 100644
index 0000000000..934734cc6f
--- /dev/null
+++ b/.github/workflows/pr-build-artifacts.yml
@@ -0,0 +1,146 @@
+name: Build PR Artifacts
+
+on:
+ pull_request:
+ types: [opened, synchronize, reopened]
+
+env:
+ NODE_VERSION: "22.x"
+
+jobs:
+ check-permissions:
+ name: Check if user has write access
+ runs-on: ubuntu-latest
+ outputs:
+ has-write-access: ${{ steps.check.outputs.require-result }}
+ steps:
+ - name: Check user permission
+ id: check
+ uses: actions-cool/check-user-permission@v2
+ with:
+ require: write
+ username: ${{ github.event.pull_request.user.login }}
+
+ build:
+ name: Build ${{ matrix.os }}
+ needs: check-permissions
+ if: needs.check-permissions.outputs.has-write-access == 'true'
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [macos-latest, ubuntu-latest, windows-latest]
+
+ steps:
+ - uses: actions/checkout@v5
+
+ - name: Install pnpm
+ uses: pnpm/action-setup@v4
+ with:
+ version: 10
+ run_install: false
+
+ - name: Setup NodeJS
+ if: startsWith(matrix.os, 'macOS') != true
+ uses: actions/setup-node@v5
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: 'pnpm'
+
+ - name: Setup NodeJS for macOS
+ if: startsWith(matrix.os, 'macOS')
+ uses: actions/setup-node@v5
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Install dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Build on macOS
+ if: startsWith(matrix.os, 'macOS')
+ run: |
+ pnpm dist:mac
+ pnpm dist:mac:arm64
+
+ - name: Install Linux dependencies
+ if: startsWith(matrix.os, 'ubuntu')
+ run: |
+ sudo snap install snapcraft --classic
+ sudo apt update
+ sudo apt install -y flatpak flatpak-builder
+ sudo flatpak remote-add --if-not-exists --system flathub https://flathub.org/repo/flathub.flatpakrepo
+ sudo flatpak install -y flathub org.freedesktop.Platform/x86_64/24.08
+ sudo flatpak install -y flathub org.freedesktop.Sdk/x86_64/24.08
+ sudo flatpak install -y flathub org.electronjs.Electron2.BaseApp/x86_64/24.08
+
+ - name: Build on Linux
+ if: startsWith(matrix.os, 'ubuntu')
+ run: |
+ pnpm dist:linux
+ pnpm dist:linux:deb-arm64
+ pnpm dist:linux:rpm-arm64
+
+ - name: Build on Windows
+ if: startsWith(matrix.os, 'windows')
+ run: |
+ pnpm dist:win
+
+ - name: Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: build-artifacts-${{ matrix.os }}
+ path: pack/
+ retention-days: 7
+ if-no-files-found: error
+
+ comment:
+ name: Comment on PR
+ needs: [check-permissions, build]
+ if: always() && needs.check-permissions.outputs.has-write-access == 'true'
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - name: Create comment
+ uses: actions/github-script@v7
+ with:
+ script: |
+ const runId = context.runId;
+ const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
+
+ const buildResult = '${{ needs.build.result }}';
+
+ let comment;
+ if (buildResult === 'success') {
+ comment = `## 🚀 Build Artifacts Ready!
+
+ The builds have completed successfully. You can download the artifacts from the workflow run:
+
+ **[📦 Download Artifacts](${runUrl})**
+
+ ### Available builds:
+ - **Windows**: \`build-artifacts-windows-latest\`
+ - **macOS**: \`build-artifacts-macos-latest\`
+ - **Linux**: \`build-artifacts-ubuntu-latest\`
+
+ *Note: Artifacts are available for 7 days.*`;
+ } else if (buildResult === 'failure') {
+ comment = `## ❌ Build Failed
+
+ Unfortunately, one or more builds failed. Please check the workflow run for details:
+
+ **[View Workflow Run](${runUrl})**`;
+ } else {
+ comment = `## ⚠️ Build Status: ${buildResult}
+
+ The build process completed with status: **${buildResult}**
+
+ **[View Workflow Run](${runUrl})**`;
+ }
+
+ github.rest.issues.createComment({
+ issue_number: context.issue.number,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: comment
+ });
diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml
index ffcb5a8567..844a3ed3ed 100644
--- a/.github/workflows/reviewdog.yml
+++ b/.github/workflows/reviewdog.yml
@@ -6,8 +6,8 @@ env:
NODE_VERSION: "22.x"
jobs:
- eslint:
- name: runner / eslint
+ biome:
+ name: runner / Biome
runs-on: ubuntu-latest
permissions:
contents: read
@@ -33,9 +33,8 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- - uses: reviewdog/action-eslint@v1.34.0
+ - uses: mongolyy/reviewdog-action-biome@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review # Change reporter.
- eslint_flags: './src'
fail_level: error
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index c6ce9c54f4..0000000000
--- a/.prettierrc
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "tabWidth": 2,
- "useTabs": false,
- "singleQuote": true,
- "trailingComma": "all",
- "quoteProps": "consistent"
-}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000..699ed73319
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["biomejs.biome"]
+}
diff --git a/README.md b/README.md
index a74b572305..cc19ba8878 100644
--- a/README.md
+++ b/README.md
@@ -1,21 +1,20 @@
-# YTMD
+# :pear: Pear Desktop
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/eslint.config.mjs)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
+[](https://github.com/pear-devs/pear-desktop/releases/)
+[](https://github.com/pear-devs/pear-desktop/blob/master/license)
+[](https://biomejs.dev/)
+[](https://GitHub.com/pear-devs/pear-desktop/releases/)
+[](https://GitHub.com/pear-devs/pear-desktop/releases/)
+
+[](https://snyk.io/test/github/pear-devs/pear-desktop)
-
+
-- Native look & feel extension, aims at keeping the original interface
- one click
+- Native look & feel extension
> [!IMPORTANT]
> ⚠️ Disclaimer
@@ -63,52 +62,52 @@ You can help with translation on [Hosted Weblate](https://hosted.weblate.org/pro
## Download
-You can check out the [latest release](https://github.com/th-ch/youtube-music/releases/latest) to quickly find the
+You can check out the [latest release](https://github.com/pear-devs/pear-desktop/releases/latest) to quickly find the
latest version.
### Arch Linux
-Install the [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) package from the AUR. For AUR installation instructions, take a look at
+Install the [`pear-desktop`](https://aur.archlinux.org/packages/pear-desktop) package from the AUR. For AUR installation instructions, take a look at
this [wiki page](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
### macOS
-You can install the app using Homebrew (see the [cask definition](https://github.com/th-ch/homebrew-youtube-music)):
+You can install the app using Homebrew (see the [cask definition](https://github.com/pear-devs/pear-desktop-homebrew)):
```bash
-brew install th-ch/youtube-music/youtube-music
+brew install pear-devs/pear-desktop
```
If you install the app manually and get an error "is damaged and can’t be opened." when launching the app, run the following in the Terminal:
```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
+/usr/bin/xattr -cr /Applications/Pear\ Desktop.app
```
### Windows
-You can use the [Scoop package manager](https://scoop.sh) to install the `youtube-music` package from
+You can use the [Scoop package manager](https://scoop.sh) to install the `pear-desktop` package from
the [`extras` bucket](https://github.com/ScoopInstaller/Extras).
```bash
scoop bucket add extras
-scoop install extras/youtube-music
+scoop install extras/pear-desktop
```
Alternately you can use [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), Windows 11s
-official CLI package manager to install the `th-ch.YouTubeMusic` package.
+official CLI package manager to install the `pear-devs.pear-desktop` package.
*Note: Microsoft Defender SmartScreen might block the installation since it is from an "unknown publisher". This is also
true for the manual installation when trying to run the executable(.exe) after a manual download here on github (same
file).*
```bash
-winget install th-ch.YouTubeMusic
+winget install pear-devs.pear-desktop
```
#### How to install without a network connection? (in Windows)
-- Download the `*.nsis.7z` file for _your device architecture_ in [release page](https://github.com/th-ch/youtube-music/releases/latest).
+- Download the `*.nsis.7z` file for _your device architecture_ in [release page](https://github.com/pear-devs/pear-desktop/releases/latest).
- `x64` for 64-bit Windows
- `ia32` for 32-bit Windows
- `arm64` for ARM64 Windows
@@ -125,8 +124,8 @@ Some predefined themes are available in https://github.com/kerichdev/themes-for-
## Dev
```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
+git clone https://github.com/pear-devs/pear-desktop
+cd pear-desktop
pnpm install --frozen-lockfile
pnpm dev
```
@@ -191,7 +190,7 @@ export default createPlugin({
console.log(await context.ipc.invoke('some-event'));
},
// Only renderer available hook
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
+ onPlayerApiReady(api, context) {
// set plugin config easily
context.setConfig({ myConfig: api.getVolume() });
},
@@ -220,7 +219,7 @@ import { createPlugin } from '@/utils';
export default createPlugin({
name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic will show a restart dialog
+ restartNeeded: true, // if value is true, pear-desktop will show a restart dialog
config: {
enabled: false,
}, // your custom config
@@ -282,7 +281,7 @@ Uses [Playwright](https://playwright.dev/) to test the app.
## License
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
+MIT © [pear-devs](https://github.com/pear-devs/pear-desktop)
## FAQ
diff --git a/biome.jsonc b/biome.jsonc
new file mode 100644
index 0000000000..0d18127c71
--- /dev/null
+++ b/biome.jsonc
@@ -0,0 +1,243 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.2.5/schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "ignoreUnknown": false
+ },
+ "formatter": {
+ "enabled": true,
+ "formatWithErrors": false,
+ "indentStyle": "space",
+ "indentWidth": 2,
+ "lineEnding": "lf",
+ "lineWidth": 80,
+ "attributePosition": "auto",
+ "bracketSameLine": false,
+ "bracketSpacing": true,
+ "expand": "auto",
+ "useEditorconfig": true
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": false,
+ "complexity": {
+ "noAdjacentSpacesInRegex": "error",
+ "noExtraBooleanCast": "error",
+ "noUselessCatch": "error",
+ "noUselessEscapeInRegex": "error",
+ "noUselessThisAlias": "error",
+ "noUselessTypeConstraint": "error",
+ "noVoid": "error",
+ "useArrowFunction": "off"
+ },
+ "correctness": {
+ "noConstAssign": "error",
+ "noConstantCondition": "error",
+ "noEmptyCharacterClassInRegex": "error",
+ "noEmptyPattern": "error",
+ "noGlobalObjectCalls": "error",
+ "noInvalidBuiltinInstantiation": "error",
+ "noInvalidConstructorSuper": "error",
+ "noNonoctalDecimalEscape": "error",
+ "noPrecisionLoss": "error",
+ "noSelfAssign": "error",
+ "noSetterReturn": "error",
+ "noSwitchDeclarations": "error",
+ "noUndeclaredVariables": "error",
+ "noUnreachable": "error",
+ "noUnreachableSuper": "error",
+ "noUnsafeFinally": "error",
+ "noUnsafeOptionalChaining": "error",
+ "noUnusedLabels": "error",
+ "noUnusedPrivateClassMembers": "error",
+ "noUnusedVariables": "error",
+ "useIsNan": "error",
+ "useValidForDirection": "error",
+ "useValidTypeof": "error",
+ "useYield": "error"
+ },
+ "nursery": {
+ "noFloatingPromises": "off",
+ "noMisusedPromises": "off",
+ "noNonNullAssertedOptionalChain": "off",
+ "noUnusedExpressions": "off",
+ "useConsistentArrowReturn": "off"
+ },
+ "style": {
+ "noCommonJs": "error",
+ "noNamespace": "warn",
+ "noNonNullAssertion": "off",
+ "useArrayLiterals": "error",
+ "useAsConstAssertion": "error",
+ "useBlockStatements": "off",
+ "useImportType": {
+ "level": "error",
+ "options": {
+ "style": "inlineType"
+ }
+ },
+ "useThrowOnlyError": "off"
+ },
+ "suspicious": {
+ "noAssignInExpressions": "warn",
+ "noAsyncPromiseExecutor": "error",
+ "noCatchAssign": "error",
+ "noClassAssign": "error",
+ "noCompareNegZero": "error",
+ "noConstantBinaryExpressions": "error",
+ "noControlCharactersInRegex": "error",
+ "noDebugger": "error",
+ "noDuplicateCase": "error",
+ "noDuplicateClassMembers": "error",
+ "noDuplicateElseIf": "error",
+ "noDuplicateObjectKeys": "error",
+ "noDuplicateParameters": "error",
+ "noEmptyBlockStatements": "warn",
+ "noExplicitAny": "error",
+ "noExtraNonNullAssertion": "error",
+ "noFallthroughSwitchClause": "error",
+ "noFunctionAssign": "error",
+ "noGlobalAssign": "error",
+ "noImportAssign": "error",
+ "noIrregularWhitespace": "error",
+ "noMisleadingCharacterClass": "error",
+ "noMisleadingInstantiator": "error",
+ "noPrototypeBuiltins": "error",
+ "noRedeclare": "error",
+ "noShadowRestrictedNames": "error",
+ "noSparseArray": "error",
+ "noTsIgnore": "error",
+ "noUnsafeDeclarationMerging": "error",
+ "noUnsafeNegation": "error",
+ "noUselessRegexBackrefs": "error",
+ "noWith": "error",
+ "useAwait": "error",
+ "useGetterReturn": "error",
+ "useNamespaceKeyword": "error"
+ }
+ },
+ "includes": [
+ "**",
+ "!dist",
+ "!node_modules",
+ "!*.config.*js",
+ "!*.test.*js"
+ ]
+ },
+ "javascript": {
+ "formatter": {
+ "jsxQuoteStyle": "double",
+ "quoteProperties": "asNeeded",
+ "trailingCommas": "all",
+ "semicolons": "always",
+ "arrowParentheses": "always",
+ "bracketSameLine": false,
+ "quoteStyle": "single",
+ "attributePosition": "auto",
+ "bracketSpacing": true
+ },
+ "globals": []
+ },
+ "html": {
+ "formatter": {
+ "selfCloseVoidElements": "always"
+ }
+ },
+ "overrides": [
+ {
+ "includes": [
+ "**/*.ts",
+ "**/*.tsx",
+ "**/*.mts",
+ "**/*.cts"
+ ],
+ "linter": {
+ "rules": {
+ "complexity": {
+ "noArguments": "error"
+ },
+ "correctness": {
+ "noConstAssign": "off",
+ "noGlobalObjectCalls": "off",
+ "noInvalidBuiltinInstantiation": "off",
+ "noInvalidConstructorSuper": "off",
+ "noSetterReturn": "off",
+ "noUndeclaredVariables": "off",
+ "noUnreachable": "off",
+ "noUnreachableSuper": "off"
+ },
+ "style": {
+ "useConst": "error"
+ },
+ "suspicious": {
+ "noClassAssign": "off",
+ "noDuplicateClassMembers": "off",
+ "noDuplicateObjectKeys": "off",
+ "noDuplicateParameters": "off",
+ "noFunctionAssign": "off",
+ "noImportAssign": "off",
+ "noRedeclare": "off",
+ "noUnsafeNegation": "off",
+ "noVar": "error",
+ "noWith": "off",
+ "useGetterReturn": "off"
+ }
+ }
+ }
+ },
+ {
+ "includes": [
+ "**/*.ts",
+ "**/*.tsx",
+ "**/*.mts",
+ "**/*.cts"
+ ],
+ "linter": {
+ "rules": {
+ "complexity": {
+ "noArguments": "error"
+ },
+ "correctness": {
+ "noConstAssign": "off",
+ "noGlobalObjectCalls": "off",
+ "noInvalidBuiltinInstantiation": "off",
+ "noInvalidConstructorSuper": "off",
+ "noSetterReturn": "off",
+ "noUndeclaredVariables": "off",
+ "noUnreachable": "off",
+ "noUnreachableSuper": "off"
+ },
+ "style": {
+ "useConst": "error"
+ },
+ "suspicious": {
+ "noClassAssign": "off",
+ "noDuplicateClassMembers": "off",
+ "noDuplicateObjectKeys": "off",
+ "noDuplicateParameters": "off",
+ "noFunctionAssign": "off",
+ "noImportAssign": "off",
+ "noRedeclare": "off",
+ "noUnsafeNegation": "off",
+ "noVar": "error",
+ "noWith": "off",
+ "useGetterReturn": "off"
+ }
+ }
+ }
+ }
+ ],
+ "assist": {
+ "enabled": true,
+ "actions": {
+ "source": {
+ "organizeImports": "on"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/favicon/favicon.ico b/docs/favicon/favicon.ico
deleted file mode 100644
index c4739a9e86..0000000000
Binary files a/docs/favicon/favicon.ico and /dev/null differ
diff --git a/docs/favicon/favicon_144.png b/docs/favicon/favicon_144.png
deleted file mode 100644
index bda6888e32..0000000000
Binary files a/docs/favicon/favicon_144.png and /dev/null differ
diff --git a/docs/favicon/favicon_32.png b/docs/favicon/favicon_32.png
deleted file mode 100644
index 23792c9e58..0000000000
Binary files a/docs/favicon/favicon_32.png and /dev/null differ
diff --git a/docs/favicon/favicon_48.png b/docs/favicon/favicon_48.png
deleted file mode 100644
index bdddff9e40..0000000000
Binary files a/docs/favicon/favicon_48.png and /dev/null differ
diff --git a/docs/favicon/favicon_96.png b/docs/favicon/favicon_96.png
deleted file mode 100644
index 31eec83b8b..0000000000
Binary files a/docs/favicon/favicon_96.png and /dev/null differ
diff --git a/docs/img/bg-bottom.svg b/docs/img/bg-bottom.svg
deleted file mode 100644
index 65be2bd7a4..0000000000
--- a/docs/img/bg-bottom.svg
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/img/bg-top.svg b/docs/img/bg-top.svg
deleted file mode 100644
index 9eae3cdda5..0000000000
--- a/docs/img/bg-top.svg
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/img/code.svg b/docs/img/code.svg
deleted file mode 100644
index 75ccd91c5e..0000000000
--- a/docs/img/code.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-
- </>
-
-
diff --git a/docs/img/download.svg b/docs/img/download.svg
deleted file mode 100644
index 6de6cbb72c..0000000000
--- a/docs/img/download.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
diff --git a/docs/img/plugins.svg b/docs/img/plugins.svg
deleted file mode 100644
index 9aab85e833..0000000000
--- a/docs/img/plugins.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
diff --git a/docs/index.html b/docs/index.html
deleted file mode 100644
index 7f0d06b551..0000000000
--- a/docs/index.html
+++ /dev/null
@@ -1,484 +0,0 @@
-
-
-
-
-
-
-
- YTMD App (Unofficial)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Custom YTMD App
-
-
- Open source, cross-platform, unofficial YTMD
- App
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Built-in adblocker
-
Block all ads and tracking out of the box
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Many other plugins in one click
-
- Enhance your user experience with media keys, integrations
- (Discord), cosmetic filters, notifications, TouchBar,
- auto-unpause and many more! Every plugin can be enabled or
- disabled in one click.
-
-
-
-
-
-
-
-
-
Open source & Cross platform
-
- Available for Windows (installer and portable), Mac and
- Linux (AppImage, deb, etc)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/js/main.js b/docs/js/main.js
deleted file mode 100644
index d7587ce954..0000000000
--- a/docs/js/main.js
+++ /dev/null
@@ -1,268 +0,0 @@
-/* eslint-disable */
-
-// Constants
-const element = document.documentElement;
-const { body } = document;
-const revealOnScroll = (window.sr = ScrollReveal({ mobile: false }));
-
-// Load animations
-element.classList.remove('no-js');
-element.classList.add('js');
-window.addEventListener('load', () => {
- body.classList.add('is-loaded');
-});
-
-if (body.classList.contains('has-animations')) {
- window.addEventListener('load', () => {
- revealOnScroll.reveal('.feature-extended .device-mockup', {
- duration: 600,
- distance: '100px',
- easing: 'cubic-bezier(0.215, 0.61, 0.355, 1)',
- origin: 'bottom',
- viewFactor: 0.6,
- });
- revealOnScroll.reveal('.feature-extended .feature-extended-body', {
- duration: 600,
- distance: '40px',
- easing: 'cubic-bezier(0.215, 0.61, 0.355, 1)',
- origin: 'top',
- viewFactor: 0.6,
- });
- });
-}
-
-// Bubble canvas
-const bubbleCanvas = function (t) {
- const e = this;
- e.parentNode = t;
- e.setCanvasSize();
- window.addEventListener('resize', () => {
- e.setCanvasSize();
- });
- e.mouseX = 0;
- e.mouseY = 0;
- window.addEventListener('mousemove', (t) => {
- e.mouseX = t.clientX;
- e.mouseY = t.clientY;
- });
- e.randomise();
-};
-
-bubbleCanvas.prototype.setCanvasSize = function () {
- this.canvasWidth = this.parentNode.clientWidth;
- this.canvasHeight = this.parentNode.clientHeight;
-};
-
-bubbleCanvas.prototype.generateDecimalBetween = function (start, end) {
- return (Math.random() * (start - end) + end).toFixed(2);
-};
-
-bubbleCanvas.prototype.update = function () {
- const t = this;
- t.translateX -= t.movementX;
- t.translateY -= t.movementY;
- t.posX += (t.mouseX / (t.staticity / t.magnetism) - t.posX) / t.smoothFactor;
- t.posY += (t.mouseY / (t.staticity / t.magnetism) - t.posY) / t.smoothFactor;
- if (
- t.translateY + t.posY < 0
- || t.translateX + t.posX < 0
- || t.translateX + t.posX > t.canvasWidth
- ) {
- t.randomise();
- t.translateY = t.canvasHeight;
- }
-};
-
-bubbleCanvas.prototype.randomise = function () {
- this.colors = ['195,53,46', '172,54,46'];
-
- this.velocity = 20;
- this.smoothFactor = 50;
- this.staticity = 30;
- this.magnetism = 0.1 + 4 * Math.random();
- this.color = this.colors[Math.floor(Math.random() * this.colors.length)];
- this.alpha = this.generateDecimalBetween(5, 10) / 10;
- this.size = this.generateDecimalBetween(1, 4);
- this.posX = 0;
- this.posY = 0;
- this.movementX = this.generateDecimalBetween(-2, 2) / this.velocity;
- this.movementY = this.generateDecimalBetween(1, 20) / this.velocity;
- this.translateX = this.generateDecimalBetween(0, this.canvasWidth);
- this.translateY = this.generateDecimalBetween(0, this.canvasHeight);
-};
-
-const drawBubbleCanvas = function (t) {
- this.canvas = document.getElementById(t);
- this.ctx = this.canvas.getContext('2d');
- this.dpr = window.devicePixelRatio;
-};
-
-drawBubbleCanvas.prototype.start = function (bubbleDensity) {
- const t = this;
- t.bubbleDensity = bubbleDensity;
- t.setCanvasSize();
- window.addEventListener('resize', () => {
- t.setCanvasSize();
- });
- t.bubblesList = [];
- t.generateBubbles();
- t.animate();
-};
-
-drawBubbleCanvas.prototype.setCanvasSize = function () {
- this.container = this.canvas.parentNode;
- this.w = this.container.offsetWidth;
- this.h = this.container.offsetHeight;
- this.wdpi = this.w * this.dpr;
- this.hdpi = this.h * this.dpr;
- this.canvas.width = this.wdpi;
- this.canvas.height = this.hdpi;
- this.canvas.style.width = this.w + 'px';
- this.canvas.style.height = this.h + 'px';
- this.ctx.scale(this.dpr, this.dpr);
-};
-
-drawBubbleCanvas.prototype.animate = function () {
- const t = this;
- t.ctx.clearRect(0, 0, t.canvas.clientWidth, t.canvas.clientHeight);
- for (const e of t.bubblesList) {
- e.update();
- t.ctx.translate(e.translateX, e.translateY);
- t.ctx.beginPath();
- t.ctx.arc(e.posX, e.posY, e.size, 0, 2 * Math.PI);
- t.ctx.fillStyle = 'rgba(' + e.color + ',' + e.alpha + ')';
- t.ctx.fill();
- t.ctx.setTransform(t.dpr, 0, 0, t.dpr, 0, 0);
- }
-
- requestAnimationFrame(this.animate.bind(this));
-};
-
-drawBubbleCanvas.prototype.addBubble = function (t) {
- return this.bubblesList.push(t);
-};
-
-drawBubbleCanvas.prototype.generateBubbles = function () {
- const t = this;
- for (let e = 0; e < t.bubbleDensity; e++) {
- t.addBubble(new bubbleCanvas(t.canvas.parentNode));
- }
-};
-
-// Night sky with stars canvas
-const starCanvas = function (t) {
- this.canvas = document.getElementById(t);
- this.ctx = this.canvas.getContext('2d');
- this.dpr = window.devicePixelRatio;
-};
-
-starCanvas.prototype.start = function () {
- let w;
- let h;
-
- const setCanvasExtents = () => {
- w = this.canvas.parentNode.clientWidth;
- h = this.canvas.parentNode.clientHeight;
- this.canvas.width = w;
- this.canvas.height = h;
- };
-
- setCanvasExtents();
-
- window.addEventListener('resize', () => {
- setCanvasExtents();
- });
-
- const makeStars = (count) => {
- const out = [];
- for (let i = 0; i < count; i++) {
- const s = {
- x: Math.random() * w - w / 2,
- y: Math.random() * h - h / 2,
- z: Math.random() * 1000,
- };
- out.push(s);
- }
-
- return out;
- };
-
- const stars = makeStars(10_000);
-
- const clear = () => {
- this.ctx.fillStyle = '#212121';
- this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
- };
-
- const putPixel = (x, y, brightness) => {
- const intensity = brightness * 255;
- const rgb = 'rgb(' + intensity + ',' + intensity + ',' + intensity + ')';
- this.ctx.beginPath();
- this.ctx.arc(x, y, 0.9, 0, 2 * Math.PI);
- this.ctx.fillStyle = rgb;
- this.ctx.fill();
- };
-
- const moveStars = (distance) => {
- const count = stars.length;
- for (let i = 0; i < count; i++) {
- const s = stars[i];
- s.z -= distance;
- while (s.z <= 1) {
- s.z += 1000;
- }
- }
- };
-
- let previousTime;
- const init = (time) => {
- previousTime = time;
- requestAnimationFrame(tick);
- };
-
- const tick = (time) => {
- const elapsed = time - previousTime;
- previousTime = time;
-
- moveStars(elapsed * 0.1);
-
- clear();
-
- const cx = w / 2;
- const cy = h / 2;
-
- const count = stars.length;
- for (let i = 0; i < count; i++) {
- const star = stars[i];
-
- const x = cx + star.x / (star.z * 0.001);
- const y = cy + star.y / (star.z * 0.001);
-
- if (x < 0 || x >= w || y < 0 || y >= h) {
- continue;
- }
-
- const d = star.z / 1000;
- const b = 1 - d * d;
-
- putPixel(x, y, b);
- }
-
- requestAnimationFrame(tick);
- };
-
- requestAnimationFrame(init);
-};
-
-// Start canvas animations
-window.addEventListener('load', () => {
- // Stars
- const headCanvas = new starCanvas('hero-particles');
- // Bubbles
- const footerCanvas = new drawBubbleCanvas('footer-particles');
- const mainCanvas = new drawBubbleCanvas('main-particles');
-
- headCanvas.start();
- footerCanvas.start(30);
- mainCanvas.start(200);
-});
diff --git a/docs/readme/README-es.md b/docs/readme/README-es.md
deleted file mode 100644
index 35bd74b657..0000000000
--- a/docs/readme/README-es.md
+++ /dev/null
@@ -1,392 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Lee esto en otros idiomas: [🏴 Inglés](../../README.md), [🇰🇷 Coreano](./README-ko.md), [🇫🇷 Francés](./README-fr.md), [🇮🇸 Islandés](./README-is.md), [🇪🇸 Español](./README-es.md), [🇷🇺 Ruso](./README-ru.md), [🇺🇦 Ucraniano](./README-uk.md), [🇧🇷 Portugués](./README-pt.md), [🇯🇵 Japonés](./README-ja.md)
-
-**Electron wrapper de YouTube Music con las siguientes características:**
-
-- Apariencia y sensación nativa, tiene como objetivo mantener la interfaz original
-- Framework para plugins personalizados: cambia YouTube Music según tus necesidades (estilo, contenido, funciones), habilita/deshabilita plugins con un solo clic
-
-## Imagen de demostración
-
-| Pantalla del reproductor (color del álbum como tema y luz ambiental) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Contenido
-
-- [Características](#características)
-- [Plugins disponibles](#plugins-disponibles)
-- [Traducción](#traducción)
-- [Descarga](#descarga)
- - [Arch Linux](#arch-linux)
- - [macOS](#macos)
- - [Windows](#windows)
- - [Cómo instalar sin conexión a internet? (en Windows)](#cómo-instalar-sin-conexión-a-internet-en-windows)
-- [Temas](#temas)
-- [Dev](#dev)
-- [Crea tus propios plugins](#crea-tus-propios-plugins)
- - [Creación de un plugin](#creación-de-un-plugin)
- - [Casos de uso comunes](#casos-de-uso-comunes)
-- [Compilar](#compilar)
-- [Vista previa de producción](#vista-previa-de-producción)
-- [Tests](#tests)
-- [Licencia](#licencia)
-- [Preguntas frecuentes](#preguntas-frecuentes)
-
-## Características:
-
-- **Confirmación automática al pausar** (Siempre habilitado): desactiva
- el mensaje emergente ["¿Continuar reproduciendo?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png)
- que pausa la música después de cierto tiempo
-
-- Y más ...
-
-## Plugins disponibles:
-
-- **Bloqueador de Anuncios**: Bloquea todos los anuncios y rastreadores de forma predeterminada
-
-- **Acciones de Álbum**: Agrega botones de deshacer No me gusta, No me gusta, Me gusta, y Deshacer me gusta a todas las canciones de una lista de reproducción o álbum
-
-- **Tema de Color del Álbum**: Aplica un tema dinámico y efectos visuales basados en la paleta de colores del álbum
-
-- **Modo Ambiente**: Aplica un efecto de iluminación proyectando colores suaves del video en el fondo de tu pantalla
-
-- **Compresor de Audio**: Aplica compresión al audio (reduce el volumen de las partes más fuertes de la señal y aumenta el
- volumen de las partes más suaves)
-
-- **Barra de Navegación Difuminada**: hace que la barra de navegación sea transparente y borrosa
-
-- **Omitir Restricciones de Edades**: omite la verificación de edad de YouTube
-
-- **Selector de Subtítulos**: Habilita los subtítulos
-
-- **Barra Lateral Compacta**: Siempre muestra la barra lateral en modo compacto
-
-- **Crossfade**: Transición suave entre canciones
-
-- **Desactivar Reproducción Automática**: Hace que cada canción comience en modo "pausado"
-
-- **[Discord](https://discord.com/) Rich Presence**: Muestra a tus amigos lo que estás escuchando
- con [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Descargador**: Descarga
- MP3 [directamente desde la interfaz](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Volumen Exponencial**: Hace que el control de volumen
- sea [exponencial](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) para facilitar la
- selección de volúmenes más bajos
-
-- **Menú en la Aplicación**: [da a las barras un aspecto elegante y oscuro](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (consulta [esta publicación](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) si tienes problemas
- para acceder al menú después de habilitar este plugin y la opción hide-menu)
-
-- **Scrobbler**: Agrega soporte para scrobbling en [Last.fm](https://www.last.fm/) y [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream**: Agrega soporte para [Lumia Stream](https://lumiastream.com/)
-
-- **Letras Genius**: Agrega soporte de letras para la mayoría de las canciones
-
-- **Music Together**: Comparte una lista de reproducción con otros. Cuando el anfitrión reproduce una canción, todos los demás escucharán la misma canción
-
-- **Navegación**: Flechas de siguiente/anterior integradas directamente en la interfaz, como en tu navegador favorito
-
-- **Sin Inicio de Sesión de Google**: Elimina los botones y enlaces de inicio de sesión de Google de la interfaz
-
-- **Notificaciones**: Muestra una notificación cuando comienza una canción
- a reproducirse ([notificaciones interactivas](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png)
- están disponibles en Windows)
-
-- **Picture-in-picture**: permite cambiar la aplicación al modo picture-in-picture
-
-- **Velocidad de Reproducción**: Escucha rápido, escucha
- lento! [Agrega un deslizador que controla la velocidad de reproducción de las canciones](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Volumen Preciso**: Controla el volumen de forma precisa utilizando la rueda del mouse/atajos de teclado, con un HUD personalizado y pasos de volumen personalizables
-
-- **Atajos (& MPRIS)**: Permite configurar atajos globales para la reproducción (reproducir/pausar/siguiente/anterior) +
- desactivar [osd multimedia](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png)
- al anular las teclas multimedia + habilitar Ctrl/CMD + F para buscar + habilitar el soporte mpris de Linux para
- teclas multimedia + [atajos personalizados](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50)
- para [usuarios avanzados](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-
-- **Omitir Canciones No Deseadas**: Salta las canciones que no te gustan
-
-- **Saltar Silencios**: Salta automáticamente las secciones de silencio
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Salta automáticamente las partes que no son de música, como la introducción/final o
- partes de videos musicales donde no se reproduce la canción
-
-- **Control Multimedia en la Barra de Tareas**: Controla la reproducción desde
- la [barra de tareas de Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **TouchBar**: Diseño personalizado de TouchBar para macOS
-
-- **Tuna OBS**: Integración con el complemento [Tuna](https://obsproject.com/forum/resources/tuna.843/) de [OBS](https://obsproject.com/)
-
-- **Cambiador de Calidad de Video**: Permite cambiar la calidad del video con
- un [botón](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) en
- la superposición de video
-
-- **Alternar Video**: Agrega
- un [botón](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) para
- alternar entre el modo de video/canción. también puede eliminar opcionalmente toda la pestaña de video
-
-- **Visualizador**: Diferentes visualizadores de música
-
-## Traducción
-
-Puedes ayudar con la traducción en [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Descarga
-
-Puedes consultar la [última versión](https://github.com/th-ch/youtube-music/releases/latest) para encontrar rápidamente la versión más reciente.
-
-### Arch Linux
-
-Instala el paquete [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) desde AUR. Para obtener instrucciones de instalación de AUR, consulta esta [página del wiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### macOS
-
-Puedes instalar la aplicación usando Homebrew (consulta la [definición de cask](https://github.com/th-ch/homebrew-youtube-music)):
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Si instalas la aplicación manualmente y obtienes un error "está dañado y no se puede abrir" al iniciar la aplicación, ejecuta lo siguiente en la Terminal:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Puedes usar el [administrador de paquetes Scoop](https://scoop.sh) para instalar el paquete `youtube-music` desde
-el [`extras` bucket](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Alternativamente, puedes usar [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), el administrador de paquetes CLI oficial de Windows 11 para instalar el paquete `th-ch.YouTubeMusic`.
-
-*Nota: Microsoft Defender SmartScreen podría bloquear la instalación ya que proviene de un "editor desconocido". Esto también esválido para la instalación manual al intentar ejecutar el ejecutable (.exe) después de una descarga manual aquí en GitHub (mismo archivo).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Cómo instalar sin conexión a Internet? (en Windows)
-
-- Descarga el archivo `*.nsis.7z` para _la arquitectura de tu dispositivo_ en la [página de lanzamientos](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` para Windows de 64 bits
- - `ia32` para Windows de 32 bits
- - `arm64` para Windows ARM64
-- Descarga el instalador en la página de lanzamientos. (`*-Setup.exe`)
-- Colócalos en el **mismo directorio**.
-- Ejecuta el instalador.
-
-## Temas
-
-Puedes cargar archivos CSS para cambiar la apariencia de la aplicación (Opciones > Ajustes visuales > Tema).
-
-Algunos temas predefinidos están disponibles en https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Dev
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Crea tus propios plugins
-
-Usando plugins, puedes:
-
-- manipular la aplicación - se pasa el `BrowserWindow` de electron al controlador del plugin
-- cambiar la interfaz manipulando el HTML/CSS
-
-### Creación de un plugin
-
-Crea una carpeta en `src/plugins/NOMBRE-DEL-PLUGIN`:
-
-- `index.ts`: el archivo principal del plugin
-```typescript
-import style from './style.css?inline'; // importar estilo como inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: "Plugin Label",
- restartNeeded: true, // si el valor es true, ytmusic muestra el diálogo de reinicio
- config: {
- enabled: false,
- }, // tu configuración personalizada
- stylesheets: [style], // tu estilo personalizado,
- menu: async ({ getConfig, setConfig }) => {
- // Todos los métodos *Config están envueltos en Promise
- const config = await getConfig();
- return [
- {
- label: "menu",
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: "radio",
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // puedes comunicarte con el plugin de renderizado
- ipc.handle("some-event", () => {
- return "hello";
- });
- },
- // se activa cuando cambia la configuración
- onConfigChange(newConfig) { /* ... */ },
- // se activa cuando se desactiva el plugin
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke("some-event"));
- },
- // Solo disponible en el plugin de renderizado
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // establecer la configuración del plugin fácilmente
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-
-```
-
-### Casos de uso comunes
-
-- inyectar CSS personalizado: crea un archivo `style.css` en la misma carpeta y luego:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // importar estilo como inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // si el valor es true, ytmusic mostrará el diálogo de reinicio
- config: {
- enabled: false,
- }, // tu configuración personalizada
- stylesheets: [style], // tu estilo personalizado
- renderer() {} // define el hook del renderizador
-});
-```
-
-- Si quieres cambiar el HTML:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // si el valor es true, ytmusic mostrará el diálogo de reinicio
- config: {
- enabled: false,
- }, // tu configuración personalizada
- renderer() {
- // Elimina el botón de inicio de sesión
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // define el hook del renderizador
-});
-```
-
-- comunicación entre el front y el back: se puede hacer utilizando el módulo ipcMain de electron. Ver archivo `index.ts` y
- ejemplo en el plugin `sponsorblock`.
-
-## Compilar
-
-1. Clonar el repositorio
-2. Seguir [esta guía](https://pnpm.io/es/installation) para instalar `pnpm`
-3. Ejecutar `pnpm install --frozen-lockfile` para instalar las dependencias
-4. Ejecutar `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (arm64 para Debian)
-- `pnpm dist:linux:rpm-arm64` - Linux (arm64 para Fedora)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-Construye la aplicación para macOS, Linux y Windows,
-utilizando [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Vista previa de producción
-
-```bash
-pnpm start
-```
-
-## Tests
-
-```bash
-pnpm test
-```
-
-Utiliza [Playwright](https://playwright.dev/) para probar la aplicación.
-
-## Licencia
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## Preguntas frecuentes
-
-### ¿Por qué no se muestra el menú de aplicaciones?
-
-Si la opción `Ocultar menú` está activada - puedes mostrar el menú con la tecla alt (o \` [acento grave] si estás utilizando el plugin in-app-menu)
diff --git a/docs/readme/README-fr.md b/docs/readme/README-fr.md
deleted file mode 100644
index da0aa18d63..0000000000
--- a/docs/readme/README-fr.md
+++ /dev/null
@@ -1,389 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Lisez ceci dans d'autres langues: [🏴 Anglais](../../README.md), [🇰🇷 Coréen](./README-ko.md), [🇫🇷 Français](./README-fr.md), [🇮🇸 Islandais](./README-is.md), [🇪🇸 Espagnol](./README-es.md), [🇷🇺 Russe](./README-ru.md), [🇺🇦 Ukrainien](./README-uk.md), [🇧🇷 Portugais](./README-pt.md), [🇯🇵 Japonais](./README-ja.md)
-
-**Enveloppe Electron autour de YouTube Music offrant :**
-
-- Aspect & sensation naturels, vise à conserver l'interface originale
-- Cadre pour les plugins personnalisés : modifiez YouTube Music selon vos besoins (style, contenu, fonctionnalités), activez/désactivez les plugins en
- un clic
-
-## Image de démonstration
-
-| Écran du lecteur (thème de couleur de l'album & lumière ambiante) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Contenu
-
-- [Fonctionnalités](#fonctionnalités)
-- [Plugins disponibles](#plugins-disponibles)
-- [Traduction](#traduction)
-- [Téléchargement](#téléchargement)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Comment installer sans connexion réseau ? (sous Windows)](#comment-installer-sans-connexion-réseau-sous-windows)
-- [Thèmes](#thèmes)
-- [Dev](#dev)
-- [Créez vos propres plugins](#créez-vos-propres-plugins)
- - [Créer un plugin](#créer-un-plugin)
- - [Cas d'utilisation courants](#cas-dutilisation-courants)
-- [Construction](#construction)
-- [Aperçu de la production](#aperçu-de-la-production)
-- [Tests](#tests)
-- [Licence](#licence)
-- [FAQ](#faq)
-
-## Fonctionnalités :
-
-- **Confirmation automatique lors de la pause** (Toujours activé) : désactiver
- la pop-up ["Continuer à regarder ?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png)
- qui pause la musique après un certain temps
-
- - Et plus encore ...
-
-## Plugins disponibles :
-
-- **Bloqueur de publicités** : Bloquez toutes les publicités et le suivi dès le départ
-
-- **Actions d'album** : Ajoute des boutons Je n'aime pas, Dislike, J'aime, et Unlike pour appliquer cela à toutes les chansons dans une playlist ou un album
-
-- **Thème de couleur d'album** : Applique un thème dynamique et des effets visuels basés sur la palette de couleurs de l'album
-
-- **Mode Ambiant** : Applique un effet d'éclairage en projetant des couleurs douces de la vidéo, sur l'arrière-plan de votre écran
-
-- **Compresseur Audio** : Appliquer une compression audio (diminue le volume des parties les plus fortes du signal et augmente le
- volume des parties les plus douces)
-
-- **Barre de navigation floue** : rend la barre de navigation transparente et floue
-
-- **Contournement des restrictions d'âge** : contourner la vérification d'âge de YouTube
-
-- **Sélecteur de sous-titres** : Activer les sous-titres
-
-- **Barre latérale compacte** : Toujours définir la barre latérale en mode compact
-
-- **Fondu enchaîné** : Fondu enchaîné entre les chansons
-
-- **Désactiver la lecture automatique** : Fait démarrer chaque chanson en mode "pause"
-
-- **[Discord](https://discord.com/) Présence riche** : Montrez à vos amis ce que vous écoutez
- avec [Présence riche](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Téléchargeur** : télécharge des
- MP3 [directement depuis l'interface](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Volume exponentiel** : Rend le curseur de volume
- [exponentiel](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) afin qu'il soit plus facile de
- sélectionner des volumes plus bas
-
-- **Menu In-App** : [donne aux barres un aspect chic et sombre](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (voir [ce poste](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) si vous avez des problèmes
- pour accéder au menu après avoir activé ce plugin et l'option masquer-menu)
-
-- **Scrobbler** : Ajoute le support de scrobbling pour [Last.fm](https://www.last.fm/) et [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream** : Ajoute le support de [Lumia Stream](https://lumiastream.com/)
-
-- **Lyrics Genius** : Ajoute le support des paroles pour la plupart des chansons
-
-- **Musique Ensemble** : Partagez une playlist avec d'autres. Lorsque l'hôte joue une chanson, tout le monde entendra la même chanson
-
-- **Navigation** : Flèches de navigation Suivant/Retour directement intégrées dans l'interface, comme dans votre navigateur préféré
-
-- **Pas de connexion Google** : Supprime les boutons et les liens de connexion Google de l'interface
-
-- **Notifications** : Affiche une notification lorsqu'une chanson commence à jouer ([notifications interactives](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png)
- sont disponibles sur Windows)
-
-- **Image dans l'image** : permet de passer l'application en mode image dans l'image
-
-- **Vitesse de lecture** : Écoutez rapidement, écoutez lentement ! [Ajoute un curseur qui contrôle la vitesse des chansons](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Volume précis** : Contrôlez le volume précisément en utilisant la molette de la souris/raccourcis clavier, avec un hud personnalisé et des étapes de volume personnalisables
-
-- **Raccourcis (& MPRIS)** : Permet de définir des raccourcis globaux pour la lecture (lecture/pause/suivant/précédent) +
- désactive [osd média](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png)
- en remplaçant les touches multimédias + activer Ctrl/CMD + F pour rechercher + activer le support mpris linux pour
- les touches multimédias + [raccourcis personnalisés](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50)
- pour [utilisateurs avancés](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-
-- **Passer la chanson non aimée** : passe les chansons non aimées
-
-- **Passer les silences** : passe automatiquement les sections silencieuses
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock) : Saute automatiquement les parties non musicales comme les intros/outros ou
- les parties des clips vidéo où la chanson n'est pas jouée
-
-- **Contrôle multimédia de la barre des tâches** : Contrôlez la lecture depuis
- votre [barre des tâches Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **TouchBar** : Disposition personnalisée de la TouchBar pour macOS
-
-- **Tuna OBS** : Intégration avec le
- plugin [Tuna](https://obsproject.com/forum/resources/tuna.843/) d'[OBS](https://obsproject.com/)
-
-- **Changeur de qualité vidéo** : Permet de changer la qualité vidéo avec
- un [bouton](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) sur
- l'overlay vidéo
-
-- **Bascule vidéo** : Ajoute
- un [bouton](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) pour
- basculer entre le mode Vidéo/Chanson. peut également supprimer l'onglet vidéo entier
-
-- **Visualiseur** : Différents visualiseurs musicaux
-
-## Traduction
-
-Vous pouvez aider à la traduction sur [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Téléchargement
-
-Vous pouvez consulter la [dernière sortie](https://github.com/th-ch/youtube-music/releases/latest) pour trouver rapidement la
-dernière version.
-
-### Arch Linux
-
-Installez le paquet [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) depuis l'AUR. Pour les instructions d'installation de l'AUR, consultez
-cette [page wiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### MacOS
-
-Vous pouvez installer l'application en utilisant Homebrew (voir la [définition du fût](https://github.com/th-ch/homebrew-youtube-music)) :
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Si vous installez l'application manuellement et obtenez une erreur "est endommagé et ne peut pas être ouvert." lors du lancement de l'application, exécutez ce qui suit dans le Terminal :
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Vous pouvez utiliser le [gestionnaire de paquets Scoop](https://scoop.sh) pour installer le paquet `youtube-music` depuis le [seau `extras`](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Alternativement, vous pouvez utiliser [Winget](https://learn.microsoft.com/fr-fr/windows/package-manager/winget/), le gestionnaire de paquets CLI officiel de Windows 11, pour installer le paquet `th-ch.YouTubeMusic`.
-
-*Note : Microsoft Defender SmartScreen pourrait bloquer l'installation car elle provient d'un "éditeur inconnu". Ceci est également vrai pour l'installation manuelle lors de l'essai d'exécution de l'exécutable (.exe) après un téléchargement manuel ici sur GitHub (même fichier).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Comment installer sans connexion réseau ? (sous Windows)
-
-- Téléchargez le fichier `*.nsis.7z` pour _l'architecture de votre appareil_ sur la [page des versions](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` pour Windows 64 bits
- - `ia32` pour Windows 32 bits
- - `arm64` pour Windows ARM64
-- Téléchargez l'installeur sur la page des versions. (`*-Setup.exe`)
-- Placez-les dans le **même dossier**.
-- Exécutez l'installeur.
-
-## Thèmes
-
-Vous pouvez charger des fichiers CSS pour changer l'apparence de l'application (Options > Ajustements visuels > Thèmes).
-
-Certains thèmes prédéfinis sont disponibles sur [https://github.com/kerichdev/themes-for-ytmdesktop-player](https://github.com/kerichdev/themes-for-ytmdesktop-player).
-
-## Dev
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-## Créez vos propres plugins
-
-En utilisant des plugins, vous pouvez :
-
-- manipuler l'application - la `BrowserWindow` d'Electron est passée au gestionnaire de plugin
-- changer le front en manipulant le HTML/CSS
-
-### Créer un plugin
-
-Créez un dossier dans `src/plugins/NOM-DE-VOTRE-PLUGIN` :
-
-- `index.ts` : le fichier principal du plugin
-```typescript
-import style from './style.css?inline'; // importez le style comme inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Étiquette du plugin',
- restartNeeded: true, // si la valeur est vraie, ytmusic affichera la boîte de dialogue de redémarrage
- config: {
- enabled: false,
- }, // votre configuration personnalisée
- stylesheets: [style], // votre style personnalisé,
- menu: async ({ getConfig, setConfig }) => {
- // Toutes les méthodes *Config sont des promesses encapsulées
- const config = await getConfig();
- return [
- {
- label: 'menu',
- submenu: [1, 2, 3].map((value) => ({
- label: `valeur ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // vous pouvez communiquer avec le plugin du rendu
- ipc.handle('un événement', () => {
- return 'bonjour';
- });
- },
- // il est déclenché lorsque la configuration change
- onConfigChange(newConfig) { /* ... */ },
- // il est déclenché lorsque le plugin est désactivé
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('un événement'));
- },
- // Seul le crochet disponible pour le rendu
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // définir facilement la configuration du plugin
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config is obtained by `getConfig` method.
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-
-```
-
-### Cas d'utilisation courants
-
-- **Injection de CSS personnalisé** : créez un fichier `style.css` dans le même dossier puis :
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // importez le style comme en ligne
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Étiquette du plugin',
- restartNeeded: true, // si la valeur est vraie, ytmusic affichera la boîte de dialogue de redémarrage
- config: {
- enabled: false,
- }, // votre configuration personnalisée
- stylesheets: [style], // votre style personnalisé
- renderer() {} // définissez le crochet de rendu
-});
-```
-
-- **Si vous voulez modifier le HTML** :
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Étiquette du plugin',
- restartNeeded: true, // si la valeur est vraie, ytmusic affichera la boîte de dialogue de redémarrage
- config: {
- enabled: false,
- }, // votre configuration personnalisée
- renderer() {
- // Supprimez le bouton de connexion
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // définissez le crochet de rendu
-});
-
-```
-
-- **Communication entre le front et le back** : cela peut se faire en utilisant le module ipcMain d'Electron. Voir le fichier `index.ts` et l'exemple dans le plugin `sponsorblock`.
-
-## Construction
-
-1. Clonez le dépôt
-2. Suivez [ce guide](https://pnpm.io/installation) pour installer `pnpm`
-3. Exécutez `pnpm install --frozen-lockfile` pour installer les dépendances
-4. Exécutez `pnpm build:OS`
-
-- `pnpm dist:win` - pour Windows
-- `pnpm dist:linux` - pour Linux
-- `pnpm dist:mac` - pour MacOS
-
-Construit l'application pour macOS, Linux et Windows,
-en utilisant [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Aperçu de la production
-
-```bash
-pnpm start
-```
-
-## Tests
-
-```bash
-pnpm test
-```
-
-Utilise [Playwright](https://playwright.dev/) pour tester l'application.
-
-## Licence
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## FAQ
-
-### Pourquoi le menu de l'application ne s'affiche-t-il pas ?
-
-Si l'option `Masquer le menu` est activée - vous pouvez afficher le menu avec la touche alt (ou \` [backtick] si vous utilisez le plugin du menu intégré)
diff --git a/docs/readme/README-hu.md b/docs/readme/README-hu.md
deleted file mode 100644
index 6b473f878e..0000000000
--- a/docs/readme/README-hu.md
+++ /dev/null
@@ -1,374 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/eslint.config.mjs)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Olvasd el más nyelveken: [🏴 Angol](../../README.md), [🇰🇷 Korea](./README-ko.md), [🇫🇷 Francia](./README-fr.md), [🇮🇸 Izland](./README-is.md), [🇪🇸 Spanyol](./README-es.md), [🇷🇺 Orosz](./README-ru.md), [🇺🇦 Ukrán](./README-uk.md), [🇧🇷 Portugál](./README-pt.md), [🇯🇵 Japán](./README-ja.md)
-
-**Electron keretrendszerre épülő alkalmazás a YouTube Music számára, amely a következőket kínálja:**
-
-- Natív megjelenés és élmény, amely az eredeti felület megtartására törekszik
-- Egyedi bővítmények keretrendszere: alakítsd át a YouTube Music-ot igényeid szerint (stílus, tartalom, funkciók), engedélyezd/tiltsd le a bővítményeket egy kattintással
-
-## Bemutató kép
-
-| Lejátszó ablak (album színtéma és környezeti fény) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Tartalom
-
-- [Funkciók](#Funkciók)
-- [Elérhető bővítmények](#Elérhető-bővítmények)
-- [Fordítás](#Fordítás)
-- [Letöltés](#Letöltés)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Hogyan telepítsük hálózati kapcsolat nélkül? (Windows alatt)](#Hogyan-telepítsd-hálózati-kapcsolat-nélkül-Windows)
-- [Témák](#Témák)
-- [Fejlesztés](#Fejlesztés)
-- [Saját bővítmények készítése](#Saját-bővítmények-készítése)
- - [Bővítmény létrehozása](#Bővítmény-létrehozása)
- - [Gyakori használati esetek](#Gyakori-használati-esetek)
-- [Build](#build)
-- [Gyártás előnézete](#Gyártás-előnézete)
-- [Tesztelés](#Tesztelés)
-- [Licenc](#Licenc)
-- [GYIK](#GYIK)
-
-## Funkciók:
-
-- **Automatikus megerősítés a lejátszás szüneteltetésekor** (Alapból engedélyezve): Kikapcsolja a ["Folytatja a nézést?"](https://i.imgur.com/z2mG0QN.png)
- felugró ablakot, amely bizonyos idő után leállítja a zenét.
-
- - És még sok más ...
-
-## Elérhető bővítmények:
-
-- **Reklámblokkoló**: Blokkolja az összes hirdetést és nyomkövetőt.
-
-- **Album műveletek**: Dislike, Undislike, Like, Unlike gombok hozzáadása, amivel ezt a lejátszási listán vagy albumban lévő összes dalra alkalmazza.
-
-- **Album színtéma**: Dinamikus téma és vizuális effektek alkalmazása az album színpalettája alapján.
-
-- **Ambient mód**: Fényhatás alkalmazása a videóból származó lágy színek vetítésével a képernyő hátterére.
-
-- **Hangtömörítő**: Hang tömörítés alkalmazása. (csökkenti a jel legzajosabb részeinek hangerősségét, és emeli a legcsendesebb részek hangerősségét)
-
-- **Navigációs sáv elmosása**: Átlátszóvá és elmosódottá teszi a navigációs sávot.
-
-- **Korellenőrzés kihagyása**: A YouTube korellenőrzését kihagyja, ezáltal nem kel meg erősíteni a zene meghallgatása elött. (automatikusan megerősítve lesz)
-
-- **Feliratválasztó**: Felirat választó a YouTube Music zenékhez.
-
-- **Kompakt oldalsáv**: Mindig becsukva tartja a bal oldali sávot, ahol a Kezdőlap, Felfedezés, Könyvtár és egyebek láthatók. (amit bármikor ki lehet nyitni)
-
-- **Áttünés**: Áttünést biztosít a dalok között, ami folytonossá teszi a zenehallgatást anélkül, hogy érezhető lenne a váltás.
-
-- **Automatikus lejátszás letiltása**: Ez a funkció kikapcsolja az automatikus lejátszást, így a zenék nem indulnak el maguktól. Amikor egy album vagy egy dal lejátszása véget ér, a következő szám nem kezdődik el automatikusan. (a bővítmény használata során minden zenét manuálisan kell elindítani)
-
-- **[Discord](https://discord.com/) Rich Presence**: Mutassa meg barátainak, hogy mit hallgat a [Rich Presence](https://i.imgur.com/nCeVQB2.png) segítségével. (Ehez a Discord-on is engedélyezve kel lennie a Tevékenységállapot megosztásának [DC Beállítások -> Tevékenyég-adatvédelem -> Megoszthatod az észlelt tevékenységeidet másokkal])
-
-- **Letöltő**: MP3/forrás hanganyag letöltése [közvetlenül az interfészről](https://i.imgur.com/ghqBNVe.png). [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Hangszínszabályzó**: Szűrőket ad hozzá, hogy erősítsd vagy csökkentsd bizonyos frekvenciatartományokat. (pl. basszuskiemelés)
-
-- **Exponenciális hangerő**: A hangerő csúszka [exponenciálissá](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) tételével könnyebbé válik az alacsony hangerő kiválasztása.
-
-- **Alkalmazáson belüli menü**: [A Menüsáv stílusos, sötét vagy album-színű megjelenítése](https://i.imgur.com/vWvO7Xt.png).
-
- > (Lásd ezt a [bejegyzést](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709), ha problémád van a menü elérésével, miután engedélyezted ezt a bővítményt és a "menü elrejtése" opciót.
-
-- **Scrobbler**: Scrobbling támogatást biztosít [Last.fm](https://www.last.fm/) és [ListenBrainz](https://listenbrainz.org/) számára.
-
-- **Lumia Stream**: [Lumia Stream](https://lumiastream.com/) támogatás hozzáadása.
-
-- **Lyrics Genius**: Dalszöveg támogatást nyújt a legtöbb dalhoz.
-
-- **Zene együtt**: Lehetővé teszi a lejátszási listák, dalok megosztását másokkal. Amikor a házigazda lejátszik egy dalt, mindenki ugyanazt a dalt fogja hallani.
-
-- **Navigáció**: Következő/Vissza navigációs nyilak közvetlenül az interfészbe integrálva, mint a kedvenc böngésződben.
-
-- **Nincs Google bejelentkezés**: A Bejelentkezés gomb eltávolítása az interfészről (Jobb fentről eltünik a bejelentkezés gomb.)
-
-- **Értesítések**: Értesítés megjelenítése, amikor egy dal elindul. ([interaktív értesítések](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) elérhetők Windows-on)
-
-- **Kép a képben**: Lehetővé teszi az alkalmazás kép a képben módra váltását.
-
-- **Lejátszás sebessége**: Hallgassd gyorsan, hallgassd lassan! [Hozzáad egy csúszkát, amely szabályozza a dal sebességét](https://i.imgur.com/uaNOWOt.png)
-
-- **Precíz hangerő**: A hangerő precíz szabályozása egérgörgővel/gyorsbillentyűkkel, egy egyedi HUD és testreszabható hangerő csuszka segítségével.
-
-- **Gyorsbillentyűk (& MPRIS)**: Lehetővé teszi globális gyorsbillentyűk beállítását a lejátszáshoz (lejátszás/szünet/következő/előző), valamint a [média OSD](https://i.imgur.com/o13SpAE.png) kikapcsolását a médiagombok felülírásával. Bekapcsolja a Ctrl/CMD + F billentyűkombinációt a kereséshez, a Linux MPRIS támogatását a médiagombokhoz, és [egyedi gyorsbillentyűket](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) a [haladó felhasználók](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902) számára.
-
-- **Nem kedvelt dal kihagyása**: Kihagyja a nem kedvelt dalokat.
-
-- **Csend kihagyása**: Automatikusan átugorja a csendes szakaszokat.
-
-- [**SzponzorBlokk**](https://github.com/ajayyy/SponsorBlock): Automatikusan átugorja a nem zenei részeket, például az intrókat/outrokat vagy a zenei videók azon részeit, ahol a dal nem szól.
-
-- **Szinkronizált dalszövegek**: Szinkronizált dalszövegeket biztosít dalokhoz, [LRClib](https://lrclib.net)-hez hasonló szolgáltatókat használva.
-
-- **Médiavezérlés a tálcán**: Lejátszás vezérlése a [Windows tálcáról](https://i.imgur.com/eolQfnA.png).
-
-- **TouchBar**: Egyedi TouchBar elrendezés macOS-hoz.
-
-- **Tuna OBS**: Integráció az [OBS](https://obsproject.com/) [Tuna](https://obsproject.com/forum/resources/tuna.843/) pluginjával.
-
-- **Videóminőség modosító**: Lehetővé teszi a videó minőségének megváltoztatását egy [gombbal](https://i.imgur.com/UgpgtHL.png) a videó fedvényen.
-
-- **Videó váltó**: Hozzáad egy [gombot](https://i.imgur.com/288QE1k.png) a Videó/Dal mód közötti váltáshoz. (opcionálisan teljesen eltávolíthatja a videó fület is)
-
-- **Vizualizáció**: Különböző zenei vizualizációk.
-
-
-## Fordítás
-
-Segíthetsz a fordításban a [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/) oldalán.
-
-
-
-
-
-
-
-## Letöltés
-
-A [legfrissebb kiadás](https://github.com/th-ch/youtube-music/releases/latest) megtekintésével gyorsan megtalálhatod a legújabb verziót.
-
-### Arch Linux
-
-Telepítsd a [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) csomagot az AUR-ból. Az AUR telepítési útmutatóját megtalálod ezen a [wiki oldalon](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### macOS
-
-Telepítheted az alkalmazást Homebrew segítségével (lásd a [cask definíciót](https://github.com/th-ch/homebrew-youtube-music)):
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Ha manuálisan telepítetted az alkalmazást, és a következő hibát kapod indításkor: "sérült, és nem nyitható meg./is damaged and can’t be opened.", futtasd az alábbi parancsot a Terminálban:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-A [Scoop csomagkezelő](https://scoop.sh) segítségével telepítheted a `youtube-music` csomagot az [`extras` tárolóból](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Alternatívaként használhatod a [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) eszközt, a Windows 11 hivatalos CLI csomagkezelőjét, hogy telepítsd a `th-ch.YouTubeMusic` csomagot.
-
-*Megjegyzés: A Microsoft Defender SmartScreen figyelmeztethet vagy blokkolhatja a telepítést, mivel az alkalmazás "ismeretlen kiadótól" származik. Ez a figyelmeztetés akkor is megjelenhet, ha manuálisan töltöd le és próbálod futtatni a GitHubról letöltött (.exe) fájlt. Ebben az esetben kattints a "További információ" gombra, majd válaszd a "Futtatás mindenképp" opciót a telepítés folytatásához.*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Hogyan telepítsd hálózati kapcsolat nélkül? (Windows)
-
-- Töltsd le a `*.nsis.7z` fájlt a [kiadás oldal](https://github.com/th-ch/youtube-music/releases/latest)ról, amely megfelel az eszközöd architektúrájának:
- - `x64` 64 bites Windows-hoz
- - `ia32` 32 bites Windows-hoz
- - `arm64` ARM64 Windows-hoz
-- Töltsd le a telepítőt a [kiadás oldal](https://github.com/th-ch/youtube-music/releases/latest)ról. (`*-Setup.exe`)
-- Helyezd mindkét fájlt **ugyanabba a könyvtárba**.
-- Futtasd a telepítőt.
-
-## Témák
-
-CSS fájlokat tölthetsz be az alkalmazás megjelenésének megváltoztatásához. (Beállítások > Kinézeti beállítások > Téma)
-
-Néhány előre definiált téma elérhető itt: https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Fejlesztés
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Saját bővítmények készítése
-
-A bővítmények segítségével a következőket teheted:
-
-- Az alkalmazás manipulálása: Az Electron `BrowserWindow` objektuma átadásra kerül a bővítménykezelőnek.
-- Az interfész módosítása: HTML és CSS manipulációval megváltoztathatod az alkalmazás kinézetét.
-
-### Bővítmény létrehozása
-
-Hozz létre egy mappát a `src/plugins/YOUR-PLUGIN-NAME` útvonalon:
-
-- `index.ts`: a bővítmény fő fájlja
-```typescript
-import style from './style.css?inline'; // import style as inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic show restart dialog
- config: {
- enabled: false,
- }, // your custom config
- stylesheets: [style], // your custom style,
- menu: async ({ getConfig, setConfig }) => {
- // All *Config methods are wrapped Promise
- const config = await getConfig();
- return [
- {
- label: 'menu',
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // you can communicate with renderer plugin
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // it fired when config changed
- onConfigChange(newConfig) { /* ... */ },
- // it fired when plugin disabled
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // Only renderer available hook
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // set plugin config easily
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### Gyakori használati esetek
-
-- Egyedi CSS injektálása: hozz létre egy `style.css` fájlt ugyanabban a mappában, majd:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // import style as inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic will show a restart dialog
- config: {
- enabled: false,
- }, // your custom config
- stylesheets: [style], // your custom style
- renderer() {} // define renderer hook
-});
-```
-
-- Ha módosítani szeretnéd a HTML-t:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic will show the restart dialog
- config: {
- enabled: false,
- }, // your custom config
- renderer() {
- // Remove the login button
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // define renderer hook
-});
-```
-
-- Az elülső és hátsó rész közötti kommunikáció: Az Electron ipcMain moduljának használatával valósítható meg. Lásd az `index.ts` fájlt és a `sponsorblock` bővítmény példáját.
-
-## Build
-
-1. Klónozd a repót
-2. Kövesd ezt az [útmutatót](https://pnpm.io/installation), hogy telepítsd a `pnpm` csomagkezelőt.
-3. Futtasd a következő parancsot `pnpm install --frozen-lockfile` a kellékek telepítéséhez.
-4. Építsd meg az alkalmazást az operációs rendszerednek megfelelő paranccsal: `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (arm64 Debiánhoz)
-- `pnpm dist:linux:rpm-arm64` - Linux (arm64 Fedorához)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-Az alkalmazás építéséhez a [electron-builder](https://github.com/electron-userland/electron-builder) eszközt használáld, amely támogatja a macOS, Linux és Windows platformokat.
-
-## Gyártás előnézete
-
-```bash
-pnpm start
-```
-
-## Tesztelés
-
-```bash
-pnpm test
-```
-
-A [Playwright](https://playwright.dev/) tesztelési keretrendszert használd az alkalmazás teszteléséhez.
-
-## Licenc
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## GYIK
-
-### Miért nem jelenik meg az alkalmazás menüje?
-
-Ha a `menü elrejtése` opció be van kapcsolva, a menüt az alt billentyűvel jelenítheted meg (vagy az ` [fordított idézőjel] billentyűvel, ha az alkalmazáson belüli menü bővítményt használod).
diff --git a/docs/readme/README-is.md b/docs/readme/README-is.md
deleted file mode 100644
index 29f9875f36..0000000000
--- a/docs/readme/README-is.md
+++ /dev/null
@@ -1,390 +0,0 @@
-
-
-# YouTube Tónlist
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Lestu þetta á öðrum tungumálum: [🏴 Enska](../../README.md), [🇰🇷 Kóreska](./README-ko.md), [🇫🇷 Franska](./README-fr.md), [🇮🇸 Íslenska](./README-is.md), [🇪🇸 Spænska](./README-es.md), [🇷🇺 Rússneska](./README-ru.md), [🇺🇦 Úkraínska](./README-uk.md), [🇧🇷 Portúgalska](./README-pt.md), [🇭🇺 Ungverska](./README-hu.md) [🇯🇵 Japanska](./README-ja.md)
-
-**Electron umbúðir utan um YouTube Tónlist sem inniheldur:**
-
-- Innfæddur útlit og tilfinning, miðar að því að halda upprunalegu viðmótinu
-- Rammi fyrir sérsniðnar tengiforrit: breyttu YouTube Tónlist að þínum þörfum (stíl, efni, eiginleikar), virkjaðu/slökktu á viðbætur í
- einn smellur
-
-## Sýnishornsmynd
-
-| Spilaraskjár (albúmslitaþema & umhverfisljós) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Efni
-
-- [Eiginleikar](#eiginleikar)
-- [Tiltæk tengiforrit](#tiltæk-tengiforrit)
-- [Þýðing](#þýðing)
-- [Sækja](#sækja)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Hvernig á að setja upp án nettengingar? (í Windows)](#hvernig-á-að-setja-upp-án-nettengingar-í-windows)
-- [Þemu](#þemu)
-- [Þróun](#þróun)
-- [Búðu til þín eigin viðbætur](#búðu-til-þín-eigin-viðbætur)
- - [Er að búa til viðbót](#er-að-búa-til-viðbót)
- - [Algeng notkunartilvik](#algeng-notkunartilvik)
-- [Byggja](#byggja)
-- [Framleiðsluforskoðun](#framleiðsluforskoðun)
-- [Prófanir](#prófanir)
-- [Leyfi](#leyfi)
-- [Algengustu spurningar](#algengustu-spurningar)
-
-## Eiginleikar:
-
-- **Sjálfvirk staðfesting þegar gert er hlé** (Alltaf virkt): slökkva á
- ["Halda áfram að horfa?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png)
- popup sem gerir hlé á tónlist eftir ákveðinn tíma
-
- - Og meira...
-
-## Tiltæk tengiforrit:
-
-- **Auglýsingablokkari**: Lokaðu fyrir allar auglýsingar og rakningar úr kassanum
-
-- **Albúmsaðgerðir**: Bætir Ódíslika, Mislíkt, Líkt, og Ólíkt til að nota þetta á öll lög á spilunarlista eða albúm
-
-- **Albúmslitaþema**: Beitir kraftmikið þema og sjónrænum áhrifum sem byggjast á litavali albúmsins
-
-- **Umhverfishamur**: Beitir lýsingaráhrifum með því að varpa mildum litum úr myndbandinu í bakgrunn skjásins
-
-- **Hljóðþjöppur**: Notaðu þjöppun á hljóð (lækkar hljóðstyrk háværustu hluta merkis og hækkar hljóðstyrk í mýkstu hlutunum)
-
-- **Þoka Leiðsagnarstika**: Gerir leiðsögustikuna gagnsæja og óskýrt
-
-- **Farið Framhjá Aldurstakmörkunum**: Framhjá aldursstaðfestingu YouTube
-
-- **Yfirskriftarval**: Virkja skjátexta
-
-- **Fyrirferðarlítillhliðarstika**: Stilltu hliðarstikuna alltaf í þétta stillingu
-
-- **Krossfæra**: Krossfæra á milli lög
-
-- **Slökkva á Sjálfvirkri Spilun**: Gerir lag að byrja í "hlé" ham
-
-- **[Discord](https://discord.com/) Rík Nærveru**: Sýndu vinum þínum hvað þú hlustar á
- með [Rík Nærveru](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Niðurhalari**: Niðurhalum
-MP3 [beint úr viðmótinu](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Veldibundiðrúmmál**: Gerir hljóðstyrkssleðann [veldisvísis](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/)
- svo það er auðveldara að velja lægra hljóðstyrk.
-
-- **Valmynd í Forriti**: [Gefur börum flott, dökkt útlit](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (sjá [þessa færslu](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) ef þú átt í vandræðum
- með að fá aðgang að valmyndinni eftir að hafa virkjað þessa viðbót og fela valmyndarvalkostinn)
-
-- **Scrobbler**: Bætir við scrobbling stuðningi fyrir [Last.fm](https://www.last.fm/) og [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream**: Bætir við [Lumia Stream](https://lumiastream.com/) stuðningi
-
-- **Söngtexti Snilld**: Bætir stuðningi við texta fyrir flest lög
-
-- **Tónlist Saman**: Deila spilunarlista með öðrum. Þegar gestgjafinn spilar lag munu allir aðrir heyra sama lagið
-
-- **Leiðsögn**: Næsta/Til baka leiðsagnarörvar beint samþættar í viðmótinu, eins og í uppáhalds vafranum þínum
-
-- **Engin Google Innskráning**: Fjarlægðu Google innskráningarhnappa og tengla úr viðmótinu
-
-- **Tilkynningar**: Birta tilkynningu þegar lag byrjar að spila
- ([gagnvirkartilkynningar](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) eru fáanlegar á Windows)
-
-- **Mynd-í-Mynd**: Gerir kleift að skipta forritinu yfir í mynd-í-mynd stillingu
-
-- **Spilunarhraði**: Hlustaðu hratt, hlustaðu hægt!
- [Bætir við sleða sem stjórnar lagahraðanum](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Nákvæmshljóðstyrkur**: Stjórnaðu hljóðstyrknum nákvæmlega með músarhjóli/hraðtökkum, með sérsniðnum HUD og sérsniðnum hljóðstyrksþrepum
-
-- **Flýtileiðir (og MPRIS)**: Leyfir að stilla alþjóðlegarflýtilyklar fyrir spilun (spila/gera hlé/næsta/fyrri) +
- óvirkja [media osd](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png)
- með því að hnekkja miðlunarlyklum + virkja Ctrl/CMD + F til að leita + virkja linux mpris stuðning fyrir
- miðlunarlyklar + [sérsniðnir flýtilyklar](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50)
- fyrir [háþróaða notendur](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-- **Slepptu Lögum sem Mislíkuðust**: Sleppir mislíkaði lög
-
-- **Slepptu Þögnum**: Slepptu sjálfkrafa þagnarköflum í lögum
-
-- [**Styrktarblokk**](https://github.com/ajayyy/SponsorBlock): Sleppur sjálfkrafa hlutum sem ekki eru tónlist, eins og inngangur/lok
- eða hlutar af tónlistarmyndböndum þar sem lag er ekki að spila
-
-- **Miðlunarstýringarverkefnastikunnar**: Stjórnaðu spilun frá [Windows verkefnastikunni þinni](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **Snertistiku**: Sérsniðið Snertistikuútlit fyrir macOS
-
-- **Tuna OBS**: Samþætting við [OBS](https://obsproject.com/)
- viðbótina [Tuna](https://obsproject.com/forum/resources/tuna.843/)
-
-- **Myndbandgæðisbreyting**: Leyfir að breyta myndbandgæðum með
- [hnappi](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) á
- myndbandsyfirlaginu
-
-- **Myndbandsrofi**: Bætir við [hnappi](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) til
- að skipta á milli myndbands/lagshams. Getur einnig valfrjálst fjarlægt allan myndbandsflipann
-
-- **Sjónrænir**: Mismunandi tónlist sjónrænir
-
-## Þýðing
-
-Þú getur aðstoðað við þýðingar á [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Sækja
-
-Þú getur skoðað [nýjustu útgáfuna](https://github.com/th-ch/youtube-music/releases/latest) til að finna fljótt
-nýjustu útgáfuna.
-
-### Arch Linux
-
-Settu upp [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) pakkann frá AUR. Fyrir AUR uppsetningarleiðbeiningar skaltu skoða
-þessa [wiki síðu](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### MacOS
-
-Þú getur sett upp appið með því að nota Homebrew (sjá [cask skilgreiningu](https://github.com/th-ch/homebrew-youtube-music))
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Ef þú setur upp forritið handvirkt og færð villu "er skemmd og ekki er hægt að opna það," þegar þú ræsir forritið skaltu keyra eftirfarandi í flugstöðinni:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Þú getur notað [Scoop pakkastjórnun](https://scoop.sh) til að setja upp `youtube-music` pakkann frá
-[`extras` fötunni](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Að öðrum kosti geturðu notað [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), Windows 11s
-opinber CLI pakkastjóri til að setja upp `th-ch.YouTubeMusic` pakkann.
-
-*Athugið: Microsoft Defender SmartScreen gæti lokað uppsetningunni þar sem hún er frá „óþekktum útgefanda“. Þetta er einnig
-satt fyrir handvirka uppsetningu þegar reynt er að keyra executable(.exe) eftir handvirkt niðurhal hér á github (sama
-skrá).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Hvernig á að setja upp án nettengingar? (í Windows)
-
-- Sæktu `*.nsis.7z` skrána fyrir _arkitektúr tækisins þíns_ á [útgáfusíðu](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` fyrir 64-bita Windows
- - `ia32` fyrir 32-bita Windows
- - `arm64` fyrir ARM64 Windows
-- Sæktu uppsetningarforrit á útgáfusíðu. (`*-Setup.exe`)
-- Settu þær í **sömu möppuna**.
-- Keyrðu uppsetningarforritið.
-
-## Þemu
-
-Þú getur hlaðið CSS skrám til að breyta útliti forritsins (Valkostir > Sjónræn klip > Þemu).
-
-Sum fyrirframskilgreind þemu eru fáanleg á https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Þróun
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Búðu til þín eigin tengiforrit
-
-Með því að nota tengiforrit geturðu:
-
-- vinna með appið - `BrowserWindow` frá electron er sent til tengiforritsstjórans
-- breyttu framhliðinni með því að vinna með HTML/CSS
-
-### Er að búa til tengiforrit
-
-Búðu til möppu í `src/plugins/YOUR-PLUGIN-NAME`:
-
-- `index.ts`: aðal skránni af tengiforritið
-```typescript
-import style from './style.css?inline'; // flytja inn stíl sem inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // ef gildi er satt, ytmusic sjá endurræsa gluggann
- config: {
- enabled: false,
- }, // sérsniðnastillingar þinn
- stylesheets: [style], // sérsniðnastílinn þinn
- menu: async ({ getConfig, setConfig }) => {
- // Allar *stillingaraðferðir eru umvafnar Lofor
- const config = await getConfig();
- return [
- {
- label: 'menu',
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // þú getur tengst við renderer tengiforritið
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // það kviknaði þegar stillingum var breytt
- onConfigChange(newConfig) { /* ... */ },
- // it fired when plugin disabled
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // Aðeins krókur sem er í boði fyrir renderer
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // stilltu stillingar viðbótarinnar auðveldlega
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### Algeng notkunartilvik
-
-- er að sprauta sérsniðnum CSS: búðu til `style.css` skrá í sömu möppu þá:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // flytja inn stíl sem inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // ef gildi er satt, ytmusic sjá endurræsa gluggann
- config: {
- enabled: false,
- }, // sérsniðnastillingar þinn
- stylesheets: [style], // sérsniðnastílinn þinn
- renderer() {} // skilgreina renderer krók
-});
-```
-
-- Ef þú vilt breyta HTML:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // ef gildi er satt, ytmusic sjá endurræsa gluggann
- config: {
- enabled: false,
- }, // sérsniðnastillingar þinn
- renderer() {
- // Fjarlægðu innskráningarhnappinn
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // skilgreina renderer krók
-});
-```
-
-- samskipti á milli að framan og aftan: hægt að gera með því að nota ipcMain eininguna frá electron. Sjá `index.ts` skrá og
- dæmi í 'styrktarblokk' tengiforritinu.
-
-## Byggja
-
-1. Klóna geymsluna
-2. Fylgdu [þessa handbók](https://pnpm.io/installation) til að setja upp 'pnpm'
-3. Keyrðu `pnpm install --frozen-lockfile` til að setja upp ósjálfstæði
-4. Keyrðu `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux
-- `pnpm dist:mac` - MacOS
-
-Byggir appið fyrir macOS, Linux og Windows,
-með því að nota [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Framleiðsluforskoðun
-
-```bash
-pnpm start
-```
-
-## Prófanir
-
-```bash
-pnpm test
-```
-
-Notar [Playwright](https://playwright.dev/) til að prófa forritið.
-
-## Leyfi
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## Algengustu Spurningar
-
-### Hvers vegna forritavalmynd birtist ekki?
-
-Ef valmöguleikinn „Fela valmynd“ er á - þú getur sýnt valmyndina með alt lyklinum (eða \` [bakka]
-ef þú notar viðbótina fyrir valmynd í forriti)
diff --git a/docs/readme/README-ja.md b/docs/readme/README-ja.md
deleted file mode 100644
index 2e326715c4..0000000000
--- a/docs/readme/README-ja.md
+++ /dev/null
@@ -1,371 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-他の言語で読む: [🏴 英語](../../README.md), [🇰🇷 韓国語](./README-ko.md), [🇫🇷 フランス語](./README-fr.md), [🇮🇸 アイスランド語](./README-is.md), [🇪🇸 スペイン語](./README-es.md), [🇷🇺 ロシア語](./README-ru.md), [🇺🇦 ウクライナ語](./README-uk.md)
-
-**YouTube MusicのElectronラッパーには以下の機能があります:**
-
-- ネイティブの外観と操作感、元のインターフェースを維持することを目指しています
-- カスタムプラグインのフレームワーク: スタイル、コンテンツ、機能など、YouTube Musicをニーズに合わせて変更し、ワンクリックでプラグインを有効/無効にできます
-
-## デモ画像
-
-| プレーヤースクリーン (アルバムカラーテーマ & アンビエントライト) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## コンテンツ
-
-- [機能](#機能)
-- [利用可能なプラグイン](#利用可能なプラグイン)
-- [翻訳](#翻訳)
-- [ダウンロード](#ダウンロード)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [ネットワーク接続なしでインストールする方法 (Windows)](#ネットワーク接続なしでインストールする方法-windows)
-- [テーマ](#テーマ)
-- [開発](#開発)
-- [独自のプラグインを作成する](#独自のプラグインを作成する)
- - [プラグインの作成](#プラグインの作成)
- - [一般的な使用例](#一般的な使用例)
-- [ビルド](#ビルド)
-- [プロダクションプレビュー](#プロダクションプレビュー)
-- [テスト](#テスト)
-- [ライセンス](#ライセンス)
-- [FAQ](#faq)
-
-## 機能:
-
-- **一時停止時の自動確認** (常に有効): 一定時間後に音楽を一時停止する["視聴を続けますか?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png)ポップアップを無効にします
-
- - その他の機能...
-
-## 利用可能なプラグイン:
-
-- **広告ブロッカー**: すべての広告とトラッキングをブロックします
-
-- **アルバムアクション**: プレイリストやアルバム内のすべての曲に「嫌いではない」「嫌い」「好き」「好きではない」ボタンを追加します
-
-- **アルバムカラーテーマ**: アルバムのカラーパレットに基づいて動的なテーマと視覚効果を適用します
-
-- **アンビエントモード**: 動画から柔らかい色を画面の背景に投影するライティング効果を適用します
-
-- **���ーディオコンプレッサー**: オーディオにコンプレッションを適用します(信号の最も大きな部分の音量を下げ、最も小さな部分の音量を上げます)
-
-- **ナビゲーションバーのぼかし**: ナビゲーションバーを透明でぼやけたものにします
-
-- **年齢制限の回避**: YouTubeの年齢確認を回避します
-
-- **字幕選択**: 字幕を有効にします
-
-- **コンパクトサイドバー**: サイドバーを常にコンパクトモードに設定します
-
-- **クロスフェード**: 曲間にクロスフェードを適用します
-
-- **自動再生の無効化**: すべての曲を「一時停止」モードで開始します
-
-- **[Discord](https://discord.com/) リッチプレゼンス**: [リッチプレゼンス](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)を使用して、友達にあなたが聴いている曲を表示します
-
-- **ダウンローダー**: UIから直接MP3/ソースオーディオをダウンロードします
-
-- **イコライザー**: 特定の周波数範囲をブーストまたはカットするフィルターを追加します(例: ベースブースター)
-
-- **指数音量**: 音量スライダーを[指数関数的](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/)にして、低い音量を選択しやすくします
-
-- **アプリ内メニュー**: [メニューバーをおしゃれで暗い外観にします](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (このプラグインとメニュー非表示オプションを有効にした後、メニューにアクセスする際に問題がある場合は、[この投稿](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709)を参照してください)
-
-- **スクロブラー**: [Last.fm](https://www.last.fm/)や[ListenBrainz](https://listenbrainz.org/)のスクロブリングサポートを追加します
-
-- **Lumia Stream**: [Lumia Stream](https://lumiastream.com/)のサポートを追加します
-
-- **Genius 歌詞**: ほとんどの曲に歌詞サポートを追加します
-
-- **Music Together**: プレイリストを他の人と共有します。ホストが曲を再生すると、他の全員が同じ曲を聴くことができます
-
-- **ナビゲーション**: お気に入りのブラウザのように、UIに直接統合された次/前のナビゲーション矢印を追加します
-
-- **Googleログインなし**: インターフェースからGoogleログインボタンとリンクを削除します
-
-- **通知**: 曲の再生が開始されると通知を表示します(Windowsでは[インタラクティブ通知](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png)が利用可能です)
-
-- **ピクチャーインピクチャー**: アプリをピクチャーインピクチャーモードに切り替えることができます
-
-- **再生速度**: 速く聴いたり、遅く聴いたりできます!曲の速度を制御するスライダーを追加します
-
-- **正確な音量**: カスタムHUDとカスタマイズ可能な音量ステップを使用して、マウスホイール/ホットキーで音量を正確に制御します
-
-- **ショートカット (& MPRIS)**: 再生用のグローバルホットキー(再生/一時停止/次/前)を設定し、メディアキーをオーバーライドしてメディアOSDを無効にし、Ctrl/CMD + Fで検索を有効にし、LinuxのMPRISサポートを有効にし、[上級ユーザー](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)向けの[カスタムホットキー](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50)を追加します
-
-- **嫌いな曲をスキップ**: 嫌いな曲をスキップします
-
-- **無音部分をスキップ**: 無音部分を自動的にスキップします
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): イントロ/アウトロなどの音楽以外の部分や、曲が再生されていないミュージックビデオの部分を自動的にスキップします
-
-- **同期歌詞**: [LRClib](https://lrclib.net)のようなプロバイダーを使用して、曲に同期した歌詞を提供します
-
-- **タスクバーメディアコントロール**: [Windowsタスクバー](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)から再生を制御します
-
-- **TouchBar**: macOS用のカスタムTouchBarレイアウト
-
-- **Tuna OBS**: [OBS](https://obsproject.com/)のプラグイン[Tuna](https://obsproject.com/forum/resources/tuna.843/)との統合
-
-- **ビデオ品質チェンジャー**: ビデオオーバーレイの[ボタン](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png)を使用してビデオ品質を変更できます
-
-- **ビデオ切り替え**: ビデオ/ソングモードを切り替える[ボタン](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png)を追加します。オプションでビデオタブ全体を削除することもできます
-
-- **ビジュアライザー**: プレイヤーにさまざまな音楽ビジュアライザーを追加します
-
-## 翻訳
-
-[Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/)で翻訳を手伝うことができます。
-
-
-
-
-
-
-## ダウンロード
-
-[最新リリース](https://github.com/th-ch/youtube-music/releases/latest)を確認して、最新バージョンをすばやく見つけることができます。
-
-### Arch Linux
-
-AURから[`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin)パッケージをインストールします。AURのインストール手順については、この[wikiページ](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages)を参照してください。
-
-### macOS
-
-Homebrewを使用してアプリをインストールできます([cask定義](https://github.com/th-ch/homebrew-youtube-music)を参照)。
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-アプリを手動でインストールし、アプリの起動時に「破損しているため開けません」というエラーが表示される場合は、ターミナルで次のコマンドを実行します。
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-[Scoopパッケージマネージャー](https://scoop.sh)を使用して、[`extras`バケット](https://github.com/ScoopInstaller/Extras)から`youtube-music`パッケージをインストールできます。
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-または、Windows 11の公式CLIパッケージマネージャーである[Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/)を使用して、`th-ch.YouTubeMusic`パッケージをインストールできます。
-
-*注: 「不明な発行元」からのものであるため、Microsoft Defender SmartScreenがインストールをブロックする場合があります。これは、GitHubで手動でダウンロードした後に実行ファイル(.exe)を実行しようとする場合にも当てはまります。*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### ネットワーク接続なしでインストールする方法 (Windows)
-
-- [リリースページ](https://github.com/th-ch/youtube-music/releases/latest)で_デバイスのアーキテクチャ_に対応する`*.nsis.7z`ファイルをダウンロードします。
- - `x64`は64ビットWindows用
- - `ia32`は32ビットWindows用
- - `arm64`はARM64 Windows用
-- リリースページでインストーラーをダウンロードします。(`*-Setup.exe`)
-- それらを**同じディレクトリ**に配置します。
-- インストーラーを実行します。
-
-## テーマ
-
-CSSファイルを読み込んでアプリケーションの外観を変更できます(オプション > 視覚的調整 > テーマ)。
-
-いくつかの事前定義されたテーマは、https://github.com/kerichdev/themes-for-ytmdesktop-player で利用できます。
-
-## 開発
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## 独自のプラグインを作成する
-
-プラグインを使用すると、次のことができます。
-
-- アプリを操作する - Electronの`BrowserWindow`がプラグインハンドラーに渡されます
-- HTML/CSSを操作してフロントエンドを変更する
-
-### プラグインの作成
-
-`src/plugins/YOUR-PLUGIN-NAME`にフォルダーを作成します。
-
-- `index.ts`: プラグインのメインファイル
-```typescript
-import style from './style.css?inline'; // スタイルをインラインとしてインポート
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'プラグインラベル',
- restartNeeded: true, // 値がtrueの場合、ytmusicは再起動ダイアログを表示します
- config: {
- enabled: false,
- }, // カスタム設定
- stylesheets: [style], // カスタムスタイル
- menu: async ({ getConfig, setConfig }) => {
- // すべての*ConfigメソッドはPromiseでラップされています
- const config = await getConfig();
- return [
- {
- label: 'メニュー',
- submenu: [1, 2, 3].map((value) => ({
- label: `値 ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // レンダラープラグインと通信できます
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // 設定が変更されたときに発生します
- onConfigChange(newConfig) { /* ... */ },
- // プラグインが無効になったときに発生します
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // レンダラーでのみ使用可能なフック
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // プラグイン設定を簡単に設定
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### 一般的な使用例
-
-- カスタムCSSの挿入: 同じフォルダーに`style.css`ファイルを作成し、次のようにします。
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // スタイルをインラインとしてインポート
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'プラグインラベル',
- restartNeeded: true, // 値がtrueの場合、ytmusicは再起動ダイアログを表示します
- config: {
- enabled: false,
- }, // カスタム設定
- stylesheets: [style], // カスタムスタイル
- renderer() {} // レンダラーフックを定義
-});
-```
-
-- HTMLを変更したい場合:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'プラグインラベル',
- restartNeeded: true, // 値がtrueの場合、ytmusicは再起動ダイアログを表示します
- config: {
- enabled: false,
- }, // カスタム設定
- renderer() {
- // ログインボタンを削除
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // レンダラーフックを定義
-});
-```
-
-- フロントエンドとバックエンドの通信: ElectronのipcMainモジュールを使用して行うことができます。`index.ts`ファイルと`sponsorblock`プラグインの例を参照してください。
-
-## ビルド
-
-1. リポジトリをクローン
-2. [このガイド](https://pnpm.io/installation)に従って`pnpm`をインストール
-3. `pnpm install --frozen-lockfile`を実行して依存関係をインストール
-4. `pnpm build:OS`を実行
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (Debian用arm64)
-- `pnpm dist:linux:rpm-arm64` - Linux (Fedora用arm64)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-[electron-builder](https://github.com/electron-userland/electron-builder)を使用して、macOS、Linux、およびWindows用のアプリをビルドします。
-
-## プロダクションプレビュー
-
-```bash
-pnpm start
-```
-
-## テスト
-
-```bash
-pnpm test
-```
-
-[Playwright](https://playwright.dev/)を使用してアプリをテストします。
-
-## ライセンス
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## FAQ
-
-### アプリのメニューが表示されないのはなぜですか?
-
-`メニューを非表示`オプションがオンの場合 - alt キー(またはアプリ内メニュープラグインを使用している場合は\` [バックティック]キー)でメニューを表示できます
diff --git a/docs/readme/README-ko.md b/docs/readme/README-ko.md
deleted file mode 100644
index dc3d4c30a6..0000000000
--- a/docs/readme/README-ko.md
+++ /dev/null
@@ -1,350 +0,0 @@
-
-
-# 유튜브 뮤직 (YouTube Music)
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-다른 언어로 읽어보세요: [🏴 영어](../../README.md), [🇰🇷 한국인](./README-ko.md), [🇫🇷 프랑스 국민](./README-fr.md), [🇮🇸 아이슬란드어](./README-is.md), [🇪🇸 스페인 사람](./README-es.md), [🇷🇺 러시아인](./README-ru.md), [🇺🇦 우크라이나어](./README-uk.md), [🇧🇷 포르투갈어](./README-pt.md), [🇯🇵 일본어](./README-ja.md)
-
-**유튜브 뮤직의 Electron 래퍼; 기능:**
-
-- 원래의 인터페이스를 유지하는 것을 목표로 하는 네이티브 디자인 및 느낌
-- 맞춤 플러그인을 위한 프레임워크: 스타일, 콘텐츠, 기능 등 필요에 따라 유튜브 뮤직을 변경하고, 클릭 한 번으로 플러그인을 활성화/비활성화할 수 있습니다.
-
-## Content
-
-- [기능](#기능)
-- [사용 가능한 플러그인](#사용-가능한-플러그인)
-- [번역](#번역)
-- [다운로드](#다운로드)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [(Windows에서) 네트워크에 연결하지 않고 설치하는 방법은 무엇인가요?](#windows에서-네트워크에-연결하지-않고-설치하는-방법은-무엇인가요)
-- [테마](#테마)
-- [개발](#개발)
-- [나만의 플러그인 만들기](#나만의-플러그인-만들기)
- - [플러그인 만들기](#플러그인-만들기)
- - [일반적인 사용 예](#일반적인-사용-예)
-- [빌드](#빌드)
-- [프로덕션 빌드 미리보기](#프로덕션-빌드-미리보기)
-- [테스트](#테스트)
-- [라이선스](#라이선스)
-- [자주 묻는 질문](#자주-묻는-질문)
-
-## 기능:
-
-- **일시 정지 시 자동 확인** (항상 활성화 됨): 일정 시간이 지나면 음악을 일시 정지하는 ["계속 시청하시겠습니까?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png) 팝업을 비활성화합니다.
-
-- 이외에 더 많은 기능 ...
-
-## 사용 가능한 플러그인:
-
-- **애드블록**: 모든 광고와 트래커를 즉시 차단합니다
-
-- **앨범 컬러 기반 테마**: 앨범 색상 팔레트를 기반으로 동적 테마 및 시각 효과를 적용합니다
-
-- **앰비언트 모드**: 영상의 간접 조명을 화면 배경에 투사합니다.
-
-- **오디오 컴프레서**: 오디오에 컴프레서를 적용합니다 (신호에서 가장 시끄러운 부분의 음량을 낮추고 가장 조용한 부분의 음량을 높임)
-
-- **네비게이션 바 흐림 효과**: 내비게이션 바를 투명하고 흐릿하게 만듭니다
-
-- **나이 제한 우회**: 유튜브의 나이 제한을 우회합니다
-
-- **자막 선택기**: 자막을 활성화합니다
-
-- **컴팩트 사이드바**: 사이드바를 항상 컴팩트 모드로 설정합니다
-
-- **크로스페이드**: 노래 사이에 크로스페이드 효과를 적용합니다
-
-- **자동 재생 해제**: 노래를 '일시 정지' 모드로 시작하게 합니다
-
-- [**디스코드 활동 상태**](https://discord.com/): [활동 상태 (Rich Presence)](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)를 사용하여 친구들에게 내가 듣는 음악을 보여주세요
-
-- **다운로더**: UI에서 [직접](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) MP3/소스 오디오를 다운로드하세요
-
-- **지수 볼륨**: 음량 슬라이더를 [지수적](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/)으로 만들어 더 낮은 음량을 쉽게 선택할 수 있도록 합니다.
-
-- **인앱 메뉴**: [메뉴 표시줄을 더 멋지게, 그리고 다크 또는 앨범의 색상으로 만듭니다](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (이 플러그인 및 메뉴 숨기기 옵션을 활성화한 후 메뉴에 액세스하는 데 문제가 있는 경우 [이 글](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709)을 참조하세요)
-
-- [**Last.fm**](https://www.last.fm/): Last.fm에 대한 스크러블 지원을 추가합니다
-
-- **Lumia Stream**: [Lumia Stream](https://lumiastream.com/) 지원을 추가합니다
-
-- **Genius 가사**: 더 많은 곡에 대해 가사 지원을 추가합니다
-
-- **네비게이션**: 브라우저에서처럼, UI에 직접 통합된 앞으로/뒤로 탐색하는 화살표를 추가합니다
-
-- **Google 로그인 제거**: UI에서 Google 로그인 버튼 및 링크 제거하기
-
-- **알림**: 노래 재생이 시작되면 알림을 표시 (Windows에서는 [대화형 알림](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) 사용 가능)
-
-- **PiP**: 앱을 PiP 모드로 전환할 수 있게 허용합니다
-
-- **재생 속도**: 빨리 듣거나, 천천히 들어보세요! [노래 속도를 제어하는 슬라이더를 추가합니다](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **정확한 음량**: 사용자 지정 HUD와 사용자 지정 음량 단계 및 마우스 휠/단축키를 사용하여 음량을 정확하게 제어하세요
-
-- **영상 품질 체인저**: 영상 오버레이의 [버튼](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png)으로 영상 품질을 변경할 수 있게 합니다
-
-- **단축키 (& MPRIS)**: 재생을 위한 전역 단축키 설정 허용 (재생/일시 정지/다음/이전) + 미디어 키를 재정의하여 [미디어 osd](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png) 비활성화 + Ctrl/CMD + F 검색 활성화 + 미디어 키에 대한 리눅스 MPRIS 지원 활성화 + [고급 사용자](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)를 위한 [사용자 지정 단축키](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) 지원
-
-- **무음 건너뛰기** - 노래의 무음 부분을 자동으로 건너뜁니다
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): 인트로/아웃트로와 같은 음악이 아닌 부분이나, 노래가 재생되지 않는 뮤직 비디오의 일부를 자동으로 건너뜁니다
-
-- **작업표시줄 미디어 컨트롤**: [Windows 작업표시줄](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)에서 재생을 제어하세요
-
-- **TouchBar**: macOS 사용자를 위한 TouchBar 위젯을 추가합니다
-
-- **Tuna-OBS**: [OBS](https://obsproject.com/)의 플러그인, [Tuna](https://obsproject.com/forum/resources/tuna.843/)와 통합을 활성화합니다
-
-- **영상 전환**: 영상/노래 모드를 전환하는 [버튼](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png)을 추가합니다. 선택적으로 전체 영상 탭을 제거할 수도 있습니다
-
-- **비주얼라이저**: 플레이어에 시각화 도구 추가
-
-## 번역
-
-[Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/)에서 번역을 도울 수 있습니다.
-
-
-
-
-
-
-## 다운로드
-
-[최신 릴리즈](https://github.com/th-ch/youtube-music/releases/latest)를 확인하여 최신 버전을 빠르게 찾을 수 있습니다.
-
-### Arch Linux
-
-AUR에서 [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) 패키지를 설치합니다. AUR 설치 지침은 [이 위키 페이지](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages)를 참조하세요.
-
-### MacOS
-
-Homebrew를 사용하여 앱을 설치할 수 있습니다:
-```bash
-brew install --cask https://raw.githubusercontent.com/th-ch/youtube-music/master/youtube-music.rb
-```
-
-(앱을 수동으로 설치하고) 앱을 실행할 때 `손상되었기 때문에 열 수 없습니다.`라는 오류가 발생하면 터미널에서 다음을 실행하세요:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-[Scoop 패키지 매니저](https://scoop.sh)를 사용하여 [`extras` 버킷](https://github.com/ScoopInstaller/Extras)에서 `youtube-music` 패키지를 설치할 수 있습니다.
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-또는 Windows 11의 공식 CLI 패키지 관리자인 [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/)을 사용하여 `th-ch.YouTubeMusic` 패키지를 설치할 수 있습니다.
-
-*참고: "알 수 없는 게시자"의 파일이기 때문에 Microsoft Defender의 SmartScreen에서 설치를 차단할 수 있습니다. 이는 GitHub에서 동일 파일을 수동으로 다운로드한 후 실행 파일(.exe)을 실행하려고 할 때도 마찬가지로 발생합니다.*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### (Windows에서) 네트워크에 연결하지 않고 설치하는 방법은 무엇인가요?
-
-- [릴리즈 페이지](https://github.com/th-ch/youtube-music/releases/latest)에서 _본인 기기 아키텍처_에 맞는 `*.nsis.7z` 파일을 다운로드하세요.
- - `x64`는 64비트 Windows 용입니다.
- - `ia32`는 32비트 Windows 용입니다.
- - `arm64`는 ARM64 Windows 용입니다.
-- 릴리즈 페이지에서 설치기를 다운로드하세요. (`*-Setup.exe`)
-- 두 파일을 **동일한 위치**에 놓아주세요.
-- 설치기를 실행하세요.
-
-## 테마
-
-CSS 파일을 로드하여 애플리케이션의 모양을 변경할 수 있습니다(설정 > 시각적 변경 > 테마).
-
-일부 사전 정의 테마는 https://github.com/kerichdev/themes-for-ytmdesktop-player 에서 사용할 수 있습니다.
-
-## 개발
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## 나만의 플러그인 만들기
-
-플러그인을 사용하면 할 수 있는 것들:
-
-- 앱 조작 - Electron에서 `BrowserWindow`가 플러그인 핸들러로 전달
-- HTML/CSS를 조작하여 프론트엔드를 변경
-
-### 플러그인 만들기
-
-`plugins/나만의-플러그인-이름`에 폴더를 만듭니다:
-
-- `index.ts`: 플러그인의 메인 파일입니다.
-```typescript
-import style from './style.css?inline'; // 스타일을 인라인으로 가져옵니다
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // 값이 true면, YTM은 재시작 다이얼로그를 표시합니다
- config: {
- enabled: false,
- }, // 나의 커스텀 config
- stylesheets: [style], // 나의 스타일
- menu: async ({ getConfig, setConfig }) => {
- // 모든 *Config 메서드는 Promise로 래핑됩니다
- const config = await getConfig();
- return [
- {
- label: 'menu',
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // 이를 사용하여 렌더러 플러그인과 통신할 수 있습니다
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // config가 변경되면 실행됩니다
- onConfigChange(newConfig) { /* ... */ },
- // 플러그인이 비활성화되면 실행됩니다
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // 렌더러에서만 사용 가능한 훅입니다
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // 플러그인의 config를 간단하게 설정할 수 있습니다
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### 일반적인 사용 예
-
-- 사용자 정의 CSS 삽입: 같은 폴더에 `style.css` 파일을 생성합니다:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // 스타일을 인라인으로 가져옵니다
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // 값이 true면, YTM은 재시작 다이얼로그를 표시합니다
- config: {
- enabled: false,
- }, // 나의 커스텀 config
- stylesheets: [style], // 나의 커스텀 스타일
- renderer() {} // 렌더러 훅 정의
-});
-```
-
-- HTML을 변경하려는 경우:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // 값이 true면, YTM은 재시작 다이얼로그를 표시합니다
- config: {
- enabled: false,
- }, // 나의 커스텀 config
- renderer() {
- // 로그인 버튼을 제거합니다
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // 렌더러 훅 정의
-});
-```
-
-- 프론트엔드와 백엔드 간의 통신: Electron의 `ipcMain` 모듈을 사용하여 수행할 수 있습니다. `SponsorBlock` 플러그인의 `index.ts` 파일과 예제를 참조하세요.
-
-## 빌드
-
-1. 레포지토리를 복제 (clone) 합니다
-2. [이 가이드](https://pnpm.io/installation)에 따라 `pnpm`을 설치합니다.
-3. `pnpm install --frozen-lockfile`을 실행하여 종속성을 설치합니다.
-4. `pnpm build:OS`을 실행합니다.
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux
-- `pnpm dist:mac` - MacOS
-
-[electron-builder](https://github.com/electron-userland/electron-builder)를 사용하여 macOS, Linux 및 Windows용 앱을 빌드합니다.
-
-## 프로덕션 빌드 미리보기
-
-```bash
-pnpm start
-```
-
-## 테스트
-
-```bash
-pnpm test
-```
-
-[Playwright](https://playwright.dev/)를 사용하여 앱을 테스트합니다.
-
-## 라이선스
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## 자주 묻는 질문
-
-### 앱 메뉴가 표시되지 않는 이유는 무엇인가요?
-
-`메뉴 숨기기` 옵션이 켜져 있는 경우 - alt 키(또는 인앱 메뉴 플러그인을 사용하는 경우 \` [백틱] 키)로 메뉴를 표시할 수 있습니다.
diff --git a/docs/readme/README-pt.md b/docs/readme/README-pt.md
deleted file mode 100644
index 0728ccffa8..0000000000
--- a/docs/readme/README-pt.md
+++ /dev/null
@@ -1,375 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Leia em outros idiomas: [🏴 Inglês](../../README.md), [🇰🇷 Coreano](./README-ko.md), [🇫🇷 Francês](./README-fr.md), [🇮🇸 Islandês](./README-is.md), [🇪🇸 Espanhol](./README-es.md), [🇷🇺 Russo](./README-ru.md), [🇺🇦 Ucraniano](./README-uk.md), [🇧🇷 Português](./README-pt.md)
-
-**Wrapper do Electron para o YouTube Music com os seguintes recursos:**
-
-- Visual e comportamento nativos: Mantém a interface original do YouTube Music.
-- Estrutura para plugins personalizados: Adapte o YouTube Music às suas necessidades (estilo, conteúdo, funcionalidades). Ative/desative plugins com um clique.
-
-## Imagem de demonstração
-
-| Tela do Player (tema de cores do álbum e luz ambiente) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Conteúdo
-
-- [Recursos](#recursos)
-- [Plugins disponíveis](#plugins-disponíveis)
-- [Tradução](#tradução)
-- [Download](#download)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Como instalar sem conexão à internet? (no Windows)](#como-instalar-sem-conexão-à-internet-no-windows)
-- [Temas](#temas)
-- [Dev](#dev)
-- [Crie seus próprios plugins](#crie-seus-próprios-plugins)
- - [Criando um plugin](#criando-um-plugin)
- - [Casos de uso comuns](#casos-de-uso-comuns)
-- [Compilar](#compilar)
-- [Prévia de produção](#prévia-de-produção)
-- [Testes](#testes)
-- [Licença](#licença)
-- [Perguntas Frequentes](#perguntas-frequentes)
-
-## Recursos:
-
-- **Confirmação automática quando pausado** (Sempre ativado): desativa
- o popup ["Continuar assistindo?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png)
- que pausa a música após um certo tempo
-
-- E mais...
-
-## Plugins disponíveis:
-
-- **Bloqueador de anúncios**: Bloqueia todos os anúncios e rastreamentos automaticamente
-
-- **Ações de Álbum**: Adiciona botões para Remover dislike, Dar dislike, Curtir e Remover curtida em todas as músicas de uma playlist ou álbum
-
-- **Tema de cores do álbum**: Aplica um tema dinâmico e efeitos visuais baseados na paleta de cores do álbum
-
-- **Modo ambiente**: Cria um efeito de iluminação projetando cores suaves do vídeo no fundo da tela
-
-- **Compressor de áudio**: Aplica compressão ao áudio (reduz o volume das partes mais altas e aumenta o das mais baixas)
-
-- **Barra de navegação desfocada**: Torna a barra de navegação transparente e desfocada
-
-- **Contornar restrições de idade**: Ignora a verificação de idade do YouTube
-
-- **Seletor de legendas**: Ativa legendas
-
-- **Barra lateral compacta**: Mantém a barra lateral sempre no modo compacto
-
-- **Crossfade**: Transição suave entre músicas
-
-- **Desativar reprodução automática**: Faz com que todas as músicas iniciem no modo "pausado"
-
-- **[Discord](https://discord.com/) Rich Presence**: Mostra para seus amigos o que você está ouvindo com [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Downloader**: Baixa MP3 [diretamente da interface](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Equalizador**: Adiciona filtros para aumentar ou reduzir faixas específicas de frequência (ex: reforço de graves)
-
-- **Volume exponencial**: Torna o controle de volume [exponencial](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) para facilitar a seleção de volumes mais baixos
-
-- **Menu integrado**: [Dá às barras um visual elegante e escuro](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (veja [este post](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) se tiver problemas para acessar o menu após ativar este plugin e a opção de ocultar menu)
-
-- **Scrobbler**: Adiciona suporte para scrobbling no [Last.fm](https://www.last.fm/) e [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream**: Adiciona suporte para [Lumia Stream](https://lumiastream.com/)
-
-- **Letras Genius**: Adiciona suporte a letras para a maioria das músicas
-
-- **Música Juntos**: Compartilhe uma playlist com outros. Quando o host toca uma música, todos ouvem a mesma música
-
-- **Navegação**: Botões de avançar/voltar integrados diretamente na interface, como no seu navegador favorito
-
-- **Sem login do Google**: Remove botões e links de login do Google da interface
-
-- **Notificações**: Exibe uma notificação quando uma música começa a tocar ([notificações interativas](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) disponíveis no Windows)
-
-- **Picture-in-picture**: Permite alternar o aplicativo para o modo picture-in-picture
-
-- **Velocidade de reprodução**: Ouça rápido, ouça devagar! [Adiciona um controle deslizante para ajustar a velocidade](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Volume preciso**: Controle o volume com precisão usando roda do mouse/atalhos, com HUD personalizado e níveis de volume customizáveis
-
-- **Atalhos (& MPRIS)**: Permite configurar teclas de atalho globais para controle (play/pause/próxima/anterior) + desativa [OSD de mídia](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png) sobrescrevendo teclas de mídia + ativa Ctrl/CMD + F para busca + suporte a MPRIS no Linux para teclas de mídia + [atalhos personalizados](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) para [usuários avançados](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-
-- **Pular músicas marcadas com "não gostei"**: Ignora automaticamente músicas que você deu dislike
-
-- **Pular silêncios**: Ignora automaticamente seções silenciosas
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Ignora automaticamente partes não musicais como introduções/outros ou partes de clipes onde a música não está tocando
-
-- **Letras sincronizadas**: Fornece letras sincronizadas para músicas, usando serviços como [LRClib](https://lrclib.net)
-
-- **Controle de mídia na barra de tarefas**: Controle a reprodução pela [barra de tarefas do Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **TouchBar**: Layout personalizado para a TouchBar do macOS
-
-- **Tuna OBS**: Integração com o plugin [Tuna](https://obsproject.com/forum/resources/tuna.843/) do [OBS](https://obsproject.com/)
-
-- **Seletor de qualidade de vídeo**: Permite alterar a qualidade do vídeo com um [botão](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) na sobreposição do vídeo
-
-- **Alternar vídeo**: Adiciona um [botão](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) para alternar entre modos Vídeo/Música. Pode também remover completamente a aba de vídeo
-
-- **Visualizador**: Diferentes visualizadores de música
-
-## Tradução
-
-Você pode ajudar com as traduções no [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Download
-
-Você pode verificar o [último lançamento](https://github.com/th-ch/youtube-music/releases/latest) para encontrar rapidamente a versão mais recente.
-
-### Arch Linux
-
-Instale o pacote [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) do AUR. Para instruções de instalação do AUR, consulte esta [página da wiki](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### macOS
-
-Você pode instalar o aplicativo usando Homebrew (veja a [definição do cask](https://github.com/th-ch/homebrew-youtube-music)):
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Se você instalar o aplicativo manualmente e receber o erro "is damaged and can’t be opened." ao abrir o app, execute o seguinte no Terminal:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Você pode usar o [gerenciador de pacotes Scoop](https://scoop.sh) para instalar o pacote `youtube-music` do [`extras bucket`](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Alternativamente, você pode usar o [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), o gerenciador de pacotes CLI oficial do Windows 11, para instalar o pacote `th-ch.YouTubeMusic`.
-
-*Nota: O Microsoft Defender SmartScreen pode bloquear a instalação por ser de um "publicador desconhecido". Isso também acontece na instalação manual ao tentar executar o arquivo .exe após download manual aqui no GitHub (mesmo arquivo).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Como instalar sem conexão à internet? (no Windows)
-
-- Baixe o arquivo `*.nsis.7z` para _sua arquitetura de dispositivo_ na [página de lançamentos](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` para Windows 64-bit
- - `ia32` para Windows 32-bit
- - `arm64` para Windows ARM64
-- Baixe o instalador na página de lançamentos (`*-Setup.exe`)
-- Coloque os arquivos no **mesmo diretório**
-- Execute o instalador
-
-## Temas
-
-Você pode carregar arquivos CSS para alterar a aparência do aplicativo (Opções > Ajustes Visuais > Temas).
-
-Alguns temas pré-definidos estão disponíveis em https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Dev
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Crie seus próprios plugins
-
-Usando plugins, você pode:
-
-- Manipular o aplicativo - o `BrowserWindow` do electron é passado para o manipulador de plugins
-- Alterar a interface manipulando o HTML/CSS
-
-### Criando um plugin
-
-Crie uma pasta em `src/plugins/NOMBRE-DEL-PLUGIN`:
-
-- `index.ts`: o arquivo principal do plugin
-```typescript
-import style from './style.css?inline'; // importar estilo como inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: "Plugin Label",
- restartNeeded: true, // se true, o ytmusic mostra diálogo de reinício
- config: {
- enabled: false,
- }, // sua configuração personalizada
- stylesheets: [style], // seu estilo personalizado
- menu: async ({ getConfig, setConfig }) => {
- // Todos os métodos *Config são wrappers Promise
- const config = await getConfig();
- return [
- {
- label: "menu",
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: "radio",
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // você pode se comunicar com o plugin renderer
- ipc.handle("some-event", () => {
- return "hello";
- });
- },
- // disparado quando a configuração muda
- onConfigChange(newConfig) { /* ... */ },
- // disparado quando o plugin é desativado
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke("some-event"));
- },
- // Hook disponível apenas no renderer
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // establecer la configuración del plugin fácilmente
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-
-```
-
-### Casos de uso comuns
-
-- **Injetar CSS personalizado**: crie um arquivo `style.css` na mesma pasta e então:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // importa estilo como inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // se true, o ytmusic mostrará um diálogo de reinício
- config: {
- enabled: false,
- }, // sua configuração personalizada
- stylesheets: [style], // seu estilo personalizado
- renderer() {} // define o hook renderer
-});
-```
-
-- Se quiser alterar o HTML:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // se true, o ytmusic mostrará o diálogo de reinício
- config: {
- enabled: false,
- }, // sua configuração personalizada
- renderer() {
- // Remove o botão de login
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // define o hook renderer
-});
-```
-
-- Comunicação entre front-end e back-end: pode ser feita usando o módulo ipcMain do Electron. Consulte o arquivo `index.ts` e o exemplo no plugin `sponsorblock`.
-
-## Compilar
-
-1. Clone o repositório
-2. Siga [este guia](https://pnpm.io/installation) para instalar o `pnpm`
-3. Execute `pnpm install --frozen-lockfile` para instalar as dependências
-4. Execute `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (arm64 para Debian)
-- `pnpm dist:linux:rpm-arm64` - Linux (arm64 para Fedora)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-Compila o aplicativo para macOS, Linux e Windows,
-usando [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Prévia de Produção
-
-```bash
-pnpm start
-```
-
-## Testes
-
-```bash
-pnpm test
-```
-
-Utiliza [Playwright](https://playwright.dev/) para testar o aplicativo.
-
-## Licença
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## Perguntas Frequentes
-
-### Por que o menu do aplicativo não aparece?
-
-Se a opção `Ocultar menu` estiver ativada - você pode exibir o menu com a tecla alt (ou \` [acento grave] se estiver usando o plugin in-app-menu)
diff --git a/docs/readme/README-ru.md b/docs/readme/README-ru.md
deleted file mode 100644
index 93e7ea8636..0000000000
--- a/docs/readme/README-ru.md
+++ /dev/null
@@ -1,374 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/.eslintrc.js)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Прочтите это на других языках: [🏴 Английский](../../README.md), [🇰🇷 корейский](./README-ko.md), [🇫🇷 Французский](./README-fr.md), [🇮🇸 исландский](./README-is.md), [🇪🇸 испанский](./README-es.md), [🇷🇺 Русский](./README-ru.md), [🇺🇦 Украинский](./README-uk.md), [🇧🇷 Португальский](./README-pt.md)
-
-**Клиент для YouTube Music основанный на Electron с поддержкой:**
-
-- Нативный вид приложения, нацелен на сохранение оригинального интерфейса
-- Фреймворк для пользовательских плагинов: изменяйте YouTube Music под ваши нужды (внешний вид, контент, возможности), включайте/выключайте плагины в один клик
-
-## Демо-изображение
-
-| Экран плеера (цветовая тема альбома & режим Ambient) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Содержание
-
-- [Возможности](#Возможности)
-- [Доступные плагины](#Доступные-плагины)
-- [Перевод](#Перевод)
-- [Скачать](#Скачать)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Как установить без подключения к интернету? (в Windows)](#Установка-без-подключения-к-Интернету-в-Windows)
-- [Темы](#Темы)
-- [Для разработчиков](#Для-разработчиков)
-- [Создайте свои собственные плагины](#Создайте-свои-собственные-плагины)
- - [Создание плагина](#Создание-плагина)
- - [Примеры использования](#Примеры-использования)
-- [Сборка](#Сборка)
-- [Предварительный просмотр](#Предварительный-просмотр)
-- [Тестирование](#Тестирование)
-- [Лицензия](#Лицензия)
-- [Часто задаваемые вопросы](#Часто-задаваемые-вопросы)
-
-## Возможности:
-
-- **Авто-подтверждение при паузе** (Всегда включено): отключает всплывающие уведомление ["Продолжить просмотр?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png),
- которое приостанавливает воспроизведение через определённое время
-
- - И больше ...
-
-## Доступные плагины:
-
-- **Блокировщик рекламы**: Блокирует всю рекламу и трекеры
-
-- **Действия с альбомом**: Добавляет кнопки "Убрать дизлайк", "Дизлайк", "Лайк", "Убрать лайк" и применяет их действия ко всем трекам в плейлисте или альбоме
-
-- **Цветовая тема альбома**: Применяет динамическую тему и эффекты, основываясь на цветовой палитре альбома
-
-- **Режим Ambient**: Применяет световой эффект, проецируя нежные цвета из видео на задний фон вашего экрана
-
-- **Нормализация аудио**: Применяет нормализацию к аудио (уменьшает громкость громких частей трека и повышает громкость тихих частей трека)
-
-- **Размытие панели навигации**: Делает панель навигации прозрачной и размытой
-
-- **Обход возрастных ограничений**: Обходит проверку возраста YouTube
-
-- **Выбор субтитров**: Включить субтитры
-
-- **Компактная боковая панель**: Всегда показывать боковую панель компактно
-
-- **Плавный переход**: Плавный переход между треками
-
-- **Отключить автопроигрыш**: Каждый трек начинается в режиме паузы
-
-- **[Discord](https://discord.com/) Rich Presence**: Показывает вашим друзьям, что вы слушаете с помощью [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Загрузчик**: Загрузка MP3 [напрямую из интерфейса](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Расширенная громкость**: Делает слайдер громкости [расширенным](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/) облегчая выбор громкости
-
-- **Меню в приложении**: [Придаёт панели меню красивый тёмный вид](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (посмотрите [этот пост,](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709) если у вас есть проблемы с доступом к меню после включения этого плагина и опции "Скрыть меню")
-
-- **Скробблер**: Добавляет поддержку скробблинга [Last.fm](https://www.last.fm/) и [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream**: Добавляет поддержку [Lumia Stream](https://lumiastream.com/)
-
-- **Тесты песен Genius**: Добавляет поддержку текстов для большинства песен
-
-- **Music Together**: Делитесь плейлистом с другими. Когда ведущий воспроизводит трек, все остальные будут слушать этот же трек.
-
-- **Навигация**: Кнопки Назад/Вперед интегрированы в интерфейс, как в вашем любимом браузере
-
-- **Без входа в систему Google**: Убирает из интерфейса кнопки и ссылки для входа через Google
-
-- **Уведомления**: Показывает уведомление, когда трек начинает играть ([интерактивные уведомления](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) доступны только для Windows)
-
-- **Картинка в картинке**: Позволяет переключить приложение в режим "картинка в картинке"
-
-- **Скорость воспроизведения**: Слушайте быстрее, слушайте медленнее! [Добавляет слайдер для контроля скорости трека](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Точная громкость**: Точечно управляйте громкостью с помощью колеса мыши/горячих клавиш, с кастомным интерфейсом и настраиваемыми шагами громкости
-
-- **Ярлыки (и MPRIS)**: Позволяет настроить глобальные горячие клавиши управления воспроизведением (плей/пауза/следующий/предыдущий) + отключает [отображение медиа на экране,](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png) переопределяя клавиши управления + включает Ctrl/CMD + F для поиска + включает поддержку linux mpris для клавиш управления медиа + [настраиваемые сочетания клавиш](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) для [продвинутых пользователей](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-
-- **Пропускать непонравившиеся треки**: Пропускает непонравившиеся треки
-
-- **Пропуск тишины**: Автоматически пропускает тихие моменты в песнях
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Автоматически пропускает немузыкальные части, такие как интро/аутро музыкальных видео, где трек не играет
-
-- **Управление воспроизведением из панели задач**: Управляйте воспроизведением из [панели задач Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **TouchBar**: Кастомная раскладка TouchBar для MacOS
-
-- **Tuna OBS**: Интеграция с [OBS](https://obsproject.com/) плагином [Tuna](https://obsproject.com/forum/resources/tuna.843/)
-
-- **Изменение качества видео**: Позволяет менять качество видео [кнопкой](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) на медиаплеере видео
-
-- **Переключатель видео**: Добавляет
- [кнопку](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) переключения режимов Трек/Видео. Также может удалять вкладку "Видео" полностью
-
-- **Визуализатор**: Различные визуализаторы музыки
-
-- **Synced Lyrics**:
-Предоставляет синхронизированные слова для песен из таких источников, как [LRClib](https://lrclib.net).
-
-## Перевод
-
-Вы можете помочь с переводом на ваш язык на [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Скачать
-
-Вы можете посмотреть [latest release,](https://github.com/th-ch/youtube-music/releases/latest) чтобы быстро найти новую версию.
-
-### Arch Linux
-
-Установите пакет [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) из AUR. Инструкции по установке из AUR можете найти на этой [вики-странице](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### macOS
-
-Вы можете установить приложение с помощью Homebrew (сморите [cask definition](https://github.com/th-ch/homebrew-youtube-music)):
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Если вы устанавливаете приложение вручную и получаете ошибку "is damaged and can’t be opened.", запустите в терминале следующую команду:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Вы можете использовать [пакетный менеджер Scoop](https://scoop.sh) для установки пакета `youtube-music` из [`extras` bucket](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Также для установки вы можете использовать [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), официальный пакетный менеджер командной строки Windows 11, для установки пакета `th-ch.YouTubeMusic`.
-
-*К сведению: SmartScreen защитника Windows может блокировать установку, так как она от "неизвестного издателя". Это также применимо к методу ручной установки, когда вы пытаетесь запустить исполняемый файл(.exe) после загрузки здесь, на GitHub (тот же файл).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Установка без подключения к Интернету? (в Windows)
-
-- Скачайте файл `*.nsis.7z` из _архетиктура вашего устройства_ на [release page](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` для 64-bit Windows
- - `ia32` для 32-bit Windows
- - `arm64` для ARM64 Windows
-- Скачайте установщик в release page. (`*-Setup.exe`)
-- Поместите их в **одной директории**.
-- Запустите установщик.
-
-## Темы
-
-Вы можете загрузить файл CSS для смены внешнего вида приложения (Настройки > Визуальные настройки > Тема).
-
-Некоторые предустановленные темы доступны здесь: https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Для разработчиков
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Создайте свои собственные плагины
-
-Используя плагины вы можете:
-
-- Манипулировать приложением - `BrowserWindow` из electron проброшен обработчику плагинов
-- Изменять внешний вид, манипулируя HTML/CSS
-
-### Создание плагина
-
-Создайте директорию в `src/plugins/YOUR-PLUGIN-NAME`:
-
-- `index.ts`: основной файл плагина
-```typescript
-import style from './style.css?inline'; // import style as inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic show restart dialog
- config: {
- enabled: false,
- }, // your custom config
- stylesheets: [style], // your custom style,
- menu: async ({ getConfig, setConfig }) => {
- // All *Config methods are wrapped Promise
- const config = await getConfig();
- return [
- {
- label: 'menu',
- submenu: [1, 2, 3].map((value) => ({
- label: `value ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // you can communicate with renderer plugin
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // it fired when config changed
- onConfigChange(newConfig) { /* ... */ },
- // it fired when plugin disabled
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // Only renderer available hook
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // set plugin config easily
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### Примеры использования
-
-- Кастомный CSS: создайте файл `style.css` в той же директории, затем:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // import style as inline
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic will show a restart dialog
- config: {
- enabled: false,
- }, // your custom config
- stylesheets: [style], // your custom style
- renderer() {} // define renderer hook
-});
-```
-
-- Если вы хотите изменить HTML:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Plugin Label',
- restartNeeded: true, // if value is true, ytmusic will show the restart dialog
- config: {
- enabled: false,
- }, // your custom config
- renderer() {
- // Remove the login button
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // define renderer hook
-});
-```
-
-- обмен между фронтом и бэком может быть выполнен с помощью модуля ipcMain из electron. Смотрите файл `index.ts` и
- пример в плагине `sponsorblock`.
-
-## Сборка
-
-1. Склонируйте репозиторий
-2. Следуйте [этой инструкции,](https://pnpm.io/installation) чтобы установить `pnpm`
-3. Запустите `pnpm install --frozen-lockfile` для установки зависимостей
-4. Запустите `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (arm64 for Debian)
-- `pnpm dist:linux:rpm-arm64` - Linux (arm64 for Fedora)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-Сборка приложения для macOS, Linux, и Windows,
-используя [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Предварительный просмотр
-
-```bash
-pnpm start
-```
-
-## Тестирование
-
-```bash
-pnpm test
-```
-
-Использует [Playwright](https://playwright.dev/) для тестирования приложения.
-
-## Лицензия
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## Часто задаваемые вопросы
-
-### Почему меня приложения не отображается?
-
-Если опция `Скрыть меню` включена - вы можете отобразить меню с помощью клавиши alt (или \` [обратный апостроф], если используете плагин "Меню в приложении")
diff --git a/docs/readme/README-uk.md b/docs/readme/README-uk.md
deleted file mode 100644
index ce32f3a0ba..0000000000
--- a/docs/readme/README-uk.md
+++ /dev/null
@@ -1,372 +0,0 @@
-
-
-# YouTube Music
-
-[](https://github.com/th-ch/youtube-music/releases/)
-[](https://github.com/th-ch/youtube-music/blob/master/license)
-[](https://github.com/th-ch/youtube-music/blob/master/eslint.config.mjs)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://GitHub.com/th-ch/youtube-music/releases/)
-[](https://aur.archlinux.org/packages/youtube-music-bin)
-[](https://snyk.io/test/github/th-ch/youtube-music)
-
-
-
-
-
-
-
-
-Прочитайте це іншими мовами: [🏴 Англійська](../../README.md), [🇰🇷 Корейська](./README-ko.md), [🇫🇷 Французька](./README-fr.md), [🇮🇸 Ісландська](./README-is.md), [🇪🇸 Іспанська](./README-es.md), [🇷🇺 Російська](./README-ru.md), [🇺🇦 Українська](./README-uk.md), [🇭🇺 Угорська](./README-hu.md), [🇧🇷 Португальська](./README-pt.md), [🇯🇵 Японська](./README-ja.md)
-
-**Клієнт YouTube Music на основі Electron, що має:**
-
-- Нативний вигляд і функціонал, що має на меті зберегти оригінальний інтерфейс
-- Фреймворк для користувацьких плагінів: змінюйте YouTube Music відповідно до ваших потреб (стиль, вміст, функції), вмикайте/вимикайте плагіни одним клацанням миші
-
-## Демонстраційне зображення
-
-| Екран плеєра (колірна тема альбому та режим Ambient) |
-|:---------------------------------------------------------------------------------------------------------:|
-||
-
-## Зміст
-
-- [Можливості](#Можливості)
-- [Доступні плагіни](#Доступні-плагіни)
-- [Переклад](#Переклад)
-- [Завантажити](#Завантажити)
- - [Arch Linux](#arch-linux)
- - [MacOS](#macos)
- - [Windows](#windows)
- - [Як встановити без підключення до Інтернету? (у Windows)](#Встановлення-без-підключення-до-Інтернету-у-Windows)
-- [Теми](#Теми)
-- [Розробка](#Розробка)
-- [Створіть власні плагіни](#Створіть-власні-плагіни)
- - [Створення плагіна](#Створення-плагіна)
- - [Поширені випадки використання](#Поширені-випадки-використання)
-- [Збірка](#Збірка)
-- [Попередній перегляд для producción](#Попередній-перегляд-для-production)
-- [Тести](#Тести)
-- [Ліцензія](#Ліцензія)
-- [Поширені запитання](#Поширені-запитання)
-
-## Можливості:
-
-- **Автоматичне підтвердження під час паузи** (Завжди ввімкнено): вимикає спливаюче вікно ["Продовжити перегляд?"](https://user-images.githubusercontent.com/61631665/129977894-01c60740-7ec6-4bf0-9a2c-25da24491b0e.png),
- яке призупиняє музику через певний час
-
- - Та багато іншого...
-
-## Доступні плагіни:
-
-- **Блокувальник реклами**: Блокує всю рекламу та відстеження «з коробки»
-
-- **Дії з альбомом**: Додає кнопки «Скасувати "Не подобається"», «Не подобається», «Подобається» та «Скасувати "Подобається"», щоб застосувати це до всіх пісень у списку відтворення або альбомі
-
-- **Колірна тема альбому**: Застосовує динамічну тему та візуальні ефекти на основі колірної палітри альбому
-
-- **Режим Ambient**: Застосовує ефект освітлення, проектуючи м'які кольори з відео на фон екрана
-
-- **Аудіокомпресор**: Застосовує компресію до аудіо (знижує гучність найгучніших частин сигналу та підвищує гучність найтихіших частин)
-
-- **Розмиття панелі навігації**: робить панель навігації прозорою та розмитою
-
-- **Обхід вікових обмежень**: обходить перевірку віку YouTube
-
-- **Вибір субтитрів**: Увімкнути субтитри
-
-- **Компактна бічна панель**: Завжди встановлювати бічну панель у компактному режимі
-
-- **Плавний перехід**: Плавний перехід між піснями
-
-- **Вимкнути автопрогравання**: Кожна пісня починається в режимі "пауза"
-
-- **[Discord](https://discord.com/) Rich Presence**: Покажіть друзям, що ви слухаєте, за допомогою [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
-
-- **Завантажувач**: завантажує MP3 [безпосередньо з інтерфейсу](https://user-images.githubusercontent.com/61631665/129977677-83a7d067-c192-45e1-98ae-b5a4927393be.png) [(youtube-dl)](https://github.com/ytdl-org/youtube-dl)
-
-- **Експоненціальна гучність**: Робить повзунок гучності [експоненціальним](https://greasyfork.org/en/scripts/397686-youtube-music-fix-volume-ratio/), щоб було легше вибирати нижчу гучність
-
-- **Меню в програмі**: [надає панелям модного, темного вигляду](https://user-images.githubusercontent.com/78568641/112215894-923dbf00-8c29-11eb-95c3-3ce15db27eca.png)
-
- > (дивіться [цей пост](https://github.com/th-ch/youtube-music/issues/410#issuecomment-952060709), якщо у вас виникли проблеми з доступом до меню після ввімкнення цього плагіна та опції приховування меню)
-
-- **Скробблер**: Додає підтримку скробблінгу для [Last.fm](https://www.last.fm/) та [ListenBrainz](https://listenbrainz.org/)
-
-- **Lumia Stream**: Додає підтримку [Lumia Stream](https://lumiastream.com/)
-
-- **Тексти пісень Genius**: Додає підтримку текстів для більшості пісень
-
-- **Музика разом**: Поділіться списком відтворення з іншими. Коли хост відтворює пісню, всі інші чутимуть ту саму пісню
-
-- **Навігація**: Стрілки навігації «Вперед»/«Назад» безпосередньо інтегровані в інтерфейс, як у вашому улюбленому браузері
-
-- **Без входу в Google**: Видаляє кнопки та посилання для входу в Google з інтерфейсу
-
-- **Сповіщення**: Відображає сповіщення, коли починає грати пісня ([інтерактивні сповіщення](https://user-images.githubusercontent.com/78568641/114102651-63ce0e00-98d0-11eb-9dfe-c5a02bb54f9c.png) доступні у Windows)
-
-- **Картинка в картинці**: дозволяє перемикати програму в режим «картинка в картинці»
-
-- **Швидкість відтворення**: Слухайте швидко, слухайте повільно! [Додає повзунок, який контролює швидкість пісні](https://user-images.githubusercontent.com/61631665/129976003-e55db5ba-bf42-448c-a059-26a009775e68.png)
-
-- **Точна гучність**: Точно керуйте гучністю за допомогою коліщатка миші/гарячих клавіш, з власним HUD та настроюваними кроками гучності
-
-- **Гарячі клавіші (та MPRIS)**: Дозволяє встановлювати глобальні гарячі клавіші для відтворення (відтворення/пауза/наступна/попередня) + вимкнути [екранне меню медіа](https://user-images.githubusercontent.com/84923831/128601225-afa38c1f-dea8-4209-9f72-0f84c1dd8b54.png) шляхом перевизначення медіаклавіш + увімкнути Ctrl/CMD + F для пошуку + увімкнути підтримку mpris у Linux для медіаклавіш + [власні гарячі клавіші](https://github.com/Araxeus/youtube-music/blob/1e591d6a3df98449bcda6e63baab249b28026148/providers/song-controls.js#L13-L50) для [досвідчених користувачів](https://github.com/th-ch/youtube-music/issues/106#issuecomment-952156902)
-
-- **Пропускати пісні, що не сподобалися**: Пропускає пісні, які вам не сподобалися
-
-- **Пропускати тишу**: Автоматично пропускати тихі фрагменти
-
-- [**SponsorBlock**](https://github.com/ajayyy/SponsorBlock): Автоматично пропускає немузичні частини, такі як інтро/аутро, або частини музичних відео, де пісня не грає
-
-- **Керування медіа на панелі завдань**: Керуйте відтворенням з [панелі завдань Windows](https://user-images.githubusercontent.com/78568641/111916130-24a35e80-8a82-11eb-80c8-5021c1aa27f4.png)
-
-- **TouchBar**: Власний макет TouchBar для macOS
-
-- **Tuna OBS**: Інтеграція з плагіном [Tuna](https://obsproject.com/forum/resources/tuna.843/) для [OBS](https://obsproject.com/)
-
-- **Зміна якості відео**: Дозволяє змінювати якість відео за допомогою [кнопки](https://user-images.githubusercontent.com/78568641/138574366-70324a5e-2d64-4f6a-acdd-dc2a2b9cecc5.png) на відеопрогравачі
-
-- **Перемикач відео**: Додає [кнопку](https://user-images.githubusercontent.com/28893833/173663950-63e6610e-a532-49b7-9afa-54cb57ddfc15.png) для перемикання між режимом відео/пісні. Також може опціонально видалити всю вкладку відео
-
-- **Візуалізатор**: Різні музичні візуалізатори
-
-- **Синхронізовані тексти**: Надає синхронізовані тексти пісень, використовуючи такі джерела, як [LRClib](https://lrclib.net).
-
-## Переклад
-
-Ви можете допомогти з перекладом на [Hosted Weblate](https://hosted.weblate.org/projects/youtube-music/).
-
-
-
-
-
-
-## Завантажити
-
-Ви можете переглянути [останній реліз](https://github.com/th-ch/youtube-music/releases/latest), щоб швидко знайти найновішу версію.
-
-### Arch Linux
-
-Встановіть пакет [`youtube-music-bin`](https://aur.archlinux.org/packages/youtube-music-bin) з AUR. Інструкції щодо встановлення з AUR можна знайти на цій [сторінці вікі](https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages).
-
-### macOS
-
-Ви можете встановити програму за допомогою Homebrew (дивіться [визначення cask](https://github.com/th-ch/homebrew-youtube-music)):
-
-```bash
-brew install th-ch/youtube-music/youtube-music
-```
-
-Якщо ви встановлюєте програму вручну та отримуєте помилку "is damaged and can’t be opened.", запустіть у Терміналі таку команду:
-
-```bash
-/usr/bin/xattr -cr /Applications/YouTube\ Music.app
-```
-
-### Windows
-
-Ви можете використовувати [менеджер пакунків Scoop](https://scoop.sh) для встановлення пакунка `youtube-music` з [`extras` bucket](https://github.com/ScoopInstaller/Extras).
-
-```bash
-scoop bucket add extras
-scoop install extras/youtube-music
-```
-
-Крім того, ви можете використовувати [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), офіційний менеджер пакунків командного рядка Windows 11, для встановлення пакунка `th-ch.YouTubeMusic`.
-
-*Примітка: Microsoft Defender SmartScreen може блокувати встановлення, оскільки воно від "невідомого видавця". Це також стосується ручного встановлення під час спроби запустити виконуваний файл (.exe) після ручного завантаження тут, на GitHub (той самий файл).*
-
-```bash
-winget install th-ch.YouTubeMusic
-```
-
-#### Як встановити без підключення до Інтернету? (у Windows)
-
-- Завантажте файл `*.nsis.7z` для _архітектури вашого пристрою_ зі [сторінки релізів](https://github.com/th-ch/youtube-music/releases/latest).
- - `x64` для 64-розрядної Windows
- - `ia32` для 32-розрядної Windows
- - `arm64` для ARM64 Windows
-- Завантажте інсталятор зі сторінки релізів. (`*-Setup.exe`)
-- Розмістіть їх в **одному каталозі**.
-- Запустіть інсталятор.
-
-## Теми
-
-Ви можете завантажити файли CSS, щоб змінити вигляд програми (Опції > Візуальні налаштування > Теми).
-
-Деякі попередньо визначені теми доступні за адресою https://github.com/kerichdev/themes-for-ytmdesktop-player.
-
-## Розробка
-
-```bash
-git clone https://github.com/th-ch/youtube-music
-cd youtube-music
-pnpm install --frozen-lockfile
-pnpm dev
-```
-
-## Створіть власні плагіни
-
-Використовуючи плагіни, ви можете:
-
-- маніпулювати програмою - `BrowserWindow` з Electron передається обробнику плагінів
-- змінювати фронтенд, маніпулюючи HTML/CSS
-
-### Створення плагіна
-
-Створіть теку в `src/plugins/НАЗВА_ВАШОГО_ПЛАГІНА`:
-
-- `index.ts`: основний файл плагіна
-```typescript
-import style from './style.css?inline'; // імпортувати стиль як вбудований
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Назва плагіна',
- restartNeeded: true, // якщо значення true, ytmusic покаже діалогове вікно перезапуску
- config: {
- enabled: false,
- }, // ваша власна конфігурація
- stylesheets: [style], // ваш власний стиль,
- menu: async ({ getConfig, setConfig }) => {
- // Усі методи *Config є обгорнутими Promise
- const config = await getConfig();
- return [
- {
- label: 'меню',
- submenu: [1, 2, 3].map((value) => ({
- label: `значення ${value}`,
- type: 'radio',
- checked: config.value === value,
- click() {
- setConfig({ value });
- },
- })),
- },
- ];
- },
- backend: {
- start({ window, ipc }) {
- window.maximize();
-
- // ви можете спілкуватися з плагіном рендерера
- ipc.handle('some-event', () => {
- return 'hello';
- });
- },
- // викликається при зміні конфігурації
- onConfigChange(newConfig) { /* ... */ },
- // викликається при вимкненні плагіна
- stop(context) { /* ... */ },
- },
- renderer: {
- async start(context) {
- console.log(await context.ipc.invoke('some-event'));
- },
- // Хук, доступний лише для рендерера
- onPlayerApiReady(api: YoutubePlayer, context: RendererContext) {
- // легко встановити конфігурацію плагіна
- context.setConfig({ myConfig: api.getVolume() });
- },
- onConfigChange(newConfig) { /* ... */ },
- stop(_context) { /* ... */ },
- },
- preload: {
- async start({ getConfig }) {
- const config = await getConfig();
- },
- onConfigChange(newConfig) {},
- stop(_context) {},
- },
-});
-```
-
-### Поширені випадки використання
-
-- ін'єкція власного CSS: створіть файл `style.css` у тій самій теці, а потім:
-
-```typescript
-// index.ts
-import style from './style.css?inline'; // імпортувати стиль як вбудований
-
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Назва плагіна',
- restartNeeded: true, // якщо значення true, ytmusic покаже діалогове вікно перезапуску
- config: {
- enabled: false,
- }, // ваша власна конфігурація
- stylesheets: [style], // ваш власний стиль
- renderer() {} // визначити хук рендерера
-});
-```
-
-- Якщо ви хочете змінити HTML:
-
-```typescript
-import { createPlugin } from '@/utils';
-
-export default createPlugin({
- name: 'Назва плагіна',
- restartNeeded: true, // якщо значення true, ytmusic покаже діалогове вікно перезапуску
- config: {
- enabled: false,
- }, // ваша власна конфігурація
- renderer() {
- // Видалити кнопку входу
- document.querySelector(".sign-in-link.ytmusic-nav-bar").remove();
- } // визначити хук рендерера
-});
-```
-
-- зв'язок між фронтендом та бекендом: можна здійснити за допомогою модуля ipcMain з Electron. Дивіться файл `index.ts` та
- приклад у плагіні `sponsorblock`.
-
-## Збірка
-
-1. Клонуйте репозиторій
-2. Дотримуйтесь [цієї інструкції](https://pnpm.io/installation), щоб встановити `pnpm`
-3. Запустіть `pnpm install --frozen-lockfile` для встановлення залежностей
-4. Запустіть `pnpm build:OS`
-
-- `pnpm dist:win` - Windows
-- `pnpm dist:linux` - Linux (amd64)
-- `pnpm dist:linux:deb-arm64` - Linux (arm64 для Debian)
-- `pnpm dist:linux:rpm-arm64` - Linux (arm64 для Fedora)
-- `pnpm dist:mac` - macOS (amd64)
-- `pnpm dist:mac:arm64` - macOS (arm64)
-
-Збирає програму для macOS, Linux та Windows,
-використовуючи [electron-builder](https://github.com/electron-userland/electron-builder).
-
-## Попередній перегляд для production
-
-```bash
-pnpm start
-```
-
-## Тести
-
-```bash
-pnpm test
-```
-
-Використовує [Playwright](https://playwright.dev/) для тестування програми.
-
-## Ліцензія
-
-MIT © [th-ch](https://github.com/th-ch/youtube-music)
-
-## Поширені запитання
-
-### Чому меню програми не відображається?
-
-Якщо опція `Приховати меню` увімкнена - ви можете показати меню клавішею Alt (або \` [зворотний апостроф], якщо використовуєте плагін "Меню в програмі")
diff --git a/docs/style/fonts.css b/docs/style/fonts.css
deleted file mode 100644
index fac730897c..0000000000
--- a/docs/style/fonts.css
+++ /dev/null
@@ -1,53 +0,0 @@
-/* hebrew */
-@font-face {
- font-family: 'Heebo';
- font-style: normal;
- font-weight: 400;
- src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H0TbFhsqMA6aw.woff2) format('woff2');
- unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F;
-}
-
-/* latin */
-@font-face {
- font-family: 'Heebo';
- font-style: normal;
- font-weight: 400;
- src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H2TbFhsqMA.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/* hebrew */
-@font-face {
- font-family: 'Heebo';
- font-style: normal;
- font-weight: 700;
- src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H0TbFhsqMA6aw.woff2) format('woff2');
- unicode-range: U+0590-05FF, U+20AA, U+25CC, U+FB1D-FB4F;
-}
-
-/* latin */
-@font-face {
- font-family: 'Heebo';
- font-style: normal;
- font-weight: 700;
- src: url(https://fonts.gstatic.com/s/heebo/v9/NGS6v5_NC0k9P9H2TbFhsqMA.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/* latin-ext */
-@font-face {
- font-family: 'Oxygen';
- font-style: normal;
- font-weight: 700;
- src: url(https://fonts.gstatic.com/s/oxygen/v10/2sDcZG1Wl4LcnbuCNWgzZmW5Kb8VZBHR.woff2) format('woff2');
- unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-
-/* latin */
-@font-face {
- font-family: 'Oxygen';
- font-style: normal;
- font-weight: 700;
- src: url(https://fonts.gstatic.com/s/oxygen/v10/2sDcZG1Wl4LcnbuCNWgzaGW5Kb8VZA.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
diff --git a/docs/style/style.css b/docs/style/style.css
deleted file mode 100644
index 1106ca621a..0000000000
--- a/docs/style/style.css
+++ /dev/null
@@ -1,1890 +0,0 @@
-html {
- line-height: 1.15;
- -ms-text-size-adjust: 100%;
- -webkit-text-size-adjust: 100%;
-}
-
-body {
- margin: 0;
-}
-
-article,
-aside,
-footer,
-header,
-nav,
-section {
- display: block;
-}
-
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-figcaption,
-figure,
-main {
- display: block;
-}
-
-figure {
- margin: 1em 40px;
-}
-
-hr {
- box-sizing: content-box;
- height: 0;
- overflow: visible;
-}
-
-pre {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-a {
- background-color: transparent;
- -webkit-text-decoration-skip: objects;
-}
-
-abbr[title] {
- border-bottom: none;
- text-decoration: underline;
- -webkit-text-decoration: underline dotted;
- text-decoration: underline dotted;
-}
-
-b,
-strong {
- font-weight: inherit;
-}
-
-b,
-strong {
- font-weight: bolder;
-}
-
-code,
-kbd,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-dfn {
- font-style: italic;
-}
-
-mark {
- background-color: #ff0;
- color: #000;
-}
-
-small {
- font-size: 80%;
-}
-
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-
-sub {
- bottom: -0.25em;
-}
-
-sup {
- top: -0.5em;
-}
-
-audio,
-video {
- display: inline-block;
-}
-
-audio:not([controls]) {
- display: none;
- height: 0;
-}
-
-img {
- border-style: none;
-}
-
-svg:not(:root) {
- overflow: hidden;
-}
-
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: sans-serif;
- font-size: 100%;
- line-height: 1.15;
- margin: 0;
-}
-
-button,
-input {
- overflow: visible;
-}
-
-button,
-select {
- text-transform: none;
-}
-
-button,
-html [type="button"],
-[type="reset"],
-[type="submit"] {
- -webkit-appearance: button;
-}
-
-button::-moz-focus-inner,
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner,
-[type="submit"]::-moz-focus-inner {
- border-style: none;
- padding: 0;
-}
-
-button:-moz-focusring,
-[type="button"]:-moz-focusring,
-[type="reset"]:-moz-focusring,
-[type="submit"]:-moz-focusring {
- outline: 1px dotted ButtonText;
-}
-
-fieldset {
- padding: 0.35em 0.75em 0.625em;
-}
-
-legend {
- box-sizing: border-box;
- color: inherit;
- display: table;
- max-width: 100%;
- padding: 0;
- white-space: normal;
-}
-
-progress {
- display: inline-block;
- vertical-align: baseline;
-}
-
-textarea {
- overflow: auto;
-}
-
-[type="checkbox"],
-[type="radio"] {
- box-sizing: border-box;
- padding: 0;
-}
-
-[type="number"]::-webkit-inner-spin-button,
-[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-
-[type="search"] {
- -webkit-appearance: textfield;
- outline-offset: -2px;
-}
-
-[type="search"]::-webkit-search-cancel-button,
-[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- font: inherit;
-}
-
-details,
-menu {
- display: block;
-}
-
-summary {
- display: list-item;
-}
-
-canvas {
- display: inline-block;
-}
-
-template {
- display: none;
-}
-
-[hidden] {
- display: none;
-}
-
-html {
- box-sizing: border-box;
-}
-
-*,
-*:before,
-*:after {
- box-sizing: inherit;
-}
-
-body {
- background: #3f4042;
- -moz-osx-font-smoothing: grayscale;
- -webkit-font-smoothing: antialiased;
-}
-
-hr {
- border: 0;
- display: block;
- height: 1px;
- background: #3f4042;
- margin-top: 24px;
- margin-bottom: 24px;
-}
-
-ul,
-ol {
- margin-top: 0;
- margin-bottom: 24px;
- padding-left: 24px;
-}
-
-ul {
- list-style: disc;
-}
-
-ol {
- list-style: decimal;
-}
-
-li > ul,
-li > ol {
- margin-bottom: 0;
-}
-
-dl {
- margin-top: 0;
- margin-bottom: 24px;
-}
-
-dt {
- font-weight: 600;
-}
-
-dd {
- margin-left: 24px;
- margin-bottom: 24px;
-}
-
-img {
- height: auto;
- max-width: 100%;
- vertical-align: middle;
-}
-
-figure {
- margin: 24px 0;
-}
-
-figcaption {
- font-size: 16px;
- line-height: 24px;
- padding: 8px 0;
-}
-
-img,
-svg {
- display: block;
-}
-
-table {
- border-collapse: collapse;
- margin-bottom: 24px;
- width: 100%;
-}
-
-tr {
- border-bottom: 1px solid #e4e8ee;
-}
-
-th {
- text-align: left;
-}
-
-th,
-td {
- padding: 10px 16px;
-}
-
-th:first-child,
-td:first-child {
- padding-left: 0;
-}
-
-th:last-child,
-td:last-child {
- padding-right: 0;
-}
-
-html {
- font-size: 20px;
- line-height: 30px;
-}
-
-body {
- color: #b7bbc1;
- font-size: 1rem;
-}
-
-body,
-button,
-input,
-select,
-textarea {
- font-family: "Heebo", sans-serif;
-}
-
-a {
- color: #c3352e;
- text-decoration: none;
-}
-
-a:hover,
-a:active {
- outline: 0;
- text-decoration: underline;
-}
-
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-.h1,
-.h2,
-.h3,
-.h4,
-.h5,
-.h6 {
- clear: both;
- color: #fff;
- font-family: "Oxygen", sans-serif;
- font-weight: 600;
-}
-
-h1,
-.h1 {
- font-size: 38px;
- line-height: 48px;
- letter-spacing: 0px;
-}
-
-@media (min-width: 641px) {
- h1,
- .h1 {
- font-size: 44px;
- line-height: 54px;
- letter-spacing: 0px;
- }
-}
-
-h2,
-.h2 {
- font-size: 32px;
- line-height: 42px;
- letter-spacing: 0px;
-}
-
-@media (min-width: 641px) {
- h2,
- .h2 {
- font-size: 38px;
- line-height: 48px;
- letter-spacing: 0px;
- }
-}
-
-h3,
-.h3,
-blockquote {
- font-size: 28px;
- line-height: 34px;
- letter-spacing: 0px;
-}
-
-@media (min-width: 641px) {
- h3,
- .h3,
- blockquote {
- font-size: 32px;
- line-height: 42px;
- letter-spacing: 0px;
- }
-}
-
-h4,
-.h4 {
- font-size: 28px;
- line-height: 34px;
- letter-spacing: 0px;
-}
-
-h5,
-.h5,
-h6,
-.h6 {
- font-size: 20px;
- line-height: 30px;
- letter-spacing: -0.1px;
-}
-
-@media (max-width: 640px) {
- .h1-mobile {
- font-size: 38px;
- line-height: 48px;
- letter-spacing: 0px;
- }
-
- .h2-mobile {
- font-size: 32px;
- line-height: 42px;
- letter-spacing: 0px;
- }
-
- .h3-mobile {
- font-size: 28px;
- line-height: 34px;
- letter-spacing: 0px;
- }
-
- .h4-mobile {
- font-size: 28px;
- line-height: 34px;
- letter-spacing: 0px;
- }
-
- .h5-mobile,
- .h6-mobile {
- font-size: 20px;
- line-height: 30px;
- letter-spacing: -0.1px;
- }
-}
-
-.text-light {
- color: #606483;
-}
-
-.text-light a {
- color: #606483;
-}
-
-.text-light h1,
-.text-light h2,
-.text-light h3,
-.text-light h4,
-.text-light h5,
-.text-light h6,
-.text-light .h1,
-.text-light .h2,
-.text-light .h3,
-.text-light .h4,
-.text-light .h5,
-.text-light .h6 {
- color: #fff !important;
-}
-
-.text-sm {
- font-size: 18px;
- line-height: 27px;
- letter-spacing: -0.1px;
-}
-
-.text-xs {
- font-size: 16px;
- line-height: 24px;
- letter-spacing: -0.1px;
-}
-
-h1,
-h2,
-.h1,
-.h2 {
- margin-top: 48px;
- margin-bottom: 16px;
-}
-
-h3,
-.h3 {
- margin-top: 36px;
- margin-bottom: 12px;
-}
-
-h4,
-h5,
-h6,
-.h4,
-.h5,
-.h6 {
- margin-top: 24px;
- margin-bottom: 4px;
-}
-
-p {
- margin-top: 0;
- margin-bottom: 24px;
-}
-
-dfn,
-cite,
-em,
-i {
- font-style: italic;
-}
-
-blockquote {
- color: #b7bbc1;
- font-style: italic;
- margin-top: 24px;
- margin-bottom: 24px;
- margin-left: 24px;
-}
-
-blockquote::before {
- content: "\201C";
-}
-
-blockquote::after {
- content: "\201D";
-}
-
-blockquote p {
- display: inline;
-}
-
-address {
- color: #b7bbc1;
- border-width: 1px 0;
- border-style: solid;
- border-color: #e4e8ee;
- padding: 24px 0;
- margin: 0 0 24px;
-}
-
-pre,
-pre h1,
-pre h2,
-pre h3,
-pre h4,
-pre h5,
-pre h6,
-pre .h1,
-pre .h2,
-pre .h3,
-pre .h4,
-pre .h5,
-pre .h6 {
- font-family: "Courier 10 Pitch", Courier, monospace;
-}
-
-pre,
-code,
-kbd,
-tt,
-var {
- background: #f3f4ff;
-}
-
-pre {
- font-size: 16px;
- line-height: 24px;
- margin-bottom: 1.6em;
- max-width: 100%;
- overflow: auto;
- padding: 24px;
- margin-top: 24px;
- margin-bottom: 24px;
-}
-
-code,
-kbd,
-tt,
-var {
- font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace;
- font-size: 16px;
- padding: 2px 4px;
-}
-
-abbr,
-acronym {
- cursor: help;
-}
-
-mark,
-ins {
- text-decoration: none;
-}
-
-small {
- font-size: 18px;
- line-height: 27px;
- letter-spacing: -0.1px;
-}
-
-b,
-strong {
- font-weight: 600;
-}
-
-button,
-input,
-select,
-textarea,
-label {
- font-size: 20px;
- line-height: 30px;
-}
-
-.container,
-.container-sm {
- width: 100%;
- margin: 0 auto;
- padding-left: 16px;
- padding-right: 16px;
-}
-
-@media (min-width: 481px) {
- .container,
- .container-sm {
- padding-left: 24px;
- padding-right: 24px;
- }
-}
-
-.container {
- max-width: 1128px;
-}
-
-.container-sm {
- max-width: 848px;
-}
-
-.container .container-sm {
- max-width: 800px;
- padding-left: 0;
- padding-right: 0;
-}
-
-.screen-reader-text {
- clip: rect(1px, 1px, 1px, 1px);
- position: absolute !important;
- height: 1px;
- width: 1px;
- overflow: hidden;
- word-wrap: normal !important;
-}
-
-.screen-reader-text:focus {
- border-radius: 2px;
- box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6);
- clip: auto !important;
- display: block;
- font-size: 14px;
- letter-spacing: 0px;
- font-weight: 600;
- line-height: 16px;
- text-decoration: none;
- text-transform: uppercase;
- background-color: #fff;
- color: #c3352e !important;
- border: none;
- height: auto;
- left: 8px;
- padding: 16px 40px;
- top: 8px;
- width: auto;
- z-index: 100000;
-}
-
-.list-reset {
- list-style: none;
- padding: 0;
-}
-
-.text-left {
- text-align: left;
-}
-
-.text-center {
- text-align: center;
-}
-
-.text-right {
- text-align: right;
-}
-
-.text-primary {
- color: #c3352e;
-}
-
-.text-secondary {
- color: #ff6c50;
-}
-
-.has-top-divider {
- position: relative;
-}
-
-.has-top-divider::before {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- display: block;
- height: 1px;
- background: #e4e8ee;
-}
-
-.has-bottom-divider {
- position: relative;
-}
-
-.has-bottom-divider::after {
- content: "";
- position: absolute;
- bottom: 0;
- left: 0;
- width: 100%;
- display: block;
- height: 1px;
- background: #e4e8ee;
-}
-
-.m-0 {
- margin: 0;
-}
-
-.mt-0 {
- margin-top: 0;
-}
-
-.mr-0 {
- margin-right: 0;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.ml-0 {
- margin-left: 0;
-}
-
-.m-8 {
- margin: 8px;
-}
-
-.mt-8 {
- margin-top: 8px;
-}
-
-.mr-8 {
- margin-right: 8px;
-}
-
-.mb-8 {
- margin-bottom: 8px;
-}
-
-.ml-8 {
- margin-left: 8px;
-}
-
-.m-16 {
- margin: 16px;
-}
-
-.mt-16 {
- margin-top: 16px;
-}
-
-.mr-16 {
- margin-right: 16px;
-}
-
-.mb-16 {
- margin-bottom: 16px;
-}
-
-.ml-16 {
- margin-left: 16px;
-}
-
-.m-24 {
- margin: 24px;
-}
-
-.mt-24 {
- margin-top: 24px;
-}
-
-.mr-24 {
- margin-right: 24px;
-}
-
-.mb-24 {
- margin-bottom: 24px;
-}
-
-.ml-24 {
- margin-left: 24px;
-}
-
-.m-32 {
- margin: 32px;
-}
-
-.mt-32 {
- margin-top: 32px;
-}
-
-.mr-32 {
- margin-right: 32px;
-}
-
-.mb-32 {
- margin-bottom: 32px;
-}
-
-.ml-32 {
- margin-left: 32px;
-}
-
-.m-40 {
- margin: 40px;
-}
-
-.mt-40 {
- margin-top: 40px;
-}
-
-.mr-40 {
- margin-right: 40px;
-}
-
-.mb-40 {
- margin-bottom: 40px;
-}
-
-.ml-40 {
- margin-left: 40px;
-}
-
-.m-48 {
- margin: 48px;
-}
-
-.mt-48 {
- margin-top: 48px;
-}
-
-.mr-48 {
- margin-right: 48px;
-}
-
-.mb-48 {
- margin-bottom: 48px;
-}
-
-.ml-48 {
- margin-left: 48px;
-}
-
-.m-56 {
- margin: 56px;
-}
-
-.mt-56 {
- margin-top: 56px;
-}
-
-.mr-56 {
- margin-right: 56px;
-}
-
-.mb-56 {
- margin-bottom: 56px;
-}
-
-.ml-56 {
- margin-left: 56px;
-}
-
-.m-64 {
- margin: 64px;
-}
-
-.mt-64 {
- margin-top: 64px;
-}
-
-.mr-64 {
- margin-right: 64px;
-}
-
-.mb-64 {
- margin-bottom: 64px;
-}
-
-.ml-64 {
- margin-left: 64px;
-}
-
-.p-0 {
- padding: 0;
-}
-
-.pt-0 {
- padding-top: 0;
-}
-
-.pr-0 {
- padding-right: 0;
-}
-
-.pb-0 {
- padding-bottom: 0;
-}
-
-.pl-0 {
- padding-left: 0;
-}
-
-.p-8 {
- padding: 8px;
-}
-
-.pt-8 {
- padding-top: 8px;
-}
-
-.pr-8 {
- padding-right: 8px;
-}
-
-.pb-8 {
- padding-bottom: 8px;
-}
-
-.pl-8 {
- padding-left: 8px;
-}
-
-.p-16 {
- padding: 16px;
-}
-
-.pt-16 {
- padding-top: 16px;
-}
-
-.pr-16 {
- padding-right: 16px;
-}
-
-.pb-16 {
- padding-bottom: 16px;
-}
-
-.pl-16 {
- padding-left: 16px;
-}
-
-.p-24 {
- padding: 24px;
-}
-
-.pt-24 {
- padding-top: 24px;
-}
-
-.pr-24 {
- padding-right: 24px;
-}
-
-.pb-24 {
- padding-bottom: 24px;
-}
-
-.pl-24 {
- padding-left: 24px;
-}
-
-.p-32 {
- padding: 32px;
-}
-
-.pt-32 {
- padding-top: 32px;
-}
-
-.pr-32 {
- padding-right: 32px;
-}
-
-.pb-32 {
- padding-bottom: 32px;
-}
-
-.pl-32 {
- padding-left: 32px;
-}
-
-.p-40 {
- padding: 40px;
-}
-
-.pt-40 {
- padding-top: 40px;
-}
-
-.pr-40 {
- padding-right: 40px;
-}
-
-.pb-40 {
- padding-bottom: 40px;
-}
-
-.pl-40 {
- padding-left: 40px;
-}
-
-.p-48 {
- padding: 48px;
-}
-
-.pt-48 {
- padding-top: 48px;
-}
-
-.pr-48 {
- padding-right: 48px;
-}
-
-.pb-48 {
- padding-bottom: 48px;
-}
-
-.pl-48 {
- padding-left: 48px;
-}
-
-.p-56 {
- padding: 56px;
-}
-
-.pt-56 {
- padding-top: 56px;
-}
-
-.pr-56 {
- padding-right: 56px;
-}
-
-.pb-56 {
- padding-bottom: 56px;
-}
-
-.pl-56 {
- padding-left: 56px;
-}
-
-.p-64 {
- padding: 64px;
-}
-
-.pt-64 {
- padding-top: 64px;
-}
-
-.pr-64 {
- padding-right: 64px;
-}
-
-.pb-64 {
- padding-bottom: 64px;
-}
-
-.pl-64 {
- padding-left: 64px;
-}
-
-.sr .has-animations .is-revealing {
- visibility: hidden;
-}
-
-.button {
- display: inline-flex;
- font-size: 14px;
- letter-spacing: 0px;
- font-weight: 700;
- line-height: 16px;
- text-decoration: none !important;
- text-transform: uppercase;
- background-color: #fff;
- background: #fff;
- color: #c3352e !important;
- border: none;
- border-radius: 2px;
- cursor: pointer;
- justify-content: center;
- padding: 16px 40px;
- height: 48px;
- text-align: center;
- white-space: nowrap;
-}
-
-.button:active {
- outline: 0;
-}
-
-.button::before {
- border-radius: 2px;
-}
-
-.button-shadow {
- position: relative;
-}
-
-.button-shadow::before {
- content: "";
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- box-shadow: 0 8px 16px rgba(22, 30, 42, 0.12);
- mix-blend-mode: multiply;
- transition: box-shadow 0.15s ease;
-}
-
-.button-shadow:hover::before {
- box-shadow: 0 8px 16px rgba(22, 30, 42, 0.16);
-}
-
-.button-sm {
- padding: 8px 24px;
- height: 32px;
-}
-
-.button-sm.button-shadow::before {
- box-shadow: 0 4px 16px rgba(22, 30, 42, 0.12);
-}
-
-.button-sm.button-shadow:hover::before {
- box-shadow: 0 4px 16px rgba(22, 30, 42, 0.16);
-}
-
-.button-primary,
-.button-secondary {
- color: #fff !important;
- transition: background 0.15s ease;
-}
-
-.button-primary {
- background: #c3352e;
-}
-
-.button-primary:hover {
- background: #ac362e;
-}
-
-.button-primary.button-shadow::before {
- box-shadow: 0 8px 16px rgba(66, 52, 248, 0.24);
-}
-
-.button-primary.button-shadow:hover::before {
- box-shadow: 0 8px 16px rgba(66, 52, 248, 0.32);
-}
-
-.button-primary .button-sm.button-shadow::before {
- box-shadow: 0 4px 16px rgba(66, 52, 248, 0.24);
-}
-
-.button-primary .button-sm.button-shadow:hover::before {
- box-shadow: 0 4px 16px rgba(66, 52, 248, 0.32);
-}
-
-.button-secondary {
- background: #ff6c50;
-}
-
-.button-secondary:hover {
- background: #ac362e;
-}
-
-.button-secondary.button-shadow::before {
- box-shadow: 0 8px 16px rgba(255, 108, 80, 0.24);
-}
-
-.button-secondary.button-shadow:hover::before {
- box-shadow: 0 8px 16px rgba(255, 108, 80, 0.32);
-}
-
-.button-secondary .button-sm.button-shadow::before {
- box-shadow: 0 4px 16px rgba(255, 108, 80, 0.24);
-}
-
-.button-secondary .button-sm.button-shadow:hover::before {
- box-shadow: 0 4px 16px rgba(255, 108, 80, 0.32);
-}
-
-.button-block {
- display: flex;
- width: 100%;
-}
-
-@media (max-width: 640px) {
- .button-wide-mobile {
- width: 100%;
- max-width: 280px;
- }
-}
-
-.site-header {
- padding: 24px 0;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- z-index: 1;
-}
-
-.site-header-inner {
- position: relative;
- display: flex;
- justify-content: space-between;
- align-items: center;
-}
-
-.header-links {
- display: inline-flex;
-}
-
-.header-links li {
- display: inline-flex;
-}
-
-.header-links a:not(.button) {
- font-size: 16px;
- line-height: 24px;
- letter-spacing: -0.1px;
- font-weight: 600;
- color: #606483;
- text-transform: uppercase;
- text-decoration: none;
- line-height: 16px;
- padding: 8px 24px;
-}
-
-.header-links a:not(.button):hover,
-.header-links a:not(.button):active {
- color: #fff;
-}
-
-.hero {
- position: relative;
- padding-top: 128px;
- padding-bottom: 88px;
- z-index: 0;
-}
-
-.hero .hero-bg {
- position: absolute;
- top: 0;
- bottom: 42%;
- left: 0;
- right: 0;
- background: #363636;
- z-index: -2;
-}
-
-.hero .hero-particles-container {
- position: absolute;
- top: 0;
- bottom: 42%;
- left: 0;
- right: 0;
-}
-
-.hero::before,
-.hero::after {
- content: "";
- position: absolute;
- left: calc(50% - 360px);
- width: 720px;
- background-repeat: no-repeat;
-}
-
-.hero::before {
- top: 0;
- height: 159px;
- background-image: url("../img/bg-top.svg");
- background-size: 720px 159px;
-}
-
-.hero::after {
- bottom: 42%;
- height: 173px;
- background-image: url("../img/bg-bottom.svg");
- background-size: 720px 173px;
-}
-
-.hero-inner {
- position: relative;
- z-index: 1;
-}
-
-.hero-copy {
- position: relative;
- margin-bottom: 48px;
-}
-
-@media (min-width: 641px) {
- .hero {
- padding-top: 160px;
- padding-bottom: 128px;
- }
-
- .hero::before,
- .hero::after {
- left: calc(50% - 720px);
- width: 1440px;
- }
-
- .hero::before {
- height: 318px;
- background-size: 1440px 318px;
- }
-
- .hero::after {
- height: 347px;
- background-size: 1440px 347px;
- }
-
- .hero-copy {
- margin-bottom: 88px;
- }
-
- .hero-paragraph {
- padding-left: 72px;
- padding-right: 72px;
- }
-}
-
-.has-animations .hero .hero-bg,
-.has-animations .hero::before,
-.has-animations .hero::after,
-.has-animations .hero-particles-container,
-.has-animations .site-header,
-.has-animations .hero-title,
-.has-animations .hero-paragraph,
-.has-animations .hero-cta,
-.has-animations .hero .mockup-bg,
-.has-animations .hero .device-mockup {
- opacity: 0;
-}
-
-.has-animations.is-loaded .hero .hero-bg {
- -webkit-animation: heroBg 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards;
- animation: heroBg 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards;
-}
-
-.has-animations.is-loaded .hero::before,
-.has-animations.is-loaded .hero::after {
- -webkit-animation: heroFadeIn 0.6s ease forwards 0.45s;
- animation: heroFadeIn 0.6s ease forwards 0.45s;
-}
-
-.has-animations.is-loaded .site-header,
-.has-animations.is-loaded .hero-particles-container,
-.has-animations.is-loaded .hero .mockup-bg {
- -webkit-animation: heroFadeIn 0.6s ease forwards 0.45s;
- animation: heroFadeIn 0.6s ease forwards 0.45s;
-}
-
-.has-animations.is-loaded .hero-title {
- -webkit-animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.15s;
- animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.15s;
-}
-
-.has-animations.is-loaded .hero-paragraph {
- -webkit-animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.3s;
- animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.3s;
-}
-
-.has-animations.is-loaded .hero-cta {
- -webkit-animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.45s;
- animation: heroContent 0.6s cubic-bezier(0.215, 0.61, 0.355, 1) forwards 0.45s;
-}
-
-.has-animations.is-loaded .hero .device-mockup {
- -webkit-animation: heroMockup 0.6s ease forwards 0.6s;
- animation: heroMockup 0.6s ease forwards 0.6s;
-}
-
-@-webkit-keyframes heroBg {
- from {
- -webkit-transform: scaleY(0) scaleX(1.2) skewY(30deg);
- transform: scaleY(0) scaleX(1.2) skewY(30deg);
- opacity: 1;
- }
- to {
- -webkit-transform: scaleY(1) scaleX(1) skewY(0);
- transform: scaleY(1) scaleX(1) skewY(0);
- opacity: 1;
- }
-}
-
-@keyframes heroBg {
- from {
- -webkit-transform: scaleY(0) scaleX(1.2) skewY(30deg);
- transform: scaleY(0) scaleX(1.2) skewY(30deg);
- opacity: 1;
- }
- to {
- -webkit-transform: scaleY(1) scaleX(1) skewY(0);
- transform: scaleY(1) scaleX(1) skewY(0);
- opacity: 1;
- }
-}
-
-@-webkit-keyframes heroContent {
- from {
- -webkit-transform: translateY(40px) skewY(2deg);
- transform: translateY(40px) skewY(2deg);
- opacity: 0;
- }
- to {
- -webkit-transform: translateY(0) skewY(0);
- transform: translateY(0) skewY(0);
- opacity: 1;
- }
-}
-
-@keyframes heroContent {
- from {
- -webkit-transform: translateY(40px) skewY(2deg);
- transform: translateY(40px) skewY(2deg);
- opacity: 0;
- }
- to {
- -webkit-transform: translateY(0) skewY(0);
- transform: translateY(0) skewY(0);
- opacity: 1;
- }
-}
-
-@-webkit-keyframes heroMockup {
- from {
- -webkit-transform: translateY(80px);
- transform: translateY(80px);
- opacity: 0;
- }
- to {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- opacity: 1;
- }
-}
-
-@keyframes heroMockup {
- from {
- -webkit-transform: translateY(80px);
- transform: translateY(80px);
- opacity: 0;
- }
- to {
- -webkit-transform: translateY(0);
- transform: translateY(0);
- opacity: 1;
- }
-}
-
-@-webkit-keyframes heroFadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-@keyframes heroFadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-.mockup-container {
- position: relative;
-}
-
-#mockup-header-img {
- position: relative;
- height: 100%;
- -moz-box-shadow: 3px 3px 13px #212121;
- -webkit-box-shadow: 3px 3px 13px #212121;
- box-shadow: 3px 3px 13px #212121;
- border-radius: 5px;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
-}
-
-.mockup-bg {
- pointer-events: none;
-}
-
-.mockup-bg img,
-.mockup-bg svg {
- position: absolute;
- top: 50%;
- left: 50%;
- -webkit-transform: translate(-50%, 0%);
- transform: translate(-50%, 0%);
- width: 100%;
- height: auto;
- max-width: 300% !important;
-}
-
-.device-mockup {
- position: relative;
- width: 350px;
- height: auto;
- margin: 0 auto;
- z-index: 1;
-}
-
-.has-animations .features-extended {
- opacity: 0;
-}
-
-.has-animations.is-loaded .features-extended {
- opacity: 1;
- position: relative;
-}
-
-.features-extended-header {
- margin-bottom: 32px;
-}
-
-.features-extended-wrap {
- display: flex;
- flex-wrap: wrap;
- margin-top: -24px;
-}
-
-.features-extended-wrap:last-of-type {
- margin-bottom: -24px;
-}
-
-.features-extended-wrap:not(:last-of-type) {
- margin-bottom: 24px;
-}
-
-.feature-extended {
- padding: 24px 0;
-}
-
-.feature-extended-image {
- position: relative;
- margin-bottom: 32px;
-}
-
-.feature-extended-image img,
-.feature-extended-image svg {
- width: 100%;
- max-width: 200px;
- height: auto;
- margin-left: auto;
- margin-right: auto;
- overflow: visible;
-}
-
-.feature-extended-body {
- text-align: center;
-}
-
-@media (min-width: 641px) {
- .features-extended .container {
- max-width: 912px;
- }
-
- .features-extended .section-inner {
- padding-bottom: 128px;
- }
-
- .features-extended .section-paragraph {
- padding-left: 72px;
- padding-right: 72px;
- margin-bottom: 0;
- }
-
- .features-extended-header {
- margin-bottom: 80px;
- }
-
- .features-extended-wrap {
- margin-top: -64px;
- }
-
- .features-extended-wrap:last-of-type {
- margin-bottom: -64px;
- }
-
- .features-extended-wrap:not(:last-of-type) {
- margin-bottom: 64px;
- }
-
- .feature-extended {
- display: flex;
- flex-wrap: nowrap;
- align-items: stretch;
- justify-content: flex-end;
- padding: 64px 0;
- }
-
- .feature-extended .feature-extended-image {
- width: 440px;
- margin-right: 96px;
- margin-bottom: 0;
- }
-
- .feature-extended .feature-extended-image img,
- .feature-extended .feature-extended-image svg {
- width: auto;
- }
-
- .feature-extended .feature-extended-image img.device-mockup,
- .feature-extended .feature-extended-image svg.device-mockup {
- max-width: 200px;
- }
-
- .feature-extended:nth-child(even) {
- justify-content: flex-start;
- }
-
- .feature-extended:nth-child(even) .feature-extended-image {
- order: 1;
- margin-left: 96px;
- margin-right: 0;
- }
-
- .feature-extended-body {
- display: flex;
- flex-direction: column;
- justify-content: center;
- flex-shrink: 0;
- width: 360px;
- text-align: left;
- }
-}
-
-@media (min-width: 1025px) {
- .features-extended .container {
- max-width: 944px;
- }
-
- .feature-extended .feature-extended-image {
- margin-right: 64px;
- }
-
- .feature-extended:nth-child(even) .feature-extended-image {
- margin-left: 64px;
- }
-
- .feature-extended-body {
- width: 392px;
- }
-}
-
-.cta .section-paragraph {
- margin-bottom: 32px;
-}
-
-@media (min-width: 641px) {
- .cta .section-paragraph {
- margin-bottom: 32px;
- padding-left: 72px;
- padding-right: 72px;
- }
-}
-
-.body-wrap {
- overflow: hidden;
- display: flex;
- flex-direction: column;
- min-height: 100vh;
-}
-
-.boxed-container {
- max-width: 1440px;
- margin: 0 auto;
- box-shadow: 0 20px 48px rgba(22, 30, 42, 0.16);
-}
-
-main {
- flex: 1 0 auto;
-}
-
-.section-inner {
- position: relative;
- padding-top: 48px;
- padding-bottom: 48px;
-}
-
-@media (min-width: 641px) {
- .section-inner {
- padding-top: 88px;
- padding-bottom: 88px;
- }
-}
-
-.site-footer {
- position: relative;
- background: #212121;
-}
-
-.site-footer::before {
- content: "";
- position: absolute;
- top: -76px;
- left: calc(50% - 360px);
- width: 720px;
- height: 291px;
- background-image: url("../img/footer.svg");
- background-size: 720px 291px;
- background-repeat: no-repeat;
-}
-
-.site-footer .footer-particles-container,
-.main-particles-container {
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
-}
-
-.site-footer-bottom {
- font-size: 14px;
- line-height: 22px;
- letter-spacing: 0px;
- z-index: 1;
-}
-
-.site-footer-bottom a {
- color: #606483;
- text-decoration: none;
-}
-
-.site-footer-bottom a:hover,
-.site-footer-bottom a:active {
- text-decoration: underline;
-}
-
-.site-footer-inner {
- position: relative;
- display: flex;
- flex-wrap: wrap;
- padding-top: 48px;
- padding-bottom: 48px;
- position: relative;
-}
-
-.footer-brand,
-.footer-links,
-.footer-social-links,
-.footer-copyright {
- flex: none;
- width: 100%;
- display: inline-flex;
- justify-content: center;
-}
-
-.footer-brand,
-.footer-links,
-.footer-social-links {
- margin-bottom: 24px;
-}
-
-.footer-links li + li,
-.footer-social-links li + li {
- margin-left: 16px;
-}
-
-.footer-social-links li {
- display: inline-flex;
-}
-
-.footer-social-links li a {
- padding: 8px;
-}
-
-@media (min-width: 641px) {
- .site-footer::before {
- top: -152px;
- left: calc(50% - 720px);
- width: 1440px;
- height: 582px;
- background-size: 1440px 582px;
- }
-
- .site-footer-inner {
- justify-content: space-between;
- padding-top: 64px;
- padding-bottom: 64px;
- }
-
- .footer-brand,
- .footer-links,
- .footer-social-links,
- .footer-copyright {
- flex: 50%;
- }
-
- .footer-brand,
- .footer-copyright {
- justify-content: flex-start;
- }
-
- .footer-links,
- .footer-social-links {
- justify-content: flex-end;
- }
-
- .footer-links {
- order: 1;
- margin-bottom: 0;
- }
-}
diff --git a/eslint.config.mjs b/eslint.config.mjs
deleted file mode 100644
index 2586a7811f..0000000000
--- a/eslint.config.mjs
+++ /dev/null
@@ -1,90 +0,0 @@
-//@ts-check
-
-import eslint from '@eslint/js';
-import prettier from 'eslint-plugin-prettier/recommended';
-import solid from 'eslint-plugin-solid/configs/recommended';
-import stylistic from '@stylistic/eslint-plugin';
-import tsEslint from 'typescript-eslint';
-
-import * as importPlugin from 'eslint-plugin-import';
-
-export default tsEslint.config(
- eslint.configs.recommended,
- tsEslint.configs.eslintRecommended,
- ...tsEslint.configs.recommendedTypeChecked,
- prettier,
- solid,
- { ignores: ['dist', 'node_modules', '*.config.*js', '*.test.*js'] },
- {
- plugins: {
- stylistic,
- importPlugin
- },
- languageOptions: {
- parser: tsEslint.parser,
- parserOptions: {
- project: true,
- sourceType: 'module',
- ecmaVersion: 'latest'
- }
- },
- rules: {
- 'stylistic/arrow-parens': ['error', 'always'],
- 'stylistic/object-curly-spacing': ['error', 'always'],
- 'stylistic/jsx-pascal-case': 'error',
- 'stylistic/jsx-curly-spacing': ['error', { when: 'never', children: true }],
- 'stylistic/jsx-sort-props': 'error',
- 'prettier/prettier': ['error', { singleQuote: true, semi: true, tabWidth: 2, trailingComma: 'all', quoteProps: 'preserve' }],
- '@typescript-eslint/no-floating-promises': 'off',
- '@typescript-eslint/no-misused-promises': ['off', { checksVoidReturn: false }],
- '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
- '@typescript-eslint/no-non-null-assertion': 'off',
- '@typescript-eslint/consistent-type-imports': ['error', {
- fixStyle: 'inline-type-imports',
- prefer: 'type-imports',
- disallowTypeAnnotations: false,
- }],
- 'importPlugin/first': 'error',
- 'importPlugin/newline-after-import': 'off',
- 'importPlugin/no-default-export': 'off',
- 'importPlugin/no-duplicates': 'error',
- 'importPlugin/no-unresolved': ['error', { ignore: ['^virtual:', '\\?inline$', '\\?raw$', '\\?asset&asarUnpack'] }],
- 'importPlugin/order': ['error', {
- 'groups': ['builtin', 'external', ['internal', 'index', 'sibling'], 'parent', 'type'],
- 'newlines-between': 'always-and-inside-groups',
- 'alphabetize': { order: 'ignore', caseInsensitive: false }
- }],
- 'importPlugin/prefer-default-export': 'off',
- 'camelcase': ['error', { properties: 'never' }],
- 'class-methods-use-this': 'off',
- 'stylistic/lines-around-comment': ['error', {
- beforeBlockComment: false,
- afterBlockComment: false,
- beforeLineComment: false,
- afterLineComment: false,
- }],
- 'stylistic/max-len': 'off',
- 'stylistic/no-mixed-operators': 'warn', // prettier does not support no-mixed-operators
- 'stylistic/no-multi-spaces': ['error', { ignoreEOLComments: true }],
- 'stylistic/no-tabs': 'error',
- 'no-void': 'error',
- 'no-empty': 'off',
- 'prefer-promise-reject-errors': 'off',
- 'stylistic/quotes': ['error', 'single', {
- avoidEscape: true,
- allowTemplateLiterals: false,
- }],
- 'stylistic/quote-props': ['error', 'consistent'],
- 'stylistic/semi': ['error', 'always'],
- },
- settings: {
- 'import/parsers': {
- '@typescript-eslint/parser': ['.ts']
- },
- 'import/resolver': {
- typescript: {},
- exports: {},
- },
- },
- },
-);
diff --git a/package.json b/package.json
index e209028fd4..0161d7af5f 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,10 @@
"dist:mac:arm64": "pnpm clean && pnpm build && pnpm electron-builder --mac dmg:arm64 -p never",
"dist:win": "pnpm clean && pnpm build && pnpm electron-builder --win -p never",
"dist:win:x64": "pnpm clean && pnpm build && pnpm electron-builder --win nsis-web:x64 -p never",
- "lint": "pnpm eslint ./src",
+ "lint": "pnpm exec biome lint ./src",
+ "lint:fix": "pnpm exec biome lint --write ./src",
+ "format": "pnpm exec biome format ./src",
+ "format:fix": "pnpm exec biome format --write ./src",
"changelog": "pnpm dlx auto-changelog",
"release:linux": "pnpm clean && pnpm build && pnpm electron-builder --linux -p always -c.snap.publish=github",
"release:mac": "pnpm clean && pnpm build && pnpm electron-builder --mac -p always",
@@ -136,11 +139,10 @@
"zod": "4.1.5"
},
"devDependencies": {
+ "@biomejs/biome": "2.2.5",
"@electron-toolkit/tsconfig": "1.0.1",
- "@eslint/js": "9.35.0",
"@malept/flatpak-bundler": "0.4.0",
"@playwright/test": "1.55.0",
- "@stylistic/eslint-plugin": "5.3.1",
"@total-typescript/ts-reset": "0.6.1",
"@types/electron-localshortcut": "3.1.3",
"@types/howler": "2.2.12",
@@ -157,19 +159,11 @@
"electron-builder-squirrel-windows": "26.0.12",
"electron-devtools-installer": "4.0.0",
"electron-vite": "4.0.0",
- "eslint": "9.35.0",
- "eslint-config-prettier": "10.1.8",
- "eslint-import-resolver-exports": "1.0.0-beta.5",
- "eslint-import-resolver-typescript": "4.4.4",
- "eslint-plugin-import": "2.32.0",
- "eslint-plugin-prettier": "5.5.4",
- "eslint-plugin-solid": "0.14.5",
"glob": "11.0.3",
"node-gyp": "11.4.2",
"playwright": "1.55.0",
"ts-morph": "27.0.0",
"typescript": "5.9.2",
- "typescript-eslint": "8.43.0",
"utf-8-validate": "6.0.5",
"vite": "npm:rolldown-vite@7.1.8",
"vite-plugin-inspect": "11.3.3",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 60535de66f..8ec2dda09d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -236,7 +236,7 @@ importers:
version: 1.3.4
virtua:
specifier: 0.42.3
- version: 0.42.3(solid-js@1.9.9)
+ version: 0.42.3(react-dom@18.3.1(react@17.0.2))(react@17.0.2)(solid-js@1.9.9)
vudio:
specifier: 2.1.1
version: 2.1.1(patch_hash=0e06c2ed11c02bdc490c209fa80070e98517c2735c641f5738b6e15d7dc1959d)
@@ -250,18 +250,15 @@ importers:
specifier: 4.1.5
version: 4.1.5
devDependencies:
- '@eslint/js':
- specifier: 9.35.0
- version: 9.35.0
+ '@biomejs/biome':
+ specifier: 2.2.5
+ version: 2.2.5
'@malept/flatpak-bundler':
specifier: 0.4.0
version: 0.4.0(patch_hash=c787371eeb2af011ea934e8818a0dad6d7dcb2df31bbb1686babc7231af0183c)
'@playwright/test':
specifier: 1.55.0
version: 1.55.0
- '@stylistic/eslint-plugin':
- specifier: 5.3.1
- version: 5.3.1(eslint@9.35.0)
'@total-typescript/ts-reset':
specifier: 0.6.1
version: 0.6.1
@@ -310,27 +307,6 @@ importers:
electron-vite:
specifier: 4.0.0
version: 4.0.0(rolldown-vite@7.1.8(@types/node@24.3.0)(esbuild@0.25.9)(yaml@2.8.1))
- eslint:
- specifier: 9.35.0
- version: 9.35.0
- eslint-config-prettier:
- specifier: 10.1.8
- version: 10.1.8(eslint@9.35.0)
- eslint-import-resolver-exports:
- specifier: 1.0.0-beta.5
- version: 1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.35.0)
- eslint-import-resolver-typescript:
- specifier: 4.4.4
- version: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.35.0)
- eslint-plugin-import:
- specifier: 2.32.0
- version: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0)
- eslint-plugin-prettier:
- specifier: 5.5.4
- version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.35.0))(eslint@9.35.0)(prettier@3.6.2)
- eslint-plugin-solid:
- specifier: 0.14.5
- version: 0.14.5(eslint@9.35.0)(typescript@5.9.2)
glob:
specifier: 11.0.3
version: 11.0.3
@@ -346,9 +322,6 @@ importers:
typescript:
specifier: 5.9.2
version: 5.9.2
- typescript-eslint:
- specifier: 8.43.0
- version: 8.43.0(eslint@9.35.0)(typescript@5.9.2)
utf-8-validate:
specifier: 6.0.5
version: 6.0.5
@@ -476,6 +449,59 @@ packages:
resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==}
engines: {node: '>=6.9.0'}
+ '@biomejs/biome@2.2.5':
+ resolution: {integrity: sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw==}
+ engines: {node: '>=14.21.3'}
+ hasBin: true
+
+ '@biomejs/cli-darwin-arm64@2.2.5':
+ resolution: {integrity: sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@biomejs/cli-darwin-x64@2.2.5':
+ resolution: {integrity: sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@biomejs/cli-linux-arm64-musl@2.2.5':
+ resolution: {integrity: sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-arm64@2.2.5':
+ resolution: {integrity: sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64-musl@2.2.5':
+ resolution: {integrity: sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-linux-x64@2.2.5':
+ resolution: {integrity: sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [linux]
+
+ '@biomejs/cli-win32-arm64@2.2.5':
+ resolution: {integrity: sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg==}
+ engines: {node: '>=14.21.3'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@biomejs/cli-win32-x64@2.2.5':
+ resolution: {integrity: sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw==}
+ engines: {node: '>=14.21.3'}
+ cpu: [x64]
+ os: [win32]
+
'@bufbuild/protobuf@2.6.3':
resolution: {integrity: sha512-w/gJKME9mYN7ZoUAmSMAWXk4hkVpxRKvEJCb3dV5g9wwWdxTJJ0ayOJAVcNxtdqaxDyFuC0uz4RSGVacJ030PQ==}
@@ -728,44 +754,6 @@ packages:
cpu: [x64]
os: [win32]
- '@eslint-community/eslint-utils@4.8.0':
- resolution: {integrity: sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
-
- '@eslint-community/regexpp@4.12.1':
- resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==}
- engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
-
- '@eslint/config-array@0.21.0':
- resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/config-helpers@0.3.1':
- resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/core@0.15.2':
- resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/eslintrc@3.3.1':
- resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/js@9.35.0':
- resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/object-schema@2.1.6':
- resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@eslint/plugin-kit@0.3.5':
- resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
'@ffmpeg.wasm/core-mt@0.12.0':
resolution: {integrity: sha512-M9pjL7JQX4AYl3WI8vGcPGPTz/O7JmhW8ac/fHA3oXTxoRAPwYSY/OsY1N9C0XahIM0+fxa1QSLN9Ekz8sBM/Q==}
@@ -841,26 +829,6 @@ packages:
hono: '>=3.9.0'
zod: ^3.25.0 || ^4.0.0
- '@humanfs/core@0.19.1':
- resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
- engines: {node: '>=18.18.0'}
-
- '@humanfs/node@0.16.6':
- resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==}
- engines: {node: '>=18.18.0'}
-
- '@humanwhocodes/module-importer@1.0.1':
- resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
- engines: {node: '>=12.22'}
-
- '@humanwhocodes/retry@0.3.1':
- resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==}
- engines: {node: '>=18.18'}
-
- '@humanwhocodes/retry@0.4.3':
- resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
- engines: {node: '>=18.18'}
-
'@isaacs/balanced-match@4.0.1':
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
engines: {node: 20 || >=22}
@@ -1023,9 +991,6 @@ packages:
resolution: {integrity: sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==}
engines: {node: '>= 10'}
- '@napi-rs/wasm-runtime@0.2.12':
- resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
-
'@napi-rs/wasm-runtime@1.0.3':
resolution: {integrity: sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==}
@@ -1073,10 +1038,6 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
- '@pkgr/core@0.2.9':
- resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
-
'@playwright/test@1.55.0':
resolution: {integrity: sha512-04IXzPwHrW69XusN/SIdDdKZBzMfOT9UNT/YiJit/xpy2VuAoB8NHc8Aplb96zsWDddLnbkPL3TsmrS04ZU2xQ==}
engines: {node: '>=18'}
@@ -1189,9 +1150,6 @@ packages:
'@rolldown/pluginutils@1.0.0-beta.36':
resolution: {integrity: sha512-qa+gfzhv0/Xv52zZInENLu6JbsnSjSExD7kTaNm7Qn5LUIH6IQb7l9pB+NrsU5/Bvt9aqcBTdRGc7x1DYMTiqQ==}
- '@rtsao/scc@1.1.0':
- resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
-
'@sapphire/async-queue@1.5.5':
resolution: {integrity: sha512-cvGzxbba6sav2zZkH8GPf2oGk9yYoD5qrNWdu9fRehifgnFZJMV+nuy2nON2roRO4yQQ+v7MK/Pktl/HgfsUXg==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
@@ -1230,12 +1188,6 @@ packages:
peerDependencies:
solid-js: ^1.6.12
- '@stylistic/eslint-plugin@5.3.1':
- resolution: {integrity: sha512-Ykums1VYonM0TgkD0VteVq9mrlO2FhF48MDJnPyv3MktIB2ydtuhlO0AfWm7xnW1kyf5bjOqA6xc7JjviuVTxg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: '>=9.0.0'
-
'@szmarczak/http-timer@4.0.6':
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
engines: {node: '>=10'}
@@ -1277,9 +1229,6 @@ packages:
'@types/electron-localshortcut@3.1.3':
resolution: {integrity: sha512-D+CRdDTRZ4/9UmcSaZ5qvW4uq2VyyVmqsH9cdNReB4CL6MSIgyhr9w2PKeNEb0J/ZS7db7irJM/+ZiA5uSQsLw==}
- '@types/estree@1.0.8':
- resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
-
'@types/fs-extra@9.0.13':
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
@@ -1292,12 +1241,6 @@ packages:
'@types/http-cache-semantics@4.0.4':
resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==}
- '@types/json-schema@7.0.15':
- resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
-
- '@types/json5@0.0.29':
- resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
-
'@types/keyv@3.1.4':
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
@@ -1337,197 +1280,6 @@ packages:
'@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
- '@typescript-eslint/eslint-plugin@8.43.0':
- resolution: {integrity: sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- '@typescript-eslint/parser': ^8.43.0
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/parser@8.43.0':
- resolution: {integrity: sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/project-service@8.42.0':
- resolution: {integrity: sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/project-service@8.43.0':
- resolution: {integrity: sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/scope-manager@8.42.0':
- resolution: {integrity: sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/scope-manager@8.43.0':
- resolution: {integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/tsconfig-utils@8.42.0':
- resolution: {integrity: sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/tsconfig-utils@8.43.0':
- resolution: {integrity: sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/type-utils@8.43.0':
- resolution: {integrity: sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/types@8.42.0':
- resolution: {integrity: sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/types@8.43.0':
- resolution: {integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/typescript-estree@8.42.0':
- resolution: {integrity: sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/typescript-estree@8.43.0':
- resolution: {integrity: sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/utils@8.42.0':
- resolution: {integrity: sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/utils@8.43.0':
- resolution: {integrity: sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
- '@typescript-eslint/visitor-keys@8.42.0':
- resolution: {integrity: sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@typescript-eslint/visitor-keys@8.43.0':
- resolution: {integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- '@unrs/resolver-binding-android-arm-eabi@1.11.1':
- resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
- cpu: [arm]
- os: [android]
-
- '@unrs/resolver-binding-android-arm64@1.11.1':
- resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
- cpu: [arm64]
- os: [android]
-
- '@unrs/resolver-binding-darwin-arm64@1.11.1':
- resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
- cpu: [arm64]
- os: [darwin]
-
- '@unrs/resolver-binding-darwin-x64@1.11.1':
- resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
- cpu: [x64]
- os: [darwin]
-
- '@unrs/resolver-binding-freebsd-x64@1.11.1':
- resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
- cpu: [x64]
- os: [freebsd]
-
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
- resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
- cpu: [arm]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
- resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
- cpu: [arm]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
- resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
- cpu: [arm64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
- resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
- cpu: [arm64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
- resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
- cpu: [ppc64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
- resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
- cpu: [riscv64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
- resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
- cpu: [riscv64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
- resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
- cpu: [s390x]
- os: [linux]
-
- '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
- resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
- cpu: [x64]
- os: [linux]
-
- '@unrs/resolver-binding-linux-x64-musl@1.11.1':
- resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
- cpu: [x64]
- os: [linux]
-
- '@unrs/resolver-binding-wasm32-wasi@1.11.1':
- resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
- engines: {node: '>=14.0.0'}
- cpu: [wasm32]
-
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
- resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
- cpu: [arm64]
- os: [win32]
-
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
- resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
- cpu: [ia32]
- os: [win32]
-
- '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
- resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
- cpu: [x64]
- os: [win32]
-
'@vladfrangu/async_event_emitter@2.4.6':
resolution: {integrity: sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA==}
engines: {node: '>=v14.0.0', npm: '>=7.0.0'}
@@ -1554,11 +1306,6 @@ packages:
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
engines: {node: '>=6.5'}
- acorn-jsx@5.3.2:
- resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
- peerDependencies:
- acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
-
acorn@8.15.0:
resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
engines: {node: '>=0.4.0'}
@@ -1651,26 +1398,6 @@ packages:
resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
engines: {node: '>= 0.4'}
- array-includes@3.1.9:
- resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
- engines: {node: '>= 0.4'}
-
- array.prototype.findlastindex@1.2.6:
- resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
- engines: {node: '>= 0.4'}
-
- array.prototype.flat@1.3.3:
- resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
- engines: {node: '>= 0.4'}
-
- array.prototype.flatmap@1.3.3:
- resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
- engines: {node: '>= 0.4'}
-
- arraybuffer.prototype.slice@1.0.4:
- resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
- engines: {node: '>= 0.4'}
-
assert-plus@1.0.0:
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
engines: {node: '>=0.8'}
@@ -1683,10 +1410,6 @@ packages:
resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
engines: {node: '>=0.12.0'}
- async-function@1.0.0:
- resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
- engines: {node: '>= 0.4'}
-
async-mutex@0.5.0:
resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==}
@@ -1852,10 +1575,6 @@ packages:
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
engines: {node: '>= 0.4'}
- callsites@3.1.0:
- resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
- engines: {node: '>=6'}
-
camelcase@7.0.1:
resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==}
engines: {node: '>=14.16'}
@@ -2043,18 +1762,6 @@ packages:
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
engines: {node: '>= 12'}
- data-view-buffer@1.0.2:
- resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
- engines: {node: '>= 0.4'}
-
- data-view-byte-length@1.0.2:
- resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
- engines: {node: '>= 0.4'}
-
- data-view-byte-offset@1.0.1:
- resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
- engines: {node: '>= 0.4'}
-
debounce-fn@6.0.0:
resolution: {integrity: sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==}
engines: {node: '>=18'}
@@ -2067,14 +1774,6 @@ packages:
supports-color:
optional: true
- debug@3.2.7:
- resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
debug@4.4.1:
resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==}
engines: {node: '>=6.0'}
@@ -2096,9 +1795,6 @@ packages:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
- deep-is@0.1.4:
- resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
-
deepmerge-ts@7.1.5:
resolution: {integrity: sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw==}
engines: {node: '>=16.0.0'}
@@ -2173,10 +1869,6 @@ packages:
os: [darwin]
hasBin: true
- doctrine@2.1.0:
- resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
- engines: {node: '>=0.10.0'}
-
dom-serializer@2.0.0:
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
@@ -2332,10 +2024,6 @@ packages:
error-stack-parser-es@1.0.5:
resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
- es-abstract@1.24.0:
- resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==}
- engines: {node: '>= 0.4'}
-
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
@@ -2358,14 +2046,6 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
- es-shim-unscopables@1.1.0:
- resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
- engines: {node: '>= 0.4'}
-
- es-to-primitive@1.3.0:
- resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
- engines: {node: '>= 0.4'}
-
es6-error@4.1.1:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
@@ -2386,137 +2066,6 @@ packages:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
- eslint-config-prettier@10.1.8:
- resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==}
- hasBin: true
- peerDependencies:
- eslint: '>=7.0.0'
-
- eslint-import-context@0.1.9:
- resolution: {integrity: sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- peerDependencies:
- unrs-resolver: ^1.0.0
- peerDependenciesMeta:
- unrs-resolver:
- optional: true
-
- eslint-import-resolver-exports@1.0.0-beta.5:
- resolution: {integrity: sha512-o6t0w7muUpXr7MkUVzD5igQoDfAQvTmcPp8HEAJdNF8eOuAO+yn6I/TTyMxz9ecCwzX7e02vzlkHURoScUuidg==}
- peerDependencies:
- eslint: '*'
- eslint-plugin-import: '*'
-
- eslint-import-resolver-node@0.3.9:
- resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
-
- eslint-import-resolver-typescript@4.4.4:
- resolution: {integrity: sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==}
- engines: {node: ^16.17.0 || >=18.6.0}
- peerDependencies:
- eslint: '*'
- eslint-plugin-import: '*'
- eslint-plugin-import-x: '*'
- peerDependenciesMeta:
- eslint-plugin-import:
- optional: true
- eslint-plugin-import-x:
- optional: true
-
- eslint-module-utils@2.12.1:
- resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: '*'
- eslint-import-resolver-node: '*'
- eslint-import-resolver-typescript: '*'
- eslint-import-resolver-webpack: '*'
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- eslint:
- optional: true
- eslint-import-resolver-node:
- optional: true
- eslint-import-resolver-typescript:
- optional: true
- eslint-import-resolver-webpack:
- optional: true
-
- eslint-plugin-import@2.32.0:
- resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
-
- eslint-plugin-prettier@5.5.4:
- resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==}
- engines: {node: ^14.18.0 || >=16.0.0}
- peerDependencies:
- '@types/eslint': '>=8.0.0'
- eslint: '>=8.0.0'
- eslint-config-prettier: '>= 7.0.0 <10.0.0 || >=10.1.0'
- prettier: '>=3.0.0'
- peerDependenciesMeta:
- '@types/eslint':
- optional: true
- eslint-config-prettier:
- optional: true
-
- eslint-plugin-solid@0.14.5:
- resolution: {integrity: sha512-nfuYK09ah5aJG/oEN6P1qziy1zLgW4PDWe75VNPi4CEFYk1x2AEqwFeQfEPR7gNn0F2jOeqKhx2E+5oNCOBYWQ==}
- engines: {node: '>=18.0.0'}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
- typescript: '>=4.8.4'
-
- eslint-scope@8.4.0:
- resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint-visitor-keys@3.4.3:
- resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
-
- eslint-visitor-keys@4.2.1:
- resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- eslint@9.35.0:
- resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- hasBin: true
- peerDependencies:
- jiti: '*'
- peerDependenciesMeta:
- jiti:
- optional: true
-
- espree@10.4.0:
- resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
- esquery@1.6.0:
- resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
- engines: {node: '>=0.10'}
-
- esrecurse@4.3.0:
- resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
- engines: {node: '>=4.0'}
-
- estraverse@5.3.0:
- resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
- engines: {node: '>=4.0'}
-
- esutils@2.0.3:
- resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
- engines: {node: '>=0.10.0'}
-
event-stream@4.0.1:
resolution: {integrity: sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==}
@@ -2560,9 +2109,6 @@ packages:
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
- fast-diff@1.3.0:
- resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
-
fast-equals@5.2.2:
resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==}
engines: {node: '>=6.0.0'}
@@ -2574,9 +2120,6 @@ packages:
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
- fast-levenshtein@2.0.6:
- resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
-
fast-uri@3.0.6:
resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==}
@@ -2602,10 +2145,6 @@ packages:
fflate@0.8.2:
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
- file-entry-cache@8.0.0:
- resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
- engines: {node: '>=16.0.0'}
-
file-type@16.5.4:
resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==}
engines: {node: '>=10'}
@@ -2625,17 +2164,6 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
- find-up@5.0.0:
- resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
- engines: {node: '>=10'}
-
- flat-cache@4.0.1:
- resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
- engines: {node: '>=16'}
-
- flatted@3.3.3:
- resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
-
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
@@ -2699,10 +2227,6 @@ packages:
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
- function.prototype.name@1.1.8:
- resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
- engines: {node: '>= 0.4'}
-
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
@@ -2730,13 +2254,6 @@ packages:
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
engines: {node: '>=10'}
- get-symbol-description@1.1.0:
- resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
- engines: {node: '>= 0.4'}
-
- get-tsconfig@4.10.1:
- resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==}
-
gifwrap@0.10.1:
resolution: {integrity: sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==}
@@ -2744,10 +2261,6 @@ packages:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
- glob-parent@6.0.2:
- resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
- engines: {node: '>=10.13.0'}
-
glob@10.4.5:
resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==}
hasBin: true
@@ -2770,10 +2283,6 @@ packages:
resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
engines: {node: '>=10.0'}
- globals@14.0.0:
- resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
- engines: {node: '>=18'}
-
globalthis@1.0.4:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
@@ -2798,9 +2307,6 @@ packages:
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
- graphemer@1.4.0:
- resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
-
hanja@1.1.5:
resolution: {integrity: sha512-gKNEkX+IIBmxXUIm5Lf859YlvHnGD01kbiHL+7CoV1ZxGI+EttflD1k/Ntz8zbymMVIlVELunTk8pK5SNYOVlg==}
@@ -2819,10 +2325,6 @@ packages:
has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
- has-proto@1.2.0:
- resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
- engines: {node: '>= 0.4'}
-
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
@@ -2853,10 +2355,6 @@ packages:
html-entities@2.3.3:
resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==}
- html-tags@3.3.1:
- resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
- engines: {node: '>=8'}
-
html-to-text@9.0.5:
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
engines: {node: '>=14'}
@@ -2918,10 +2416,6 @@ packages:
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
- ignore@5.3.2:
- resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
- engines: {node: '>= 4'}
-
ignore@7.0.5:
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
@@ -2932,10 +2426,6 @@ packages:
immediate@3.0.6:
resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==}
- import-fresh@3.3.1:
- resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
- engines: {node: '>=6'}
-
imurmurhash@0.1.4:
resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
engines: {node: '>=0.8.19'}
@@ -2957,9 +2447,6 @@ packages:
ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
- inline-style-parser@0.2.4:
- resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
-
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
@@ -2976,10 +2463,6 @@ packages:
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
engines: {node: '>= 0.4'}
- is-async-function@2.1.1:
- resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
- engines: {node: '>= 0.4'}
-
is-bigint@1.1.0:
resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
engines: {node: '>= 0.4'}
@@ -2988,9 +2471,6 @@ packages:
resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
engines: {node: '>= 0.4'}
- is-bun-module@2.0.0:
- resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
-
is-callable@1.2.7:
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
engines: {node: '>= 0.4'}
@@ -2999,14 +2479,6 @@ packages:
resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
hasBin: true
- is-core-module@2.16.1:
- resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
- engines: {node: '>= 0.4'}
-
- is-data-view@1.0.2:
- resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
- engines: {node: '>= 0.4'}
-
is-date-object@1.1.0:
resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
engines: {node: '>= 0.4'}
@@ -3025,26 +2497,14 @@ packages:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
- is-finalizationregistry@1.1.1:
- resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
- engines: {node: '>= 0.4'}
-
is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
- is-generator-function@1.1.0:
- resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==}
- engines: {node: '>= 0.4'}
-
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
- is-html@2.0.0:
- resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==}
- engines: {node: '>=8'}
-
is-inside-container@1.0.0:
resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
engines: {node: '>=14.16'}
@@ -3061,10 +2521,6 @@ packages:
resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
engines: {node: '>= 0.4'}
- is-negative-zero@2.0.3:
- resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
- engines: {node: '>= 0.4'}
-
is-number-object@1.1.1:
resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
engines: {node: '>= 0.4'}
@@ -3109,10 +2565,6 @@ packages:
resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
engines: {node: '>= 0.4'}
- is-typed-array@1.1.15:
- resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
- engines: {node: '>= 0.4'}
-
is-unicode-supported@0.1.0:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'}
@@ -3124,10 +2576,6 @@ packages:
resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
engines: {node: '>= 0.4'}
- is-weakref@1.1.1:
- resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
- engines: {node: '>= 0.4'}
-
is-weakset@2.0.4:
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
engines: {node: '>= 0.4'}
@@ -3214,16 +2662,9 @@ packages:
json-schema-typed@8.0.1:
resolution: {integrity: sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==}
- json-stable-stringify-without-jsonify@1.0.1:
- resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
-
json-stringify-safe@5.0.1:
resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
- json5@1.0.2:
- resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
- hasBin: true
-
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
@@ -3238,9 +2679,6 @@ packages:
jszip@3.10.1:
resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==}
- kebab-case@1.0.2:
- resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==}
-
keyboardevent-from-electron-accelerator@2.0.0:
resolution: {integrity: sha512-iQcmNA0M4ETMNi0kG/q0h/43wZk7rMeKYrXP7sqKIJbHkTU8Koowgzv+ieR/vWJbOwxx5nDC3UnudZ0aLSu4VA==}
@@ -3250,9 +2688,6 @@ packages:
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
- known-css-properties@0.30.0:
- resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==}
-
kuromoji@0.1.2:
resolution: {integrity: sha512-V0dUf+C2LpcPEXhoHLMAop/bOht16Dyr+mDiIE39yX3vqau7p80De/koFqpiTcL1zzdZlc3xuHZ8u5gjYRfFaQ==}
@@ -3272,10 +2707,6 @@ packages:
leac@0.6.0:
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
- levn@0.4.1:
- resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
- engines: {node: '>= 0.8.0'}
-
lib-esm@0.4.2:
resolution: {integrity: sha512-VGqaEGuryUbT7FLGxXg46nrSzkhLzyk+JQjYoYEORH5UtdIu3yf6DCOqh65FOR3bWOHHGINQH/vR5YGGIFBgJw==}
@@ -3346,10 +2777,6 @@ packages:
resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
engines: {node: '>= 12.0.0'}
- locate-path@6.0.0:
- resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
- engines: {node: '>=10'}
-
lodash.debounce@4.0.8:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
@@ -3360,9 +2787,6 @@ packages:
resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead.
- lodash.merge@4.6.2:
- resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
-
lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
@@ -3373,6 +2797,10 @@ packages:
long@4.0.0:
resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
lowercase-keys@2.0.0:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'}
@@ -3580,14 +3008,6 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
- napi-postinstall@0.3.3:
- resolution: {integrity: sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow==}
- engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
- hasBin: true
-
- natural-compare@1.4.0:
- resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
-
negotiator@0.6.4:
resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==}
engines: {node: '>= 0.6'}
@@ -3654,6 +3074,10 @@ packages:
nth-check@2.1.1:
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -3670,18 +3094,6 @@ packages:
resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
engines: {node: '>= 0.4'}
- object.fromentries@2.0.8:
- resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
- engines: {node: '>= 0.4'}
-
- object.groupby@1.0.3:
- resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
- engines: {node: '>= 0.4'}
-
- object.values@1.2.1:
- resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
- engines: {node: '>= 0.4'}
-
ohash@2.0.11:
resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==}
@@ -3706,10 +3118,6 @@ packages:
openapi3-ts@4.5.0:
resolution: {integrity: sha512-jaL+HgTq2Gj5jRcfdutgRGLosCy/hT8sQf6VOy+P+g36cZOjI1iukdPnijC+4CmeRzg/jEllJUboEic2FhxhtQ==}
- optionator@0.9.4:
- resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
- engines: {node: '>= 0.8.0'}
-
ora@5.4.1:
resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
engines: {node: '>=10'}
@@ -3718,10 +3126,6 @@ packages:
resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==}
engines: {node: '>=0.10.0'}
- own-keys@1.0.1:
- resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
- engines: {node: '>= 0.4'}
-
p-cancelable@2.1.1:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
@@ -3730,10 +3134,6 @@ packages:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
- p-locate@5.0.0:
- resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
- engines: {node: '>=10'}
-
p-map@4.0.0:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
@@ -3748,10 +3148,6 @@ packages:
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
- parent-module@1.0.1:
- resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
- engines: {node: '>=6'}
-
parse-bmfont-ascii@1.0.6:
resolution: {integrity: sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==}
@@ -3770,10 +3166,6 @@ packages:
path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
- path-exists@4.0.0:
- resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
- engines: {node: '>=8'}
-
path-is-absolute@1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
@@ -3785,9 +3177,6 @@ packages:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
- path-parse@1.0.7:
- resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
-
path-scurry@1.11.1:
resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
engines: {node: '>=16 || 14 >=14.18'}
@@ -3884,19 +3273,6 @@ packages:
engines: {node: '>=14.0.0'}
hasBin: true
- prelude-ls@1.2.1:
- resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
- engines: {node: '>= 0.8.0'}
-
- prettier-linter-helpers@1.0.0:
- resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==}
- engines: {node: '>=6.0.0'}
-
- prettier@3.6.2:
- resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
- engines: {node: '>=14'}
- hasBin: true
-
proc-log@2.0.1:
resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
@@ -3950,6 +3326,15 @@ packages:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
+ react-dom@18.3.1:
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+
+ react@17.0.2:
+ resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==}
+ engines: {node: '>=0.10.0'}
+
read-binary-file-arch@1.0.6:
resolution: {integrity: sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==}
hasBin: true
@@ -3969,10 +3354,6 @@ packages:
resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==}
engines: {node: '>=8'}
- reflect.getprototypeof@1.0.10:
- resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
- engines: {node: '>= 0.4'}
-
regenerator-runtime@0.13.11:
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
@@ -4002,22 +3383,6 @@ packages:
resolve-alpn@1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
- resolve-from@4.0.0:
- resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
- engines: {node: '>=4'}
-
- resolve-pkg-maps@1.0.0:
- resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
-
- resolve.exports@2.0.3:
- resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==}
- engines: {node: '>=10'}
-
- resolve@1.22.10:
- resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==}
- engines: {node: '>= 0.4'}
- hasBin: true
-
responselike@2.0.1:
resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==}
@@ -4099,20 +3464,12 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
- safe-array-concat@1.1.3:
- resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
- engines: {node: '>=0.4'}
-
safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
- safe-push-apply@1.0.0:
- resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
- engines: {node: '>= 0.4'}
-
safe-regex-test@1.1.0:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
@@ -4126,6 +3483,9 @@ packages:
sax@1.4.1:
resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==}
+ scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+
sdp@3.2.1:
resolution: {integrity: sha512-lwsAIzOPlH8/7IIjjz3K0zYBk7aBVVcvjMwt3M4fLxpjMYyy7i3I97SLHebgn4YBjirkzfp3RvRDWSKsh/+WFw==}
@@ -4182,10 +3542,6 @@ packages:
resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
engines: {node: '>= 0.4'}
- set-proto@1.0.0:
- resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
- engines: {node: '>= 0.4'}
-
setimmediate@1.0.5:
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
@@ -4317,10 +3673,6 @@ packages:
resolution: {integrity: sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
- stable-hash-x@0.2.0:
- resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
- engines: {node: '>=12.0.0'}
-
stat-mode@1.0.0:
resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==}
engines: {node: '>= 6'}
@@ -4340,18 +3692,6 @@ packages:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
- string.prototype.trim@1.2.10:
- resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimend@1.0.9:
- resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
- engines: {node: '>= 0.4'}
-
- string.prototype.trimstart@1.0.8:
- resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
- engines: {node: '>= 0.4'}
-
string_decoder@1.1.1:
resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
@@ -4366,10 +3706,6 @@ packages:
resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
engines: {node: '>=12'}
- strip-bom@3.0.0:
- resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
- engines: {node: '>=4'}
-
strip-final-newline@2.0.0:
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
engines: {node: '>=6'}
@@ -4378,10 +3714,6 @@ packages:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
- strip-json-comments@3.1.1:
- resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
- engines: {node: '>=8'}
-
strtok3@6.3.0:
resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==}
engines: {node: '>=10'}
@@ -4389,9 +3721,6 @@ packages:
stubborn-fs@1.2.5:
resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==}
- style-to-object@1.0.9:
- resolution: {integrity: sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==}
-
sumchecker@3.0.1:
resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
engines: {node: '>= 8.0'}
@@ -4400,14 +3729,6 @@ packages:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
- supports-preserve-symlinks-flag@1.0.0:
- resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
- engines: {node: '>= 0.4'}
-
- synckit@0.11.11:
- resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==}
- engines: {node: ^14.18.0 || >=16.0.0}
-
tar@6.2.1:
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
engines: {node: '>=10'}
@@ -4479,25 +3800,12 @@ packages:
truncate-utf8-bytes@1.0.2:
resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
- ts-api-utils@2.1.0:
- resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==}
- engines: {node: '>=18.12'}
- peerDependencies:
- typescript: '>=4.8.4'
-
ts-morph@27.0.0:
resolution: {integrity: sha512-xcqelpTR5PCuZMs54qp9DE3t7tPgA2v/P1/qdW4ke5b3Y5liTGTYj6a/twT35EQW/H5okRqp1UOqwNlgg0K0eQ==}
- tsconfig-paths@3.15.0:
- resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
-
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
- type-check@0.4.0:
- resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
- engines: {node: '>= 0.8.0'}
-
type-fest@0.13.1:
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
engines: {node: '>=10'}
@@ -4510,29 +3818,6 @@ packages:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
- typed-array-buffer@1.0.3:
- resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-length@1.0.3:
- resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
- engines: {node: '>= 0.4'}
-
- typed-array-byte-offset@1.0.4:
- resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
- engines: {node: '>= 0.4'}
-
- typed-array-length@1.0.7:
- resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
- engines: {node: '>= 0.4'}
-
- typescript-eslint@8.43.0:
- resolution: {integrity: sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- peerDependencies:
- eslint: ^8.57.0 || ^9.0.0
- typescript: '>=4.8.4 <6.0.0'
-
typescript@5.9.2:
resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
engines: {node: '>=14.17'}
@@ -4542,10 +3827,6 @@ packages:
resolution: {integrity: sha512-+NWHrac9dvilNgme+gP4YrBSumsaMZP0fNBtXXFIf33RLLKEcBUKaQZ7ULUbS0sBfcjxIZ4V96OTRkCbM7hxpw==}
engines: {node: '>=18'}
- unbox-primitive@1.1.0:
- resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
- engines: {node: '>= 0.4'}
-
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
@@ -4588,9 +3869,6 @@ packages:
resolution: {integrity: sha512-JLoggz+PvLVMJo+jZt97hdIIIZ2yTzGgft9e9q8iMrC4ewufl62ekeW7mixBghonn2gVb/ICjyvlmOCUBnJLQg==}
engines: {node: '>=20.19.0'}
- unrs-resolver@1.11.1:
- resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
-
unzip-crx-3@0.2.0:
resolution: {integrity: sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==}
@@ -4720,10 +3998,6 @@ packages:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
- which-builtin-type@1.2.1:
- resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
- engines: {node: '>= 0.4'}
-
which-collection@1.0.2:
resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
engines: {node: '>= 0.4'}
@@ -4746,10 +4020,6 @@ packages:
resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==}
engines: {node: '>=12'}
- word-wrap@1.2.5:
- resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
- engines: {node: '>=0.10.0'}
-
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -4978,6 +4248,41 @@ snapshots:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.27.1
+ '@biomejs/biome@2.2.5':
+ optionalDependencies:
+ '@biomejs/cli-darwin-arm64': 2.2.5
+ '@biomejs/cli-darwin-x64': 2.2.5
+ '@biomejs/cli-linux-arm64': 2.2.5
+ '@biomejs/cli-linux-arm64-musl': 2.2.5
+ '@biomejs/cli-linux-x64': 2.2.5
+ '@biomejs/cli-linux-x64-musl': 2.2.5
+ '@biomejs/cli-win32-arm64': 2.2.5
+ '@biomejs/cli-win32-x64': 2.2.5
+
+ '@biomejs/cli-darwin-arm64@2.2.5':
+ optional: true
+
+ '@biomejs/cli-darwin-x64@2.2.5':
+ optional: true
+
+ '@biomejs/cli-linux-arm64-musl@2.2.5':
+ optional: true
+
+ '@biomejs/cli-linux-arm64@2.2.5':
+ optional: true
+
+ '@biomejs/cli-linux-x64-musl@2.2.5':
+ optional: true
+
+ '@biomejs/cli-linux-x64@2.2.5':
+ optional: true
+
+ '@biomejs/cli-win32-arm64@2.2.5':
+ optional: true
+
+ '@biomejs/cli-win32-x64@2.2.5':
+ optional: true
+
'@bufbuild/protobuf@2.6.3': {}
'@dehoist/romanize-thai@1.0.0': {}
@@ -5222,50 +4527,6 @@ snapshots:
'@esbuild/win32-x64@0.25.9':
optional: true
- '@eslint-community/eslint-utils@4.8.0(eslint@9.35.0)':
- dependencies:
- eslint: 9.35.0
- eslint-visitor-keys: 3.4.3
-
- '@eslint-community/regexpp@4.12.1': {}
-
- '@eslint/config-array@0.21.0':
- dependencies:
- '@eslint/object-schema': 2.1.6
- debug: 4.4.1
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/config-helpers@0.3.1': {}
-
- '@eslint/core@0.15.2':
- dependencies:
- '@types/json-schema': 7.0.15
-
- '@eslint/eslintrc@3.3.1':
- dependencies:
- ajv: 6.12.6
- debug: 4.4.1
- espree: 10.4.0
- globals: 14.0.0
- ignore: 5.3.2
- import-fresh: 3.3.1
- js-yaml: 4.1.0
- minimatch: 3.1.2
- strip-json-comments: 3.1.1
- transitivePeerDependencies:
- - supports-color
-
- '@eslint/js@9.35.0': {}
-
- '@eslint/object-schema@2.1.6': {}
-
- '@eslint/plugin-kit@0.3.5':
- dependencies:
- '@eslint/core': 0.15.2
- levn: 0.4.1
-
'@ffmpeg.wasm/core-mt@0.12.0': {}
'@ffmpeg.wasm/main@0.12.0':
@@ -5351,19 +4612,6 @@ snapshots:
hono: 4.9.6
zod: 4.1.5
- '@humanfs/core@0.19.1': {}
-
- '@humanfs/node@0.16.6':
- dependencies:
- '@humanfs/core': 0.19.1
- '@humanwhocodes/retry': 0.3.1
-
- '@humanwhocodes/module-importer@1.0.1': {}
-
- '@humanwhocodes/retry@0.3.1': {}
-
- '@humanwhocodes/retry@0.4.3': {}
-
'@isaacs/balanced-match@4.0.1': {}
'@isaacs/brace-expansion@5.0.0':
@@ -5621,13 +4869,6 @@ snapshots:
'@msgpack/msgpack@2.8.0': {}
- '@napi-rs/wasm-runtime@0.2.12':
- dependencies:
- '@emnapi/core': 1.4.5
- '@emnapi/runtime': 1.4.5
- '@tybys/wasm-util': 0.10.0
- optional: true
-
'@napi-rs/wasm-runtime@1.0.3':
dependencies:
'@emnapi/core': 1.4.5
@@ -5680,8 +4921,6 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
- '@pkgr/core@0.2.9': {}
-
'@playwright/test@1.55.0':
dependencies:
playwright: 1.55.0
@@ -5751,8 +4990,6 @@ snapshots:
'@rolldown/pluginutils@1.0.0-beta.36': {}
- '@rtsao/scc@1.1.0': {}
-
'@sapphire/async-queue@1.5.5': {}
'@sapphire/snowflake@3.5.5': {}
@@ -5781,16 +5018,6 @@ snapshots:
dependencies:
solid-js: 1.9.9
- '@stylistic/eslint-plugin@5.3.1(eslint@9.35.0)':
- dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
- '@typescript-eslint/types': 8.42.0
- eslint: 9.35.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- estraverse: 5.3.0
- picomatch: 4.0.3
-
'@szmarczak/http-timer@4.0.6':
dependencies:
defer-to-connect: 2.0.1
@@ -5850,8 +5077,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@types/estree@1.0.8': {}
-
'@types/fs-extra@9.0.13':
dependencies:
'@types/node': 24.3.0
@@ -5862,10 +5087,6 @@ snapshots:
'@types/http-cache-semantics@4.0.4': {}
- '@types/json-schema@7.0.15': {}
-
- '@types/json5@0.0.29': {}
-
'@types/keyv@3.1.4':
dependencies:
'@types/node': 24.3.0
@@ -5910,266 +5131,58 @@ snapshots:
'@types/node': 24.3.0
optional: true
- '@typescript-eslint/eslint-plugin@8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint@9.35.0)(typescript@5.9.2)':
- dependencies:
- '@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- '@typescript-eslint/scope-manager': 8.43.0
- '@typescript-eslint/type-utils': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- '@typescript-eslint/utils': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- '@typescript-eslint/visitor-keys': 8.43.0
- eslint: 9.35.0
- graphemer: 1.4.0
- ignore: 7.0.5
- natural-compare: 1.4.0
- ts-api-utils: 2.1.0(typescript@5.9.2)
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ '@vladfrangu/async_event_emitter@2.4.6': {}
- '@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2)':
+ '@xhayper/discord-rpc@1.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
dependencies:
- '@typescript-eslint/scope-manager': 8.43.0
- '@typescript-eslint/types': 8.43.0
- '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/visitor-keys': 8.43.0
- debug: 4.4.1
- eslint: 9.35.0
- typescript: 5.9.2
+ '@discordjs/rest': 2.5.1
+ '@vladfrangu/async_event_emitter': 2.4.6
+ discord-api-types: 0.38.23
+ ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
transitivePeerDependencies:
- - supports-color
+ - bufferutil
+ - utf-8-validate
- '@typescript-eslint/project-service@8.42.0(typescript@5.9.2)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.42.0
- debug: 4.4.1
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ '@xmldom/xmldom@0.8.11': {}
- '@typescript-eslint/project-service@8.43.0(typescript@5.9.2)':
- dependencies:
- '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.43.0
- debug: 4.4.1
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ '@zeit/schemas@2.36.0': {}
- '@typescript-eslint/scope-manager@8.42.0':
- dependencies:
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/visitor-keys': 8.42.0
+ abbrev@1.1.1: {}
- '@typescript-eslint/scope-manager@8.43.0':
- dependencies:
- '@typescript-eslint/types': 8.43.0
- '@typescript-eslint/visitor-keys': 8.43.0
+ abbrev@3.0.1: {}
- '@typescript-eslint/tsconfig-utils@8.42.0(typescript@5.9.2)':
+ abort-controller@3.0.0:
dependencies:
- typescript: 5.9.2
+ event-target-shim: 5.0.1
- '@typescript-eslint/tsconfig-utils@8.43.0(typescript@5.9.2)':
- dependencies:
- typescript: 5.9.2
+ acorn@8.15.0: {}
- '@typescript-eslint/type-utils@8.43.0(eslint@9.35.0)(typescript@5.9.2)':
+ agent-base@6.0.2:
dependencies:
- '@typescript-eslint/types': 8.43.0
- '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/utils': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
debug: 4.4.1
- eslint: 9.35.0
- ts-api-utils: 2.1.0(typescript@5.9.2)
- typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.42.0': {}
-
- '@typescript-eslint/types@8.43.0': {}
-
- '@typescript-eslint/typescript-estree@8.42.0(typescript@5.9.2)':
- dependencies:
- '@typescript-eslint/project-service': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/tsconfig-utils': 8.42.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/visitor-keys': 8.42.0
- debug: 4.4.1
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.7.2
- ts-api-utils: 2.1.0(typescript@5.9.2)
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ agent-base@7.1.4: {}
- '@typescript-eslint/typescript-estree@8.43.0(typescript@5.9.2)':
+ agentkeepalive@4.6.0:
dependencies:
- '@typescript-eslint/project-service': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/tsconfig-utils': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/types': 8.43.0
- '@typescript-eslint/visitor-keys': 8.43.0
- debug: 4.4.1
- fast-glob: 3.3.3
- is-glob: 4.0.3
- minimatch: 9.0.5
- semver: 7.7.2
- ts-api-utils: 2.1.0(typescript@5.9.2)
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ humanize-ms: 1.2.1
- '@typescript-eslint/utils@8.42.0(eslint@9.35.0)(typescript@5.9.2)':
+ aggregate-error@3.1.0:
dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
- '@typescript-eslint/scope-manager': 8.42.0
- '@typescript-eslint/types': 8.42.0
- '@typescript-eslint/typescript-estree': 8.42.0(typescript@5.9.2)
- eslint: 9.35.0
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ clean-stack: 2.2.0
+ indent-string: 4.0.0
- '@typescript-eslint/utils@8.43.0(eslint@9.35.0)(typescript@5.9.2)':
- dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
- '@typescript-eslint/scope-manager': 8.43.0
- '@typescript-eslint/types': 8.43.0
- '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2)
- eslint: 9.35.0
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
+ ajv-formats@3.0.1(ajv@8.17.1):
+ optionalDependencies:
+ ajv: 8.17.1
- '@typescript-eslint/visitor-keys@8.42.0':
+ ajv-keywords@3.5.2(ajv@6.12.6):
dependencies:
- '@typescript-eslint/types': 8.42.0
- eslint-visitor-keys: 4.2.1
+ ajv: 6.12.6
- '@typescript-eslint/visitor-keys@8.43.0':
- dependencies:
- '@typescript-eslint/types': 8.43.0
- eslint-visitor-keys: 4.2.1
-
- '@unrs/resolver-binding-android-arm-eabi@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-android-arm64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-darwin-arm64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-darwin-x64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-freebsd-x64@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-linux-x64-musl@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-wasm32-wasi@1.11.1':
- dependencies:
- '@napi-rs/wasm-runtime': 0.2.12
- optional: true
-
- '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
- optional: true
-
- '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
- optional: true
-
- '@vladfrangu/async_event_emitter@2.4.6': {}
-
- '@xhayper/discord-rpc@1.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
- dependencies:
- '@discordjs/rest': 2.5.1
- '@vladfrangu/async_event_emitter': 2.4.6
- discord-api-types: 0.38.23
- ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
- transitivePeerDependencies:
- - bufferutil
- - utf-8-validate
-
- '@xmldom/xmldom@0.8.11': {}
-
- '@zeit/schemas@2.36.0': {}
-
- abbrev@1.1.1: {}
-
- abbrev@3.0.1: {}
-
- abort-controller@3.0.0:
- dependencies:
- event-target-shim: 5.0.1
-
- acorn-jsx@5.3.2(acorn@8.15.0):
- dependencies:
- acorn: 8.15.0
-
- acorn@8.15.0: {}
-
- agent-base@6.0.2:
- dependencies:
- debug: 4.4.1
- transitivePeerDependencies:
- - supports-color
-
- agent-base@7.1.4: {}
-
- agentkeepalive@4.6.0:
- dependencies:
- humanize-ms: 1.2.1
-
- aggregate-error@3.1.0:
- dependencies:
- clean-stack: 2.2.0
- indent-string: 4.0.0
-
- ajv-formats@3.0.1(ajv@8.17.1):
- optionalDependencies:
- ajv: 8.17.1
-
- ajv-keywords@3.5.2(ajv@6.12.6):
- dependencies:
- ajv: 6.12.6
-
- ajv@6.12.6:
+ ajv@6.12.6:
dependencies:
fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0
@@ -6262,51 +5275,6 @@ snapshots:
call-bound: 1.0.4
is-array-buffer: 3.0.5
- array-includes@3.1.9:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- is-string: 1.1.1
- math-intrinsics: 1.1.0
-
- array.prototype.findlastindex@1.2.6:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-shim-unscopables: 1.1.0
-
- array.prototype.flat@1.3.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-shim-unscopables: 1.1.0
-
- array.prototype.flatmap@1.3.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-shim-unscopables: 1.1.0
-
- arraybuffer.prototype.slice@1.0.4:
- dependencies:
- array-buffer-byte-length: 1.0.2
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
- is-array-buffer: 3.0.5
-
assert-plus@1.0.0:
optional: true
@@ -6315,8 +5283,6 @@ snapshots:
async-exit-hook@2.0.1: {}
- async-function@1.0.0: {}
-
async-mutex@0.5.0:
dependencies:
tslib: 2.8.1
@@ -6551,8 +5517,6 @@ snapshots:
call-bind-apply-helpers: 1.0.2
get-intrinsic: 1.3.0
- callsites@3.1.0: {}
-
camelcase@7.0.1: {}
caniuse-lite@1.0.30001735: {}
@@ -6733,24 +5697,6 @@ snapshots:
data-uri-to-buffer@4.0.1: {}
- data-view-buffer@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-length@1.0.2:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
- data-view-byte-offset@1.0.1:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-data-view: 1.0.2
-
debounce-fn@6.0.0:
dependencies:
mimic-function: 5.0.1
@@ -6759,10 +5705,6 @@ snapshots:
dependencies:
ms: 2.0.0
- debug@3.2.7:
- dependencies:
- ms: 2.1.3
-
debug@4.4.1:
dependencies:
ms: 2.1.3
@@ -6794,8 +5736,6 @@ snapshots:
deep-extend@0.6.0: {}
- deep-is@0.1.4: {}
-
deepmerge-ts@7.1.5: {}
deepmerge@4.3.1: {}
@@ -6884,10 +5824,6 @@ snapshots:
verror: 1.10.1
optional: true
- doctrine@2.1.0:
- dependencies:
- esutils: 2.0.3
-
dom-serializer@2.0.0:
dependencies:
domelementtype: 2.3.0
@@ -7094,63 +6030,6 @@ snapshots:
error-stack-parser-es@1.0.5: {}
- es-abstract@1.24.0:
- dependencies:
- array-buffer-byte-length: 1.0.2
- arraybuffer.prototype.slice: 1.0.4
- available-typed-arrays: 1.0.7
- call-bind: 1.0.8
- call-bound: 1.0.4
- data-view-buffer: 1.0.2
- data-view-byte-length: 1.0.2
- data-view-byte-offset: 1.0.1
- es-define-property: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- es-set-tostringtag: 2.1.0
- es-to-primitive: 1.3.0
- function.prototype.name: 1.1.8
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- get-symbol-description: 1.1.0
- globalthis: 1.0.4
- gopd: 1.2.0
- has-property-descriptors: 1.0.2
- has-proto: 1.2.0
- has-symbols: 1.1.0
- hasown: 2.0.2
- internal-slot: 1.1.0
- is-array-buffer: 3.0.5
- is-callable: 1.2.7
- is-data-view: 1.0.2
- is-negative-zero: 2.0.3
- is-regex: 1.2.1
- is-set: 2.0.3
- is-shared-array-buffer: 1.0.4
- is-string: 1.1.1
- is-typed-array: 1.1.15
- is-weakref: 1.1.1
- math-intrinsics: 1.1.0
- object-inspect: 1.13.4
- object-keys: 1.1.1
- object.assign: 4.1.7
- own-keys: 1.0.1
- regexp.prototype.flags: 1.5.4
- safe-array-concat: 1.1.3
- safe-push-apply: 1.0.0
- safe-regex-test: 1.1.0
- set-proto: 1.0.0
- stop-iteration-iterator: 1.1.0
- string.prototype.trim: 1.2.10
- string.prototype.trimend: 1.0.9
- string.prototype.trimstart: 1.0.8
- typed-array-buffer: 1.0.3
- typed-array-byte-length: 1.0.3
- typed-array-byte-offset: 1.0.4
- typed-array-length: 1.0.7
- unbox-primitive: 1.1.0
- which-typed-array: 1.1.19
-
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
@@ -7180,16 +6059,6 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.2
- es-shim-unscopables@1.1.0:
- dependencies:
- hasown: 2.0.2
-
- es-to-primitive@1.3.0:
- dependencies:
- is-callable: 1.2.7
- is-date-object: 1.1.0
- is-symbol: 1.1.1
-
es6-error@4.1.1:
optional: true
@@ -7224,179 +6093,11 @@ snapshots:
escalade@3.2.0: {}
- escape-string-regexp@4.0.0: {}
+ escape-string-regexp@4.0.0:
+ optional: true
escape-string-regexp@5.0.0: {}
- eslint-config-prettier@10.1.8(eslint@9.35.0):
- dependencies:
- eslint: 9.35.0
-
- eslint-import-context@0.1.9(unrs-resolver@1.11.1):
- dependencies:
- get-tsconfig: 4.10.1
- stable-hash-x: 0.2.0
- optionalDependencies:
- unrs-resolver: 1.11.1
-
- eslint-import-resolver-exports@1.0.0-beta.5(eslint-plugin-import@2.32.0)(eslint@9.35.0):
- dependencies:
- eslint: 9.35.0
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0)
- resolve.exports: 2.0.3
-
- eslint-import-resolver-node@0.3.9:
- dependencies:
- debug: 3.2.7
- is-core-module: 2.16.1
- resolve: 1.22.10
- transitivePeerDependencies:
- - supports-color
-
- eslint-import-resolver-typescript@4.4.4(eslint-plugin-import@2.32.0)(eslint@9.35.0):
- dependencies:
- debug: 4.4.1
- eslint: 9.35.0
- eslint-import-context: 0.1.9(unrs-resolver@1.11.1)
- get-tsconfig: 4.10.1
- is-bun-module: 2.0.0
- stable-hash-x: 0.2.0
- tinyglobby: 0.2.14
- unrs-resolver: 1.11.1
- optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0)
- transitivePeerDependencies:
- - supports-color
-
- eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0):
- dependencies:
- debug: 3.2.7
- optionalDependencies:
- '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- eslint: 9.35.0
- eslint-import-resolver-node: 0.3.9
- eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import@2.32.0)(eslint@9.35.0)
- transitivePeerDependencies:
- - supports-color
-
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0):
- dependencies:
- '@rtsao/scc': 1.1.0
- array-includes: 3.1.9
- array.prototype.findlastindex: 1.2.6
- array.prototype.flat: 1.3.3
- array.prototype.flatmap: 1.3.3
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 9.35.0
- eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.35.0)
- hasown: 2.0.2
- is-core-module: 2.16.1
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.fromentries: 2.0.8
- object.groupby: 1.0.3
- object.values: 1.2.1
- semver: 6.3.1
- string.prototype.trimend: 1.0.9
- tsconfig-paths: 3.15.0
- optionalDependencies:
- '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
-
- eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.35.0))(eslint@9.35.0)(prettier@3.6.2):
- dependencies:
- eslint: 9.35.0
- prettier: 3.6.2
- prettier-linter-helpers: 1.0.0
- synckit: 0.11.11
- optionalDependencies:
- eslint-config-prettier: 10.1.8(eslint@9.35.0)
-
- eslint-plugin-solid@0.14.5(eslint@9.35.0)(typescript@5.9.2):
- dependencies:
- '@typescript-eslint/utils': 8.42.0(eslint@9.35.0)(typescript@5.9.2)
- eslint: 9.35.0
- estraverse: 5.3.0
- is-html: 2.0.0
- kebab-case: 1.0.2
- known-css-properties: 0.30.0
- style-to-object: 1.0.9
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
-
- eslint-scope@8.4.0:
- dependencies:
- esrecurse: 4.3.0
- estraverse: 5.3.0
-
- eslint-visitor-keys@3.4.3: {}
-
- eslint-visitor-keys@4.2.1: {}
-
- eslint@9.35.0:
- dependencies:
- '@eslint-community/eslint-utils': 4.8.0(eslint@9.35.0)
- '@eslint-community/regexpp': 4.12.1
- '@eslint/config-array': 0.21.0
- '@eslint/config-helpers': 0.3.1
- '@eslint/core': 0.15.2
- '@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.35.0
- '@eslint/plugin-kit': 0.3.5
- '@humanfs/node': 0.16.6
- '@humanwhocodes/module-importer': 1.0.1
- '@humanwhocodes/retry': 0.4.3
- '@types/estree': 1.0.8
- '@types/json-schema': 7.0.15
- ajv: 6.12.6
- chalk: 4.1.2
- cross-spawn: 7.0.6
- debug: 4.4.1
- escape-string-regexp: 4.0.0
- eslint-scope: 8.4.0
- eslint-visitor-keys: 4.2.1
- espree: 10.4.0
- esquery: 1.6.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 8.0.0
- find-up: 5.0.0
- glob-parent: 6.0.2
- ignore: 5.3.2
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- json-stable-stringify-without-jsonify: 1.0.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.4
- transitivePeerDependencies:
- - supports-color
-
- espree@10.4.0:
- dependencies:
- acorn: 8.15.0
- acorn-jsx: 5.3.2(acorn@8.15.0)
- eslint-visitor-keys: 4.2.1
-
- esquery@1.6.0:
- dependencies:
- estraverse: 5.3.0
-
- esrecurse@4.3.0:
- dependencies:
- estraverse: 5.3.0
-
- estraverse@5.3.0: {}
-
- esutils@2.0.3: {}
-
event-stream@4.0.1:
dependencies:
duplexer: 0.1.2
@@ -7448,8 +6149,6 @@ snapshots:
fast-deep-equal@3.1.3: {}
- fast-diff@1.3.0: {}
-
fast-equals@5.2.2: {}
fast-glob@3.3.3:
@@ -7462,8 +6161,6 @@ snapshots:
fast-json-stable-stringify@2.1.0: {}
- fast-levenshtein@2.0.6: {}
-
fast-uri@3.0.6: {}
fastq@1.19.1:
@@ -7485,10 +6182,6 @@ snapshots:
fflate@0.8.2: {}
- file-entry-cache@8.0.0:
- dependencies:
- flat-cache: 4.0.1
-
file-type@16.5.4(patch_hash=fa6e3546c096bc3579fd83808c2dfac1a64546eb2ce096bf838076bda630baf5):
dependencies:
readable-web-to-node-stream: 3.0.4
@@ -7509,18 +6202,6 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
- find-up@5.0.0:
- dependencies:
- locate-path: 6.0.0
- path-exists: 4.0.0
-
- flat-cache@4.0.1:
- dependencies:
- flatted: 3.3.3
- keyv: 4.5.4
-
- flatted@3.3.3: {}
-
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
@@ -7594,15 +6275,6 @@ snapshots:
function-bind@1.1.2: {}
- function.prototype.name@1.1.8:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- functions-have-names: 1.2.3
- hasown: 2.0.2
- is-callable: 1.2.7
-
functions-have-names@1.2.3: {}
gensync@1.0.0-beta.2: {}
@@ -7633,16 +6305,6 @@ snapshots:
get-stream@6.0.1: {}
- get-symbol-description@1.1.0:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- get-intrinsic: 1.3.0
-
- get-tsconfig@4.10.1:
- dependencies:
- resolve-pkg-maps: 1.0.0
-
gifwrap@0.10.1:
dependencies:
image-q: 4.0.0
@@ -7652,10 +6314,6 @@ snapshots:
dependencies:
is-glob: 4.0.3
- glob-parent@6.0.2:
- dependencies:
- is-glob: 4.0.3
-
glob@10.4.5:
dependencies:
foreground-child: 3.3.1
@@ -7701,12 +6359,11 @@ snapshots:
serialize-error: 7.0.1
optional: true
- globals@14.0.0: {}
-
globalthis@1.0.4:
dependencies:
define-properties: 1.2.1
gopd: 1.2.0
+ optional: true
globby@14.1.0:
dependencies:
@@ -7739,8 +6396,6 @@ snapshots:
graceful-fs@4.2.11: {}
- graphemer@1.4.0: {}
-
hanja@1.1.5: {}
happy-dom@18.0.1:
@@ -7757,10 +6412,6 @@ snapshots:
dependencies:
es-define-property: 1.0.1
- has-proto@1.2.0:
- dependencies:
- dunder-proto: 1.0.1
-
has-symbols@1.1.0: {}
has-tostringtag@1.0.2:
@@ -7783,8 +6434,6 @@ snapshots:
html-entities@2.3.3: {}
- html-tags@3.3.1: {}
-
html-to-text@9.0.5:
dependencies:
'@selderee/plugin-htmlparser2': 0.11.0
@@ -7864,8 +6513,6 @@ snapshots:
ieee754@1.2.1: {}
- ignore@5.3.2: {}
-
ignore@7.0.5: {}
image-q@4.0.0:
@@ -7874,11 +6521,6 @@ snapshots:
immediate@3.0.6: {}
- import-fresh@3.3.1:
- dependencies:
- parent-module: 1.0.1
- resolve-from: 4.0.0
-
imurmurhash@0.1.4: {}
indent-string@4.0.0: {}
@@ -7894,8 +6536,6 @@ snapshots:
ini@1.3.8: {}
- inline-style-parser@0.2.4: {}
-
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -7915,14 +6555,6 @@ snapshots:
call-bound: 1.0.4
get-intrinsic: 1.3.0
- is-async-function@2.1.1:
- dependencies:
- async-function: 1.0.0
- call-bound: 1.0.4
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
is-bigint@1.1.0:
dependencies:
has-bigints: 1.1.0
@@ -7932,26 +6564,12 @@ snapshots:
call-bound: 1.0.4
has-tostringtag: 1.0.2
- is-bun-module@2.0.0:
- dependencies:
- semver: 7.7.2
-
is-callable@1.2.7: {}
is-ci@3.0.1:
dependencies:
ci-info: 3.9.0
- is-core-module@2.16.1:
- dependencies:
- hasown: 2.0.2
-
- is-data-view@1.0.2:
- dependencies:
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- is-typed-array: 1.1.15
-
is-date-object@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -7963,27 +6581,12 @@ snapshots:
is-extglob@2.1.1: {}
- is-finalizationregistry@1.1.1:
- dependencies:
- call-bound: 1.0.4
-
is-fullwidth-code-point@3.0.0: {}
- is-generator-function@1.1.0:
- dependencies:
- call-bound: 1.0.4
- get-proto: 1.0.1
- has-tostringtag: 1.0.2
- safe-regex-test: 1.1.0
-
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
- is-html@2.0.0:
- dependencies:
- html-tags: 3.3.1
-
is-inside-container@1.0.0:
dependencies:
is-docker: 3.0.0
@@ -7994,8 +6597,6 @@ snapshots:
is-map@2.0.3: {}
- is-negative-zero@2.0.3: {}
-
is-number-object@1.1.1:
dependencies:
call-bound: 1.0.4
@@ -8035,20 +6636,12 @@ snapshots:
has-symbols: 1.1.0
safe-regex-test: 1.1.0
- is-typed-array@1.1.15:
- dependencies:
- which-typed-array: 1.1.19
-
is-unicode-supported@0.1.0: {}
is-url@1.2.4: {}
is-weakmap@2.0.2: {}
- is-weakref@1.1.1:
- dependencies:
- call-bound: 1.0.4
-
is-weakset@2.0.4:
dependencies:
call-bound: 1.0.4
@@ -8146,15 +6739,9 @@ snapshots:
json-schema-typed@8.0.1: {}
- json-stable-stringify-without-jsonify@1.0.1: {}
-
json-stringify-safe@5.0.1:
optional: true
- json5@1.0.2:
- dependencies:
- minimist: 1.2.8
-
json5@2.2.3: {}
jsonfile@4.0.0:
@@ -8174,8 +6761,6 @@ snapshots:
readable-stream: 2.3.8
setimmediate: 1.0.5
- kebab-case@1.0.2: {}
-
keyboardevent-from-electron-accelerator@2.0.0: {}
keyboardevents-areequal@0.2.2: {}
@@ -8184,8 +6769,6 @@ snapshots:
dependencies:
json-buffer: 3.0.1
- known-css-properties@0.30.0: {}
-
kuromoji@0.1.2(patch_hash=4a948f1ea45c61779fa371feb020253ccf7a24e1f7c6b2e250b3ce53d86216d4):
dependencies:
async: 2.6.4
@@ -8206,11 +6789,6 @@ snapshots:
leac@0.6.0: {}
- levn@0.4.1:
- dependencies:
- prelude-ls: 1.2.1
- type-check: 0.4.0
-
lib-esm@0.4.2: {}
lie@3.3.0:
@@ -8262,18 +6840,12 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.30.1
lightningcss-win32-x64-msvc: 1.30.1
- locate-path@6.0.0:
- dependencies:
- p-locate: 5.0.0
-
lodash.debounce@4.0.8: {}
lodash.escaperegexp@4.1.2: {}
lodash.isequal@4.5.0: {}
- lodash.merge@4.6.2: {}
-
lodash@4.17.21: {}
log-symbols@4.1.0:
@@ -8283,6 +6855,11 @@ snapshots:
long@4.0.0: {}
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+ optional: true
+
lowercase-keys@2.0.0: {}
lru-cache@10.4.3: {}
@@ -8480,10 +7057,6 @@ snapshots:
nanoid@3.3.11: {}
- napi-postinstall@0.3.3: {}
-
- natural-compare@1.4.0: {}
-
negotiator@0.6.4: {}
negotiator@1.0.0: {}
@@ -8553,6 +7126,9 @@ snapshots:
dependencies:
boolbase: 1.0.0
+ object-assign@4.1.1:
+ optional: true
+
object-inspect@1.13.4: {}
object-is@1.1.6:
@@ -8571,26 +7147,6 @@ snapshots:
has-symbols: 1.1.0
object-keys: 1.1.1
- object.fromentries@2.0.8:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-object-atoms: 1.1.1
-
- object.groupby@1.0.3:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
-
- object.values@1.2.1:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
ohash@2.0.11: {}
omggif@1.0.10: {}
@@ -8616,15 +7172,6 @@ snapshots:
dependencies:
yaml: 2.8.1
- optionator@0.9.4:
- dependencies:
- deep-is: 0.1.4
- fast-levenshtein: 2.0.6
- levn: 0.4.1
- prelude-ls: 1.2.1
- type-check: 0.4.0
- word-wrap: 1.2.5
-
ora@5.4.1:
dependencies:
bl: 4.1.0
@@ -8639,22 +7186,12 @@ snapshots:
os-homedir@1.0.2: {}
- own-keys@1.0.1:
- dependencies:
- get-intrinsic: 1.3.0
- object-keys: 1.1.1
- safe-push-apply: 1.0.0
-
p-cancelable@2.1.1: {}
p-limit@3.1.0:
dependencies:
yocto-queue: 0.1.0
- p-locate@5.0.0:
- dependencies:
- p-limit: 3.1.0
-
p-map@4.0.0:
dependencies:
aggregate-error: 3.1.0
@@ -8665,10 +7202,6 @@ snapshots:
pako@1.0.11: {}
- parent-module@1.0.1:
- dependencies:
- callsites: 3.1.0
-
parse-bmfont-ascii@1.0.6: {}
parse-bmfont-binary@1.0.6: {}
@@ -8689,16 +7222,12 @@ snapshots:
path-browserify@1.0.1: {}
- path-exists@4.0.0: {}
-
path-is-absolute@1.0.1: {}
path-is-inside@1.0.2: {}
path-key@3.1.1: {}
- path-parse@1.0.7: {}
-
path-scurry@1.11.1:
dependencies:
lru-cache: 10.4.3
@@ -8779,14 +7308,6 @@ snapshots:
commander: 9.5.0
optional: true
- prelude-ls@1.2.1: {}
-
- prettier-linter-helpers@1.0.0:
- dependencies:
- fast-diff: 1.3.0
-
- prettier@3.6.2: {}
-
proc-log@2.0.1: {}
proc-log@5.0.0: {}
@@ -8824,6 +7345,19 @@ snapshots:
minimist: 1.2.8
strip-json-comments: 2.0.1
+ react-dom@18.3.1(react@17.0.2):
+ dependencies:
+ loose-envify: 1.4.0
+ react: 17.0.2
+ scheduler: 0.23.2
+ optional: true
+
+ react@17.0.2:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ optional: true
+
read-binary-file-arch@1.0.6:
dependencies:
debug: 4.4.1
@@ -8858,17 +7392,6 @@ snapshots:
dependencies:
readable-stream: 4.7.0
- reflect.getprototypeof@1.0.10:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
- get-intrinsic: 1.3.0
- get-proto: 1.0.1
- which-builtin-type: 1.2.1
-
regenerator-runtime@0.13.11: {}
regexp.prototype.flags@1.5.4:
@@ -8899,18 +7422,6 @@ snapshots:
resolve-alpn@1.2.1: {}
- resolve-from@4.0.0: {}
-
- resolve-pkg-maps@1.0.0: {}
-
- resolve.exports@2.0.3: {}
-
- resolve@1.22.10:
- dependencies:
- is-core-module: 2.16.1
- path-parse: 1.0.7
- supports-preserve-symlinks-flag: 1.0.0
-
responselike@2.0.1:
dependencies:
lowercase-keys: 2.0.0
@@ -8984,23 +7495,10 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
- safe-array-concat@1.1.3:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- get-intrinsic: 1.3.0
- has-symbols: 1.1.0
- isarray: 2.0.5
-
safe-buffer@5.1.2: {}
safe-buffer@5.2.1: {}
- safe-push-apply@1.0.0:
- dependencies:
- es-errors: 1.3.0
- isarray: 2.0.5
-
safe-regex-test@1.1.0:
dependencies:
call-bound: 1.0.4
@@ -9015,6 +7513,11 @@ snapshots:
sax@1.4.1: {}
+ scheduler@0.23.2:
+ dependencies:
+ loose-envify: 1.4.0
+ optional: true
+
sdp@3.2.1: {}
selderee@0.11.0:
@@ -9087,12 +7590,6 @@ snapshots:
functions-have-names: 1.2.3
has-property-descriptors: 1.0.2
- set-proto@1.0.0:
- dependencies:
- dunder-proto: 1.0.1
- es-errors: 1.3.0
- es-object-atoms: 1.1.1
-
setimmediate@1.0.5: {}
shebang-command@2.0.0:
@@ -9240,8 +7737,6 @@ snapshots:
dependencies:
minipass: 3.3.6
- stable-hash-x@0.2.0: {}
-
stat-mode@1.0.0: {}
stop-iteration-iterator@1.1.0:
@@ -9266,29 +7761,6 @@ snapshots:
emoji-regex: 9.2.2
strip-ansi: 7.1.0
- string.prototype.trim@1.2.10:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-data-property: 1.1.4
- define-properties: 1.2.1
- es-abstract: 1.24.0
- es-object-atoms: 1.1.1
- has-property-descriptors: 1.0.2
-
- string.prototype.trimend@1.0.9:
- dependencies:
- call-bind: 1.0.8
- call-bound: 1.0.4
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
- string.prototype.trimstart@1.0.8:
- dependencies:
- call-bind: 1.0.8
- define-properties: 1.2.1
- es-object-atoms: 1.1.1
-
string_decoder@1.1.1:
dependencies:
safe-buffer: 5.1.2
@@ -9305,14 +7777,10 @@ snapshots:
dependencies:
ansi-regex: 6.1.0
- strip-bom@3.0.0: {}
-
strip-final-newline@2.0.0: {}
strip-json-comments@2.0.1: {}
- strip-json-comments@3.1.1: {}
-
strtok3@6.3.0:
dependencies:
'@tokenizer/token': 0.3.0
@@ -9320,10 +7788,6 @@ snapshots:
stubborn-fs@1.2.5: {}
- style-to-object@1.0.9:
- dependencies:
- inline-style-parser: 0.2.4
-
sumchecker@3.0.1:
dependencies:
debug: 4.4.1
@@ -9334,12 +7798,6 @@ snapshots:
dependencies:
has-flag: 4.0.0
- supports-preserve-symlinks-flag@1.0.0: {}
-
- synckit@0.11.11:
- dependencies:
- '@pkgr/core': 0.2.9
-
tar@6.2.1:
dependencies:
chownr: 2.0.0
@@ -9419,28 +7877,13 @@ snapshots:
dependencies:
utf8-byte-length: 1.0.5
- ts-api-utils@2.1.0(typescript@5.9.2):
- dependencies:
- typescript: 5.9.2
-
ts-morph@27.0.0:
dependencies:
'@ts-morph/common': 0.28.0
code-block-writer: 13.0.3
- tsconfig-paths@3.15.0:
- dependencies:
- '@types/json5': 0.0.29
- json5: 1.0.2
- minimist: 1.2.8
- strip-bom: 3.0.0
-
tslib@2.8.1: {}
- type-check@0.4.0:
- dependencies:
- prelude-ls: 1.2.1
-
type-fest@0.13.1:
optional: true
@@ -9448,61 +7891,10 @@ snapshots:
type-fest@4.41.0: {}
- typed-array-buffer@1.0.3:
- dependencies:
- call-bound: 1.0.4
- es-errors: 1.3.0
- is-typed-array: 1.1.15
-
- typed-array-byte-length@1.0.3:
- dependencies:
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
-
- typed-array-byte-offset@1.0.4:
- dependencies:
- available-typed-arrays: 1.0.7
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- has-proto: 1.2.0
- is-typed-array: 1.1.15
- reflect.getprototypeof: 1.0.10
-
- typed-array-length@1.0.7:
- dependencies:
- call-bind: 1.0.8
- for-each: 0.3.5
- gopd: 1.2.0
- is-typed-array: 1.1.15
- possible-typed-array-names: 1.1.0
- reflect.getprototypeof: 1.0.10
-
- typescript-eslint@8.43.0(eslint@9.35.0)(typescript@5.9.2):
- dependencies:
- '@typescript-eslint/eslint-plugin': 8.43.0(@typescript-eslint/parser@8.43.0(eslint@9.35.0)(typescript@5.9.2))(eslint@9.35.0)(typescript@5.9.2)
- '@typescript-eslint/parser': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- '@typescript-eslint/typescript-estree': 8.43.0(typescript@5.9.2)
- '@typescript-eslint/utils': 8.43.0(eslint@9.35.0)(typescript@5.9.2)
- eslint: 9.35.0
- typescript: 5.9.2
- transitivePeerDependencies:
- - supports-color
-
typescript@5.9.2: {}
uint8array-extras@1.4.1: {}
- unbox-primitive@1.1.0:
- dependencies:
- call-bound: 1.0.4
- has-bigints: 1.1.0
- has-symbols: 1.1.0
- which-boxed-primitive: 1.1.1
-
undici-types@6.21.0: {}
undici-types@7.10.0: {}
@@ -9536,30 +7928,6 @@ snapshots:
pathe: 2.0.3
picomatch: 4.0.3
- unrs-resolver@1.11.1:
- dependencies:
- napi-postinstall: 0.3.3
- optionalDependencies:
- '@unrs/resolver-binding-android-arm-eabi': 1.11.1
- '@unrs/resolver-binding-android-arm64': 1.11.1
- '@unrs/resolver-binding-darwin-arm64': 1.11.1
- '@unrs/resolver-binding-darwin-x64': 1.11.1
- '@unrs/resolver-binding-freebsd-x64': 1.11.1
- '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
- '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
- '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
- '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
- '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
- '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
- '@unrs/resolver-binding-linux-x64-musl': 1.11.1
- '@unrs/resolver-binding-wasm32-wasi': 1.11.1
- '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
- '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
- '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
-
unzip-crx-3@0.2.0:
dependencies:
jszip: 3.10.1
@@ -9606,8 +7974,10 @@ snapshots:
extsprintf: 1.4.1
optional: true
- virtua@0.42.3(solid-js@1.9.9):
+ virtua@0.42.3(react-dom@18.3.1(react@17.0.2))(react@17.0.2)(solid-js@1.9.9):
optionalDependencies:
+ react: 17.0.2
+ react-dom: 18.3.1(react@17.0.2)
solid-js: 1.9.9
vite-dev-rpc@1.1.0(rolldown-vite@7.1.8(@types/node@24.3.0)(esbuild@0.25.9)(yaml@2.8.1)):
@@ -9680,22 +8050,6 @@ snapshots:
is-string: 1.1.1
is-symbol: 1.1.1
- which-builtin-type@1.2.1:
- dependencies:
- call-bound: 1.0.4
- function.prototype.name: 1.1.8
- has-tostringtag: 1.0.2
- is-async-function: 2.1.1
- is-date-object: 1.1.0
- is-finalizationregistry: 1.1.1
- is-generator-function: 1.1.0
- is-regex: 1.2.1
- is-weakref: 1.1.1
- isarray: 2.0.5
- which-boxed-primitive: 1.1.1
- which-collection: 1.0.2
- which-typed-array: 1.1.19
-
which-collection@1.0.2:
dependencies:
is-map: 2.0.3
@@ -9725,8 +8079,6 @@ snapshots:
dependencies:
string-width: 5.1.2
- word-wrap@1.2.5: {}
-
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
diff --git a/src/config/plugins.ts b/src/config/plugins.ts
index e44204645e..2c4fe7fe2c 100644
--- a/src/config/plugins.ts
+++ b/src/config/plugins.ts
@@ -13,7 +13,7 @@ export function getPlugins() {
export async function isEnabled(plugin: string) {
const pluginConfig = deepmerge(
- (await allPlugins())[plugin].config ?? { enabled: false },
+ (await allPlugins())[plugin]?.config ?? { enabled: false },
(store.get('plugins') as Record)[plugin] ?? {},
);
return pluginConfig !== undefined && pluginConfig.enabled;
diff --git a/src/config/store.ts b/src/config/store.ts
index 253b298ab7..5ce9889f79 100644
--- a/src/config/store.ts
+++ b/src/config/store.ts
@@ -1,10 +1,7 @@
import Store from 'electron-store';
-
-import { defaultConfig as defaults } from './defaults';
-
import { DefaultPresetList, type Preset } from '@/plugins/downloader/types';
-
-import type { SyncedLyricsPluginConfig } from '@/plugins/synced-lyrics/types';
+import { type SyncedLyricsPluginConfig } from '@/plugins/synced-lyrics/types';
+import { defaultConfig as defaults } from './defaults';
export type IStore = InstanceType<
typeof import('conf').default>
@@ -231,7 +228,7 @@ const migrations = {
}
// Include custom options
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // biome-ignore lint/suspicious/noExplicitAny: Plugin configurations have dynamic structures that vary by plugin type
const plugins: Record = {
adblocker: {
enabled: true,
@@ -246,7 +243,6 @@ const migrations = {
};
for (const enabledPlugin of enabledPlugins) {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
plugins[enabledPlugin] = {
...plugins[enabledPlugin],
enabled: true,
diff --git a/src/i18n/resources/de.json b/src/i18n/resources/de.json
index 0a229be93a..9b1291c72f 100644
--- a/src/i18n/resources/de.json
+++ b/src/i18n/resources/de.json
@@ -895,14 +895,14 @@
"type": {
"label": "Typ",
"submenu": {
- "acrylic": "Acrylic",
+ "acrylic": "Acryl",
"mica": "Mica",
"none": "Nichts",
- "tabbed": "Tabbed"
+ "tabbed": "Mit Registerkarten"
}
}
},
- "name": "Transparent Player"
+ "name": "Transparenter Player"
},
"tuna-obs": {
"description": "Integration mit dem OBS-Plugin Tuna",
diff --git a/src/i18n/resources/fil.json b/src/i18n/resources/fil.json
index f96a8241f9..d93b391bb5 100644
--- a/src/i18n/resources/fil.json
+++ b/src/i18n/resources/fil.json
@@ -97,7 +97,7 @@
"label": "Mga advance na opsyon",
"submenu": {
"auto-reset-app-cache": "I-reset ang app cache kapag nagsisimula ang app",
- "disable-hardware-acceleration": "Di paganahin ang pagpapabilis ng hardware",
+ "disable-hardware-acceleration": "Di-paganahin ang pagpapabilis ng hardware",
"edit-config-json": "I-edit ang config.json",
"override-user-agent": "I-override ang User-Agent",
"restart-on-config-changes": "I-restart kada may pagbabago sa config",
@@ -153,7 +153,7 @@
"custom-window-title": {
"label": "Custom na window title",
"prompt": {
- "label": "I-enter ang custom na window tile: (iwanang blanko para ma-disable)",
+ "label": "I-enter ang custom na window tile: (iwanang blanko para di-mapagana)",
"placeholder": "Halimbawa: YouTube Music"
}
},
@@ -339,6 +339,27 @@
"description": "Ilapat ang compression sa audio (pinababa ang volume ng pinakamalakas na bahagi ng signal at pinapataas ang volume ng pinakamalambot na bahagi)",
"name": "Compressor ng Audio"
},
+ "auth-proxy-adapter": {
+ "description": "Suporta para sa paggamit ng authentication proxy services",
+ "menu": {
+ "disable": "Huwag paganahin ang Proxy Adapter",
+ "enable": "Paganahin ang Proxy Adapter",
+ "port": {
+ "label": "Port"
+ }
+ },
+ "name": "Auth Proxy Adapter",
+ "prompt": {
+ "hostname": {
+ "label": "Ilagay ang pangalan ng host para sa local proxy server (kinailangang mag-restart):",
+ "title": "Hostname ng Proxy"
+ },
+ "port": {
+ "label": "Ilagay ang port para sa local proxy server (kinailangang mag-restart):",
+ "title": "Port ng Proxy"
+ }
+ }
+ },
"blur-nav-bar": {
"description": "Gawing transparent at malabo ang bar ng nabigasyon",
"name": "Palabuin ang Bar ng Nabigasyon"
@@ -363,6 +384,11 @@
},
"templates": {
"title": "Bumukas ng pagpilian ng caption"
+ },
+ "toast": {
+ "caption-changed": "Binago ang caption sa {{language}}",
+ "caption-disabled": "Di-napagana ang mga caption",
+ "no-captions": "Walang captions ay available para sa kantang ito"
}
},
"compact-sidebar": {
@@ -403,7 +429,7 @@
"menu": {
"apply-once": "Nalalapat lamang sa startup"
},
- "name": "Patayin ang Pag-Autoplay"
+ "name": "Di-paganahin ang Autoplay"
},
"discord": {
"backend": {
@@ -430,6 +456,7 @@
}
}
},
+ "name": "Discord Rich Presence",
"prompt": {
"set-inactivity-timeout": {
"label": "Ilagay ang inactivity timeout sa ilang segundo:",
@@ -441,10 +468,16 @@
"backend": {
"dialog": {
"error": {
+ "buttons": {
+ "ok": "OK"
+ },
"message": "Kainis! Paumanhin, nabigo ang pag-download…",
"title": "Nagkaroon ng error sa pag-download!"
},
"start-download-playlist": {
+ "buttons": {
+ "ok": "OK"
+ },
"detail": "({{playlistSize}} na mga kanta)",
"message": "Dina-download ang Playlist na {{playlistTitle}}",
"title": "Nasimulan na ang pag-download"
@@ -486,6 +519,7 @@
},
"submenu": {
"enabled": "Napagana na",
+ "mode": "Sukatan ng oras",
"percent": "Porsyento",
"seconds": "Segundo"
}
@@ -494,29 +528,36 @@
"presets": "Mga preset",
"skip-existing": "Laktawan ang mga kasalukuyang file"
},
+ "name": "Taga-download",
"renderer": {
"can-not-update-progress": "Hindi ma-update ang progress"
},
"templates": {
- "button": "Mag-download"
+ "button": "I-download"
}
},
"equalizer": {
"description": "Nagdaragdag ng equalizer sa player",
"menu": {
"presets": {
- "label": "Mga Preset"
+ "label": "Mga Preset",
+ "list": {
+ "bass-booster": "Taga-boost ng Bass"
+ }
}
- }
+ },
+ "name": "Equalizer"
},
"exponential-volume": {
- "description": "Ginagawang exponential ang volume slider para mas madaling pumili ng mas mababang volume."
+ "description": "Ginagawang exponential ang volume slider para mas madaling pumili ng mas mababang volume.",
+ "name": "Exponential na Volume"
},
"in-app-menu": {
"description": "Nagbibigay sa mga menu-bar ng magarbo, madilim o kulay ng album",
"menu": {
"hide-dom-window-controls": "Itago ang mga DOM window control"
- }
+ },
+ "name": "In-App na Menu"
},
"lumiastream": {
"description": "Nabibigay suporta sa Lumia Stream",
@@ -524,6 +565,7 @@
},
"lyrics-genius": {
"description": "Nagdaragdag ng suporta sa lyrics para sa karamihan ng kanta",
+ "name": "Lyrics Genius",
"renderer": {
"fetched-lyrics": "Kinuha ang lyrics para sa Genius"
}
@@ -535,6 +577,7 @@
},
"internal": {
"save": "I-save",
+ "track-source": "Source ng Track",
"unknown-user": "Di-kilalang User"
},
"menu": {
@@ -557,6 +600,7 @@
"host": "Nakakonekta bilang Host"
}
},
+ "name": "Music Together [Beta]",
"toast": {
"add-song-failed": "Nabigong magdagdag ng kanta",
"closed": "Nakasara ang Music Together",
@@ -574,7 +618,15 @@
},
"navigation": {
"description": "Ang Next/Back navigation na arrow ay direktang magamit sa interface, katulad sa iyong paboritong browser",
- "name": "Nabigasyon"
+ "name": "Nabigasyon",
+ "templates": {
+ "back": {
+ "title": "Pumunta sa nakaraang page"
+ },
+ "forward": {
+ "title": "Pumunta sa susunod na page"
+ }
+ }
},
"no-google-login": {
"description": "Tanggalin ang mga Google login na button at mga link mula sa interface",
@@ -632,8 +684,10 @@
"description": "Kontrolin nang wasto ang volume gamit ang mousewheel/mga hotkey, na may custom HUD at customizable na volume step",
"menu": {
"arrows-shortcuts": "Lokal na Arrow-key na Kontrol",
- "custom-volume-steps": "I-set ang custom na Volume Step"
+ "custom-volume-steps": "I-set ang custom na Volume Step",
+ "global-shortcuts": "Global na mga Hotkey"
},
+ "name": "Eksaktong Volume",
"prompt": {
"global-shortcuts": {
"keybind-options": {
@@ -657,7 +711,13 @@
}
}
},
- "description": "Payagang mapapalitan ang kalidad ng video na may button sa video overlay"
+ "description": "Payagang mapapalitan ang kalidad ng video na may button sa video overlay",
+ "name": "Taga-palit sa quality ng video",
+ "renderer": {
+ "quality-settings-button": {
+ "label": "Buksan ang taga-palit ng quality"
+ }
+ }
},
"scrobbler": {
"description": "Idagdag ang scrobbling support (last.fm, Listenbrains, atbp.)",
@@ -707,7 +767,8 @@
"play-pause": "Mag-play / Mag-pause",
"previous": "Nakaraan"
},
- "label": "Pumili ng Global na Keybind para sa Songs Control:"
+ "label": "Pumili ng Global na Keybind para sa Songs Control:",
+ "title": "Global na mga Keybind"
}
}
},
@@ -741,12 +802,15 @@
"tooltip": "Gumamit ng malaki, mala-app na effect sa kasalukuyang linya"
},
"focus": {
+ "label": "Focus",
"tooltip": "Gawing puti lamang ang kasalukuyang linya"
},
"offset": {
+ "label": "Offset",
"tooltip": "I-offset sa kanan ang kasalukuyang linya"
},
"scale": {
+ "label": "Scale",
"tooltip": "I-scale ang kasalukuyang linya"
}
},
@@ -828,10 +892,11 @@
"force-hide": "Piliting tanggalin ang video tab",
"mode": {
"submenu": {
- "disabled": "Naka-disable"
+ "disabled": "Di-napagana"
}
}
},
+ "name": "Pag-toggle ng Video",
"templates": {
"button-song": "Kanta"
}
@@ -840,7 +905,8 @@
"description": "Idaragdag ng visualizer sa player",
"menu": {
"visualizer-type": "Uri ng Visualizer"
- }
+ },
+ "name": "Taga-visualize"
}
}
}
diff --git a/src/i18n/resources/hu.json b/src/i18n/resources/hu.json
index 76c0f18d62..d8fcba9df3 100644
--- a/src/i18n/resources/hu.json
+++ b/src/i18n/resources/hu.json
@@ -342,12 +342,24 @@
},
"auth-proxy-adapter": {
"menu": {
+ "disable": "Proxy adapder kikapcsolása",
+ "enable": "Proxy adapter bekapcsolása",
"hostname": {
"label": "Gazdanév"
},
"port": {
"label": "Port"
}
+ },
+ "prompt": {
+ "hostname": {
+ "label": "Adjon meg egy hosztnevet a lokális proxy szerverhez (újraindítást igényel):",
+ "title": "Proxy hosztnév"
+ },
+ "port": {
+ "label": "Adjon meg egy portot a lokális proxy szerverhez (újraindátást igényel):",
+ "title": "Proxy Port"
+ }
}
},
"blur-nav-bar": {
diff --git a/src/i18n/resources/lt.json b/src/i18n/resources/lt.json
index afccff9f56..b38831b9e1 100644
--- a/src/i18n/resources/lt.json
+++ b/src/i18n/resources/lt.json
@@ -150,6 +150,11 @@
"visual-tweaks": {
"label": "Vizualiniai patobulinimai",
"submenu": {
+ "custom-window-title": {
+ "prompt": {
+ "placeholder": "Pavyzdys: YouTube Music"
+ }
+ },
"like-buttons": {
"default": "Numatytasis",
"force-show": "Priversti rodyti",
@@ -357,6 +362,10 @@
},
"templates": {
"title": "Atidaryti antraščių parinkiklį"
+ },
+ "toast": {
+ "caption-changed": "Subtitrai pakeisti į {{language}}",
+ "caption-disabled": "Subtitrai išjungti"
}
},
"compact-sidebar": {
@@ -385,6 +394,17 @@
}
}
},
+ "custom-output-device": {
+ "menu": {
+ "device-selector": "Pasirinkti įrenginį"
+ },
+ "name": "Pasirinktinas išvesties įrenginys",
+ "prompt": {
+ "device-selector": {
+ "title": "Pasirinkite išvesties įrenginį"
+ }
+ }
+ },
"disable-autoplay": {
"description": "Pradeda dainą pristabdytame rėžime",
"menu": {
@@ -408,7 +428,14 @@
"hide-duration-left": "Slėpti kiek liko laiko",
"hide-github-button": "Slėpti \"GitHub\" nuorodos mygtuką",
"play-on-youtube-music": "Leisti ant \"Youtube Music\"",
- "set-inactivity-timeout": "Nustatyti neveiklumo laiką"
+ "set-inactivity-timeout": "Nustatyti neveiklumo laiką",
+ "set-status-display-type": {
+ "submenu": {
+ "artist": "Klausosi {artist]",
+ "title": "Klausosi {song title}",
+ "youtube-music": "Klausosi Youtube Music"
+ }
+ }
},
"name": "\"Discord\" Turtingas Buvimas (Rich Presence)",
"prompt": {
@@ -464,6 +491,19 @@
"description": "Atsisiunčia MP3 / šaltinio garsą tiesiogiai iš sąsajos",
"menu": {
"choose-download-folder": "Pasirinkti atsisiuntimų aplanką",
+ "download-finish-settings": {
+ "prompt": {
+ "last-percent": "Po x procentų",
+ "last-seconds": "Paskutinės x sekundės",
+ "title": "Nustatyti kada atsisiųsti"
+ },
+ "submenu": {
+ "enabled": "Įjungtas",
+ "mode": "Laiko rėžimas",
+ "percent": "Procentai",
+ "seconds": "Sekundės"
+ }
+ },
"download-playlist": "Atsisiųsti grojaraštį",
"presets": "Iš anksto nustatyti nustatymai",
"skip-existing": "Praleisti egzistuojančius failus"
@@ -476,6 +516,13 @@
"button": "Atsisiųsti"
}
},
+ "equalizer": {
+ "menu": {
+ "presets": {
+ "label": "Išankstiniai nustatymai"
+ }
+ }
+ },
"exponential-volume": {
"description": "Padaro garsumo slankiklį eksponentinį, kad būtų lengviau pasirinkti mažesnį garsumą.",
"name": "Eksponentinis garsas"
@@ -512,7 +559,20 @@
"unknown-user": "Nežinomas Naudotojas"
},
"menu": {
- "click-to-copy-id": "Kopijuoti Vedėjo ID"
+ "click-to-copy-id": "Kopijuoti Vedėjo ID",
+ "permission": {
+ "all": "Leisti svečiams valdyti grojaraštį ir grotuvą",
+ "playlist": "Leisti svečiams valdyti grojaraštį"
+ },
+ "set-permission": "Keisti valdymo leidimus",
+ "status": {
+ "disconnected": "Atsijungta",
+ "guest": "Prisijungta kaip svečias"
+ }
+ },
+ "toast": {
+ "add-song-failed": "Nepavyko pridėti dainos",
+ "remove-song-failed": "Nepavyko pašalinti dainos"
}
},
"navigation": {
@@ -607,6 +667,17 @@
"description": "Leidžia pakeisti vaizdo kokybę su mygtuku ant vaizdo perdangos",
"name": "Vaizdo Kokybės Pakeitėjas"
},
+ "scrobbler": {
+ "menu": {
+ "scrobble-alternative-artist": "Naudoti alternatyvius atlikėjus",
+ "scrobble-alternative-title": "Naudoti alternatyvius pavadinimus"
+ },
+ "prompt": {
+ "lastfm": {
+ "api-key": "Last.fm API raktas"
+ }
+ }
+ },
"shortcuts": {
"description": "Leidžia nustatyti visuotinius atkūrimo sparčiuosius klavišus (paleisti / pristabdyti / kitą / ankstesnį) ir išjungti medijos OSD nepaisant medijos klavišų, įjungti Ctrl / CMD + F ieškoti, įjungti Linux MPRIS palaikymą medijos klavišams ir pasirinktinius sparčiuosius klavišus pažengusiems vartotojams.",
"menu": {
@@ -639,6 +710,11 @@
"name": "Rėmėjų blokuotojas"
},
"synced-lyrics": {
+ "description": "Teikia sinchronizuotus dainų žodžius, naudojantis tiekėjais kaip LRClib.",
+ "errors": {
+ "fetch": "⚠️\t\tĮvyko klaida gaunant dainos žodžius.\n\tPabandykite dar karta vėliau.",
+ "not-found": "⚠️ Šiai dainai nerasti dainos tekstai."
+ },
"refetch-btn": {
"fetching": "Gaunama...",
"normal": "Atgauti dainos žodžius"
diff --git a/src/i18n/resources/ms.json b/src/i18n/resources/ms.json
index afd0cef068..4afecd909e 100644
--- a/src/i18n/resources/ms.json
+++ b/src/i18n/resources/ms.json
@@ -462,6 +462,7 @@
"label": "Teks status",
"submenu": {
"artist": "Sedang mendengar {artist}",
+ "title": "Sedang mendengar {tajuk lagu}",
"youtube-music": "Mendengar YouTube Music"
}
}
@@ -498,6 +499,7 @@
"converting": "Menukarkan…",
"done": "Selesai: {{filePath}}",
"download-info": "Memuat turun {{artist}} - {{title}} [{{videoId}}",
+ "download-progress": "Muat turun: {{peratus}}%",
"downloading": "Memuat turun…",
"downloading-counter": "Memuat turun {{current}}/{{total}}…",
"downloading-playlist": "Memuat turun senarai main \"{{playlistTitle}}\" - {{playlistSize}} lagu ({{playlistId}})",
@@ -508,26 +510,42 @@
"playlist-has-only-one-song": "Senarai main hanya mempunyai satu item, memuat turunnya terus",
"playlist-id-not-found": "ID senarai main tidak dijumpai",
"playlist-is-empty": "Senarai main kosong",
+ "playlist-is-mix-or-private": "Ralat dalam mendapatkan senarai info main: pastikan ia tidak peribadi atau di dalam senarai main \"Campuran untuk anda\"\n\n{{ralat}}",
+ "preparing-file": "Menyediakan fail…",
"saving": "Menyimpan…",
"trying-to-get-playlist-id": "Mencuba untuk mendapatkan ID senarai main: {{playlistId}}",
- "video-id-not-found": "Video tidak dijumpai"
+ "video-id-not-found": "Video tidak dijumpai",
+ "writing-id3": "Sedang menulis tag ID3…"
}
},
"description": "Memuat turun audio MP3 / sumber terus dari antara muka",
"menu": {
"choose-download-folder": "Pilih folder muat turun",
"download-finish-settings": {
+ "label": "Muat turun selesai",
"prompt": {
+ "last-percent": "Selepas peratus x",
+ "last-seconds": "Saat x terakhir",
"title": "Konfigurasikan masa untuk memuat turun"
},
"submenu": {
+ "advanced": "Lanjutan",
"enabled": "Dinyalakan",
"mode": "Mod masa",
"percent": "Peratus",
"seconds": "Saat"
}
},
- "download-playlist": "Muat turun senarai main"
+ "download-playlist": "Muat turun senarai main",
+ "presets": "Pratetap",
+ "skip-existing": "Langkau fail sedia ada"
+ },
+ "name": "Pemuat turun",
+ "renderer": {
+ "can-not-update-progress": "Tidak boleh memuat turun perkembangan"
+ },
+ "templates": {
+ "button": "Memuat turun"
}
},
"lumiastream": {
diff --git a/src/i18n/resources/nl.json b/src/i18n/resources/nl.json
index 744a58f3a9..42fa9773b5 100644
--- a/src/i18n/resources/nl.json
+++ b/src/i18n/resources/nl.json
@@ -884,8 +884,10 @@
"name": "TouchBar"
},
"transparent-player": {
+ "description": "Maakt de applicatiescherm doorzichtbaar",
"menu": {
"opacity": {
+ "label": "Dekking",
"submenu": {
"percent": "{{opacity}}%"
}
@@ -899,7 +901,8 @@
"tabbed": "Tabbed"
}
}
- }
+ },
+ "name": "Doorzichtige muziek speler"
},
"tuna-obs": {
"description": "Integratie met OBS's plug-in Tuna",
diff --git a/src/i18n/resources/pl.json b/src/i18n/resources/pl.json
index 72e83a6e08..0d8cb0e344 100644
--- a/src/i18n/resources/pl.json
+++ b/src/i18n/resources/pl.json
@@ -426,7 +426,7 @@
"menu": {
"device-selector": "Wybierz urządzenie"
},
- "name": "Niestandardowe wyjście audio",
+ "name": "Niestandardowe urządzenie wyjścia",
"prompt": {
"device-selector": {
"label": "Wybierz wyjście audio które ma być użyte",
diff --git a/src/i18n/resources/uk.json b/src/i18n/resources/uk.json
index 9ea2e93184..e44dee787a 100644
--- a/src/i18n/resources/uk.json
+++ b/src/i18n/resources/uk.json
@@ -150,6 +150,13 @@
"visual-tweaks": {
"label": "Візуальні налаштування",
"submenu": {
+ "custom-window-title": {
+ "label": "Налаштування заголовка вікна",
+ "prompt": {
+ "label": "Введіть власний заголовок вікна: (залиште порожнім, щоб вимкнути)",
+ "placeholder": "Приклад: YouTube Music"
+ }
+ },
"like-buttons": {
"default": "За замовчуванням",
"force-show": "Завжди показувати",
@@ -409,6 +416,19 @@
}
}
},
+ "custom-output-device": {
+ "description": "Налаштування власного пристрою для відтворення пісень",
+ "menu": {
+ "device-selector": "Обрати пристрій"
+ },
+ "name": "Спеціальний пристрій виводу",
+ "prompt": {
+ "device-selector": {
+ "label": "Оберіть пристрій для виводу медіа",
+ "title": "Оберіть пристрій виводу"
+ }
+ }
+ },
"disable-autoplay": {
"description": "Запуск пісні в режимі \"пауза\"",
"menu": {
@@ -432,7 +452,13 @@
"hide-duration-left": "Приховати тривалість, яка залишилася",
"hide-github-button": "Приховати посилання на GitHub",
"play-on-youtube-music": "Слухати на YouTube Music",
- "set-inactivity-timeout": "Встановити тайм-аут бездіяльності"
+ "set-inactivity-timeout": "Встановити тайм-аут бездіяльності",
+ "set-status-display-type": {
+ "label": "Статус",
+ "submenu": {
+ "youtube-music": "Відтворення з YouTube Music"
+ }
+ }
},
"name": "Активність Discord",
"prompt": {
diff --git a/src/i18n/resources/zh-TW.json b/src/i18n/resources/zh-TW.json
index 771692efc5..e67ef0ab1f 100644
--- a/src/i18n/resources/zh-TW.json
+++ b/src/i18n/resources/zh-TW.json
@@ -151,9 +151,9 @@
"label": "介面設定",
"submenu": {
"custom-window-title": {
- "label": "客製化窗口標題",
+ "label": "自訂窗口標題",
"prompt": {
- "label": "輸入客製化窗口標題: (留空讓其停用)",
+ "label": "輸入自訂視窗標題: (留空將其停用)",
"placeholder": "例如: YouTube 音樂"
}
},
@@ -459,11 +459,11 @@
"play-on-youtube-music": "顯示 Play on YouTube Music 按鈕",
"set-inactivity-timeout": "設定閒置狀態時長",
"set-status-display-type": {
- "label": "狀態文字",
+ "label": "狀態樣式",
"submenu": {
- "artist": "正在聽 {artist}",
- "title": "正在聽 {song title}",
- "youtube-music": "正在聽 YouTube Music"
+ "artist": "正在聆聽 {artist} 的歌曲",
+ "title": "正在聆聽 {song title}",
+ "youtube-music": "正在聆聽 YouTube Music"
}
}
},
@@ -666,8 +666,8 @@
"name": "歌曲播放通知"
},
"performance-improvement": {
- "description": "使用實驗性的腳本以最佳化效能",
- "name": "效能最佳化 [Beta]"
+ "description": "使用實驗性的腳本以優化效能",
+ "name": "效能優化 [Beta]"
},
"picture-in-picture": {
"description": "允許應用程式切換至子母畫面模式",
@@ -765,7 +765,7 @@
"prompt": {
"lastfm": {
"api-key": "Last.fm API 金鑰",
- "api-secret": "Last.fm API 金鑰"
+ "api-secret": "Last.fm API 密鑰"
},
"listenbrainz": {
"token": {
@@ -849,7 +849,7 @@
"label": "無",
"tooltip": "沒有偏好的提供者"
},
- "tooltip": "選擇要使用的預設提供者"
+ "tooltip": "選擇預設的歌詞提供者"
},
"romanization": {
"label": "羅馬拼音化歌詞",
@@ -884,7 +884,7 @@
"name": "觸控列 (Touchbar) 支援"
},
"transparent-player": {
- "description": "讓應用程式視窗變為透明",
+ "description": "讓視窗背景變為透明糢糊",
"menu": {
"opacity": {
"label": "不透明度",
@@ -893,16 +893,16 @@
}
},
"type": {
- "label": "類型",
+ "label": "樣式",
"submenu": {
- "acrylic": "壓克力",
- "mica": "雲母",
+ "acrylic": "壓克力(Acrylic)",
+ "mica": "雲母(Mica)",
"none": "無",
- "tabbed": "分頁式"
+ "tabbed": "分頁式(Tabbed)"
}
}
},
- "name": "透明撥放器"
+ "name": "透明糢糊效果"
},
"tuna-obs": {
"description": "與 OBS 的 Tuna 外掛連線",
@@ -940,9 +940,9 @@
}
},
"visualizer": {
- "description": "新增一個視覺化音樂效果",
+ "description": "在播放器新增視覺化效果",
"menu": {
- "visualizer-type": "視覺化效果類型"
+ "visualizer-type": "視覺化效果樣式"
},
"name": "視覺化效果"
}
diff --git a/src/index.ts b/src/index.ts
index a46e33fed9..5ee798415e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,65 +1,54 @@
+import fs from 'node:fs';
import path from 'node:path';
import url from 'node:url';
-import fs from 'node:fs';
-
+import { languageResources } from 'virtual:i18n';
+import { allPlugins, mainPlugins } from 'virtual:plugins';
+import ErrorHtmlAsset from '@assets/error.html?asset';
+import enhanceWebRequest, {
+ type BetterSession,
+} from '@jellybrick/electron-better-web-request';
+import { deepmerge } from 'deepmerge-ts';
import {
- BrowserWindow,
app,
- screen,
- globalShortcut,
- session,
- shell,
+ BrowserWindow,
+ type BrowserWindowConstructorOptions,
dialog,
+ globalShortcut,
ipcMain,
protocol,
- type BrowserWindowConstructorOptions,
+ screen,
+ session,
+ shell,
} from 'electron';
-import enhanceWebRequest, {
- type BetterSession,
-} from '@jellybrick/electron-better-web-request';
+import electronDebug from 'electron-debug';
import is from 'electron-is';
import unhandled from 'electron-unhandled';
import { autoUpdater } from 'electron-updater';
-import electronDebug from 'electron-debug';
-import { parse } from 'node-html-parser';
-import { deepmerge } from 'deepmerge-ts';
import { deepEqual } from 'fast-equals';
-
-import { allPlugins, mainPlugins } from 'virtual:plugins';
-
-import { languageResources } from 'virtual:i18n';
-
+import { parse } from 'node-html-parser';
import * as config from '@/config';
-
+import { loadI18n, setLanguage, t } from '@/i18n';
+import {
+ forceLoadMainPlugin,
+ forceUnloadMainPlugin,
+ getAllLoadedMainPlugins,
+ loadAllMainPlugins,
+} from '@/loader/main';
import { refreshMenu, setApplicationMenu } from '@/menu';
+import { defaultAuthProxyConfig } from '@/plugins/auth-proxy-adapter/config';
import { fileExists, injectCSS, injectCSSAsFile } from '@/plugins/utils/main';
-import { isTesting } from '@/utils/testing';
-import { setUpTray } from '@/tray';
-import { setupSongInfo } from '@/providers/song-info';
import { restart, setupAppControls } from '@/providers/app-controls';
import {
APP_PROTOCOL,
handleProtocol,
setupProtocolHandler,
} from '@/providers/protocol-handler';
-
-import youtubeMusicCSS from '@/youtube-music.css?inline';
-
-import {
- forceLoadMainPlugin,
- forceUnloadMainPlugin,
- getAllLoadedMainPlugins,
- loadAllMainPlugins,
-} from '@/loader/main';
-
+import { setupSongInfo } from '@/providers/song-info';
+import { setUpTray } from '@/tray';
+import { type PluginConfig } from '@/types/plugins';
import { LoggerPrefix } from '@/utils';
-import { loadI18n, setLanguage, t } from '@/i18n';
-
-import ErrorHtmlAsset from '@assets/error.html?asset';
-
-import { defaultAuthProxyConfig } from '@/plugins/auth-proxy-adapter/config';
-
-import type { PluginConfig } from '@/types/plugins';
+import { isTesting } from '@/utils/testing';
+import youtubeMusicCSS from '@/youtube-music.css?inline';
// Catch errors and log them
unhandled({
@@ -684,7 +673,6 @@ app.whenReady().then(async () => {
shortcutDetails.target !== appLocation ||
shortcutDetails.appUserModelId !== appID
) {
- // eslint-disable-next-line @typescript-eslint/only-throw-error
throw 'needUpdate';
}
} catch (error) {
@@ -943,7 +931,9 @@ function removeContentSecurityPolicy(
!details.responseHeaders['access-control-allow-origin'] &&
!details.responseHeaders['Access-Control-Allow-Origin']
) {
- details.responseHeaders['access-control-allow-origin'] = ['https://music.youtube.com'];
+ details.responseHeaders['access-control-allow-origin'] = [
+ 'https://music.youtube.com',
+ ];
}
}
@@ -953,6 +943,7 @@ function removeContentSecurityPolicy(
// When multiple listeners are defined, apply them all
betterSession.webRequest.setResolver(
'onHeadersReceived',
+ // biome-ignore lint/suspicious/useAwait: Async function required by setResolver API signature even though no await is used
async (listeners) => {
return listeners.reduce(
async (accumulator, listener) => {
diff --git a/src/loader/main.ts b/src/loader/main.ts
index c6202e7c66..531f89eb1b 100644
--- a/src/loader/main.ts
+++ b/src/loader/main.ts
@@ -1,15 +1,14 @@
-import { type BrowserWindow, ipcMain } from 'electron';
+import { allPlugins, mainPlugins } from 'virtual:plugins';
import { deepmerge } from 'deepmerge-ts';
-import { allPlugins, mainPlugins } from 'virtual:plugins';
+import { type BrowserWindow, ipcMain } from 'electron';
import * as config from '@/config';
-import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
-
import { t } from '@/i18n';
+import { type BackendContext } from '@/types/contexts';
-import type { PluginConfig, PluginDef } from '@/types/plugins';
-import type { BackendContext } from '@/types/contexts';
+import { type PluginConfig, type PluginDef } from '@/types/plugins';
+import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
const loadedPluginMap: Record<
string,
@@ -38,12 +37,10 @@ const createContext = (
win.webContents.send(event, ...args);
},
handle: (event: string, listener: CallableFunction) => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return,@typescript-eslint/no-unsafe-call
ipcMain.handle(event, (_, ...args: unknown[]) => listener(...args));
},
on: (event: string, listener: CallableFunction) => {
ipcMain.on(event, (_, ...args: unknown[]) => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
listener(...args);
});
},
diff --git a/src/loader/renderer.ts b/src/loader/renderer.ts
index 8ca76b0225..388c2a4871 100644
--- a/src/loader/renderer.ts
+++ b/src/loader/renderer.ts
@@ -1,13 +1,9 @@
-import { deepmerge } from 'deepmerge-ts';
-
import { rendererPlugins } from 'virtual:plugins';
-
-import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
-
+import { deepmerge } from 'deepmerge-ts';
import { t } from '@/i18n';
-
-import type { RendererContext } from '@/types/contexts';
-import type { PluginConfig, PluginDef } from '@/types/plugins';
+import { type RendererContext } from '@/types/contexts';
+import { type PluginConfig, type PluginDef } from '@/types/plugins';
+import { LoggerPrefix, startPlugin, stopPlugin } from '@/utils';
const unregisterStyleMap: Record void)[]> = {};
const loadedPluginMap: Record<
@@ -31,7 +27,6 @@ export const createContext = (
window.ipcRenderer.invoke(event, ...args),
on: (event: string, listener: CallableFunction) => {
window.ipcRenderer.on(event, (_, ...args: unknown[]) => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call
listener(...args);
});
},
diff --git a/src/navigation.d.ts b/src/navigation.d.ts
index c2912a2ab8..d94cc5a506 100644
--- a/src/navigation.d.ts
+++ b/src/navigation.d.ts
@@ -1,4 +1,4 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
+/** biome-ignore-all lint/suspicious/noExplicitAny: Type definitions for experimental Navigation API use 'any' to match browser API specification */
interface NavigationOptions {
info: any;
diff --git a/src/plugins/api-server/backend/main.ts b/src/plugins/api-server/backend/main.ts
index ae05d9247c..9690e2f843 100644
--- a/src/plugins/api-server/backend/main.ts
+++ b/src/plugins/api-server/backend/main.ts
@@ -1,24 +1,23 @@
-import { jwt } from 'hono/jwt';
-import { OpenAPIHono as Hono } from '@hono/zod-openapi';
-import { cors } from 'hono/cors';
-import { swaggerUI } from '@hono/swagger-ui';
+/** biome-ignore-all lint/suspicious/noAssignInExpressions: Hono framework patterns use assignment expressions in conditionals for concise route handling */
+
import { serve } from '@hono/node-server';
import { createNodeWebSocket } from '@hono/node-ws';
+import { swaggerUI } from '@hono/swagger-ui';
+import { OpenAPIHono as Hono } from '@hono/zod-openapi';
+import { cors } from 'hono/cors';
+import { jwt } from 'hono/jwt';
import { registerCallback } from '@/providers/song-info';
+import {
+ type LikeType,
+ type RepeatMode,
+ type VolumeState,
+} from '@/types/datahost-get-state';
import { createBackend } from '@/utils';
-
-import { JWTPayloadSchema } from './scheme';
-import { registerAuth, registerControl, registerWebsocket } from './routes';
-
import { type APIServerConfig, AuthStrategy } from '../config';
-
-import type { BackendType } from './types';
-import type {
- LikeType,
- RepeatMode,
- VolumeState,
-} from '@/types/datahost-get-state';
+import { registerAuth, registerControl, registerWebsocket } from './routes';
+import { JWTPayloadSchema } from './scheme';
+import { type BackendType } from './types';
export const backend = createBackend({
async start(ctx) {
diff --git a/src/plugins/api-server/backend/routes/websocket.ts b/src/plugins/api-server/backend/routes/websocket.ts
index dc744b4fb0..9b33645fbd 100644
--- a/src/plugins/api-server/backend/routes/websocket.ts
+++ b/src/plugins/api-server/backend/routes/websocket.ts
@@ -1,21 +1,17 @@
-import { createRoute } from '@hono/zod-openapi';
-
import { type NodeWebSocket } from '@hono/node-ws';
-
+import { createRoute } from '@hono/zod-openapi';
+import { type Context, type Next } from 'hono';
+import { type WSContext } from 'hono/ws';
+import { type APIServerConfig } from '@/plugins/api-server/config';
import {
registerCallback,
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
-
+import { type BackendContext } from '@/types/contexts';
+import { type RepeatMode, type VolumeState } from '@/types/datahost-get-state';
import { API_VERSION } from '../api-version';
-
-import type { WSContext } from 'hono/ws';
-import type { Context, Next } from 'hono';
-import type { RepeatMode, VolumeState } from '@/types/datahost-get-state';
-import type { HonoApp } from '../types';
-import type { BackendContext } from '@/types/contexts';
-import type { APIServerConfig } from '@/plugins/api-server/config';
+import { type HonoApp } from '../types';
enum DataTypes {
PlayerInfo = 'PLAYER_INFO',
@@ -130,7 +126,6 @@ export const register = (
}),
upgradeWebSocket(() => ({
onOpen(_, ws) {
- // "Unsafe argument of type `WSContext` assigned to a parameter of type `WSContext`. (@typescript-eslint/no-unsafe-argument)" ????? what?
sockets.add(ws as WSContext);
ws.send(
diff --git a/src/plugins/downloader/main/index.ts b/src/plugins/downloader/main/index.ts
index 902f41abd0..e070eaed2a 100644
--- a/src/plugins/downloader/main/index.ts
+++ b/src/plugins/downloader/main/index.ts
@@ -1,45 +1,41 @@
+import { randomBytes } from 'node:crypto';
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
-import { randomBytes } from 'node:crypto';
-
+import { Mutex } from 'async-mutex';
+import { BG, type BgConfig } from 'bgutils-js';
import { app, type BrowserWindow, dialog, ipcMain } from 'electron';
-import { Innertube, UniversalCache, Utils, YTNodes } from 'youtubei.js';
import is from 'electron-is';
import filenamify from 'filenamify';
-import { Mutex } from 'async-mutex';
-import * as NodeID3 from 'node-id3';
-import { BG, type BgConfig } from 'bgutils-js';
import { lazy } from 'lazy-var';
-
+import { type PlayerErrorMessage } from 'node_modules/youtubei.js/dist/src/parser/nodes';
+import { type VideoInfo } from 'node_modules/youtubei.js/dist/src/parser/youtube';
import {
- cropMaxWidth,
- getFolder,
- sendFeedback as sendFeedback_,
- setBadge,
-} from './utils';
+ type Playlist,
+ type TrackInfo,
+} from 'node_modules/youtubei.js/dist/src/parser/ytmusic';
+import { type FormatOptions } from 'node_modules/youtubei.js/dist/src/types';
+import * as NodeID3 from 'node-id3';
+import { Innertube, UniversalCache, Utils, YTNodes } from 'youtubei.js';
+import { t } from '@/i18n';
+import { getNetFetchAsFetch } from '@/plugins/utils/main';
import {
- registerCallback,
cleanupName,
getImage,
MediaType,
+ registerCallback,
type SongInfo,
SongInfoEvent,
} from '@/providers/song-info';
-import { getNetFetchAsFetch } from '@/plugins/utils/main';
-import { t } from '@/i18n';
-
+import { type BackendContext } from '@/types/contexts';
+import { type GetPlayerResponse } from '@/types/get-player-response';
+import { type DownloaderPluginConfig } from '../index';
import { DefaultPresetList, type Preset, YoutubeFormatList } from '../types';
-
-import type { DownloaderPluginConfig } from '../index';
-import type { BackendContext } from '@/types/contexts';
-import type { GetPlayerResponse } from '@/types/get-player-response';
-import type { FormatOptions } from 'node_modules/youtubei.js/dist/src/types';
-import type { VideoInfo } from 'node_modules/youtubei.js/dist/src/parser/youtube';
-import type { PlayerErrorMessage } from 'node_modules/youtubei.js/dist/src/parser/nodes';
-import type {
- TrackInfo,
- Playlist,
-} from 'node_modules/youtubei.js/dist/src/parser/ytmusic';
+import {
+ cropMaxWidth,
+ getFolder,
+ sendFeedback as sendFeedback_,
+ setBadge,
+} from './utils';
type CustomSongInfo = SongInfo & { trackId?: string };
@@ -87,7 +83,6 @@ const sendError = (error: Error, source?: string) => {
const songNameMessage = source ? `\nin ${source}` : '';
const cause = error.cause
? `\n\n${
- // eslint-disable-next-line @typescript-eslint/no-base-to-string,@typescript-eslint/restrict-template-expressions
error.cause instanceof Error ? error.cause.toString() : error.cause
}`
: '';
@@ -126,6 +121,7 @@ export const onMainLoad = async ({
yt = await Innertube.create({
cache: new UniversalCache(false),
+ player_id: '0004de42',
cookie: await getCookieFromWindow(win),
generate_session_locally: true,
fetch: getNetFetchAsFetch(),
@@ -170,7 +166,6 @@ export const onMainLoad = async ({
if (interpreterJavascript) {
// This is a workaround to run the interpreterJavascript code
// Maybe there is a better way to do this (e.g. https://github.com/Siubaak/sval ?)
- // eslint-disable-next-line @typescript-eslint/no-implied-eval,@typescript-eslint/no-unsafe-call
new Function(interpreterJavascript)();
const poTokenResult = await BG.PoToken.generate({
diff --git a/src/plugins/music-together/connection.ts b/src/plugins/music-together/connection.ts
index a85ab0611c..8c41cff76d 100644
--- a/src/plugins/music-together/connection.ts
+++ b/src/plugins/music-together/connection.ts
@@ -1,12 +1,12 @@
+import delay from 'delay';
import {
type DataConnection,
Peer,
type PeerError,
PeerErrorType,
} from 'peerjs';
-import delay from 'delay';
-import type { Permission, Profile, VideoData } from './types';
+import { type Permission, type Profile, type VideoData } from './types';
export type ConnectionEventMap = {
ADD_SONGS: { videoList: VideoData[]; index?: number };
@@ -123,6 +123,7 @@ export class Connection {
}
/* public */
+ // biome-ignore lint/suspicious/useAwait: Method returns a promise to maintain async API consistency for future enhancements
async waitForReady() {
return this.waitOpen.promise;
}
@@ -188,6 +189,7 @@ export class Connection {
}
/* privates */
+ // biome-ignore lint/suspicious/useAwait: Method returns a promise to maintain async API consistency with other connection methods
private async registerConnection(conn: DataConnection) {
return new Promise((resolve, reject) => {
this.peer.once('error', (err) => {
diff --git a/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-animationframe.js b/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-animationframe.js
index bffcc97726..9e2279cc04 100644
--- a/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-animationframe.js
+++ b/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-animationframe.js
@@ -24,9 +24,9 @@ SOFTWARE.
*/
-/* eslint-disable */
+/** biome-ignore-all lint: Third-party library maintained externally, modifications should be avoided to ease future updates */
-export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
+export const injectCpuTamerByAnimationFrame = (__CONTEXT__) => {
'use strict';
const win = this instanceof Window ? this : window;
@@ -37,9 +37,12 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
win[hkey_script] = true;
/** @type {globalThis.PromiseConstructor} */
- const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
+ const Promise = (async () => {})().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
const PromiseExternal = ((resolve_, reject_) => {
- const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
+ const h = (resolve, reject) => {
+ resolve_ = resolve;
+ reject_ = reject;
+ };
return class PromiseExternal extends Promise {
constructor(cb = h) {
super(cb);
@@ -57,46 +60,56 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
// https://gist.github.com/cvan/042b2448fcecefafbb6a91469484cdf8
try {
const canvas = document.createElement('canvas');
- return !!(canvas.getContext('webgl') || canvas.getContext('experimental-webgl'));
+ return !!(
+ canvas.getContext('webgl') || canvas.getContext('experimental-webgl')
+ );
} catch (e) {
return false;
}
})();
if (!isGPUAccelerationAvailable) {
- throw new Error('Your browser does not support GPU Acceleration. YouTube CPU Tamer by AnimationFrame is skipped.');
+ throw new Error(
+ 'Your browser does not support GPU Acceleration. YouTube CPU Tamer by AnimationFrame is skipped.',
+ );
}
const timeupdateDT = (() => {
-
window.__j6YiAc__ = 1;
- document.addEventListener('timeupdate', () => {
- window.__j6YiAc__ = Date.now();
- }, true);
+ document.addEventListener(
+ 'timeupdate',
+ () => {
+ window.__j6YiAc__ = Date.now();
+ },
+ true,
+ );
let kz = -1;
try {
kz = top.__j6YiAc__;
- } catch (e) {
-
- }
+ } catch (e) {}
return kz >= 1 ? () => top.__j6YiAc__ : () => window.__j6YiAc__;
-
})();
const cleanContext = async (win) => {
const waitFn = requestAnimationFrame; // shall have been binded to window
try {
let mx = 16; // MAX TRIAL
- const frameId = 'vanillajs-iframe-v1'
+ const frameId = 'vanillajs-iframe-v1';
let frame = document.getElementById(frameId);
let removeIframeFn = null;
if (!frame) {
frame = document.createElement('iframe');
frame.id = frameId;
- const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
+ const blobURL =
+ typeof webkitCancelAnimationFrame === 'function' &&
+ typeof kagi === 'undefined'
+ ? (frame.src = URL.createObjectURL(
+ new Blob([], { type: 'text/html' }),
+ ))
+ : null; // avoid Brave Crash
frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
n.appendChild(frame);
@@ -107,26 +120,48 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
removeIframeFn = (setTimeout) => {
const removeIframeOnDocumentReady = (e) => {
- e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
+ e &&
+ win.removeEventListener(
+ 'DOMContentLoaded',
+ removeIframeOnDocumentReady,
+ false,
+ );
e = n;
n = win = removeIframeFn = 0;
setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
- }
+ };
if (!setTimeout || document.readyState !== 'loading') {
removeIframeOnDocumentReady();
} else {
- win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
+ win.addEventListener(
+ 'DOMContentLoaded',
+ removeIframeOnDocumentReady,
+ false,
+ );
}
- }
+ };
}
while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
const fc = frame.contentWindow;
- if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
+ if (!fc) throw 'window is not found.'; // throw error if root is null due to exceeding MAX TRIAL
try {
- const { requestAnimationFrame, setInterval, setTimeout, clearInterval, clearTimeout } = fc;
- const res = { requestAnimationFrame, setInterval, setTimeout, clearInterval, clearTimeout };
+ const {
+ requestAnimationFrame,
+ setInterval,
+ setTimeout,
+ clearInterval,
+ clearTimeout,
+ } = fc;
+ const res = {
+ requestAnimationFrame,
+ setInterval,
+ setTimeout,
+ clearInterval,
+ clearTimeout,
+ };
for (let k in res) res[k] = res[k].bind(win); // necessary
- if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
+ if (removeIframeFn)
+ Promise.resolve(res.setTimeout).then(removeIframeFn);
return res;
} catch (e) {
if (removeIframeFn) removeIframeFn();
@@ -138,11 +173,16 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
}
};
- cleanContext(win).then(__CONTEXT__ => {
-
+ cleanContext(win).then((__CONTEXT__) => {
if (!__CONTEXT__) return null;
- const { requestAnimationFrame, setTimeout, setInterval, clearTimeout, clearInterval } = __CONTEXT__;
+ const {
+ requestAnimationFrame,
+ setTimeout,
+ setInterval,
+ clearTimeout,
+ clearInterval,
+ } = __CONTEXT__;
/** @type {Function|null} */
let afInterupter = null;
@@ -150,13 +190,13 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
const getRAFHelper = () => {
const asc = document.createElement('a-f');
if (!('onanimationiteration' in asc)) {
- return (resolve) => requestAnimationFrame(afInterupter = resolve);
+ return (resolve) => requestAnimationFrame((afInterupter = resolve));
}
asc.id = 'a-f';
let qr = null;
asc.onanimationiteration = function () {
if (qr !== null) qr = (qr(), null);
- }
+ };
if (!document.getElementById('afscript')) {
const style = document.createElement('style');
style.id = 'afscript';
@@ -189,7 +229,10 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
`;
(document.head || document.documentElement).appendChild(style);
}
- document.documentElement.insertBefore(asc, document.documentElement.firstChild);
+ document.documentElement.insertBefore(
+ asc,
+ document.documentElement.firstChild,
+ );
return (resolve) => (qr = afInterupter = resolve);
};
@@ -203,7 +246,7 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
const afResolve = async (rX) => {
await new Promise(rafPN);
rX.resolved = true;
- const t = afix = (afix & 1073741823) + 1;
+ const t = (afix = (afix & 1073741823) + 1);
return rX.resolve(t), t;
};
const eFunc = async () => {
@@ -217,12 +260,13 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
} else {
const vP = !uP ? (afPromiseP = new PromiseExternal()) : null;
const vQ = !uQ ? (afPromiseQ = new PromiseExternal()) : null;
- if (uQ) await uQ; else if (uP) await uP;
+ if (uQ) await uQ;
+ else if (uP) await uP;
if (vP) t = await afResolve(vP);
if (vQ) t = await afResolve(vQ);
}
return t;
- }
+ };
const inExec = new Set();
const wFunc = async (handler, wStore) => {
try {
@@ -244,9 +288,15 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
};
const sFunc = (propFunc) => {
return (func, ms = 0, ...args) => {
- if (typeof func === 'function') { // ignore all non-function parameter (e.g. string)
+ if (typeof func === 'function') {
+ // ignore all non-function parameter (e.g. string)
const wStore = { dt: Date.now() };
- return (wStore.cid = propFunc(wFunc, ms, (args.length > 0 ? func.bind(null, ...args) : func), wStore));
+ return (wStore.cid = propFunc(
+ wFunc,
+ ms,
+ args.length > 0 ? func.bind(null, ...args) : func,
+ wStore,
+ ));
} else {
return propFunc(func, ms, ...args);
}
@@ -269,18 +319,19 @@ export const injectCpuTamerByAnimationFrame = ((__CONTEXT__) => {
win.setInterval.toString = setInterval.toString.bind(setInterval);
win.clearTimeout.toString = clearTimeout.toString.bind(clearTimeout);
win.clearInterval.toString = clearInterval.toString.bind(clearInterval);
- } catch (e) { console.warn(e) }
-
+ } catch (e) {
+ console.warn(e);
+ }
})();
let mInterupter = null;
setInterval(() => {
if (mInterupter === afInterupter) {
- if (mInterupter !== null) afInterupter = mInterupter = (mInterupter(), null);
+ if (mInterupter !== null)
+ afInterupter = mInterupter = (mInterupter(), null);
} else {
mInterupter = afInterupter;
}
}, 125);
});
-
-});
+};
diff --git a/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-dom-mutation.js b/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-dom-mutation.js
index cc5a9fbdf4..922153758d 100644
--- a/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-dom-mutation.js
+++ b/src/plugins/performance-improvement/scripts/cpu-tamer/cpu-tamer-by-dom-mutation.js
@@ -24,9 +24,9 @@ SOFTWARE.
*/
-/* eslint-disable */
+/** biome-ignore-all lint: Third-party library maintained externally, modifications should be avoided to ease future updates */
-export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
+export const injectCpuTamerByDomMutation = (__CONTEXT__) => {
'use strict';
const win = this instanceof Window ? this : window;
@@ -37,9 +37,12 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
win[hkey_script] = true;
/** @type {globalThis.PromiseConstructor} */
- const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
+ const Promise = (async () => {})().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
const PromiseExternal = ((resolve_, reject_) => {
- const h = (resolve, reject) => { resolve_ = resolve; reject_ = reject };
+ const h = (resolve, reject) => {
+ resolve_ = resolve;
+ reject_ = reject;
+ };
return class PromiseExternal extends Promise {
constructor(cb = h) {
super(cb);
@@ -79,13 +82,19 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
const waitFn = requestAnimationFrame; // shall have been binded to window
try {
let mx = 16; // MAX TRIAL
- const frameId = 'vanillajs-iframe-v1'
+ const frameId = 'vanillajs-iframe-v1';
let frame = document.getElementById(frameId);
let removeIframeFn = null;
if (!frame) {
frame = document.createElement('iframe');
frame.id = frameId;
- const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
+ const blobURL =
+ typeof webkitCancelAnimationFrame === 'function' &&
+ typeof kagi === 'undefined'
+ ? (frame.src = URL.createObjectURL(
+ new Blob([], { type: 'text/html' }),
+ ))
+ : null; // avoid Brave Crash
frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
n.appendChild(frame);
@@ -96,26 +105,48 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
removeIframeFn = (setTimeout) => {
const removeIframeOnDocumentReady = (e) => {
- e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
+ e &&
+ win.removeEventListener(
+ 'DOMContentLoaded',
+ removeIframeOnDocumentReady,
+ false,
+ );
e = n;
n = win = removeIframeFn = 0;
setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
- }
+ };
if (!setTimeout || document.readyState !== 'loading') {
removeIframeOnDocumentReady();
} else {
- win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
+ win.addEventListener(
+ 'DOMContentLoaded',
+ removeIframeOnDocumentReady,
+ false,
+ );
}
- }
+ };
}
while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
const fc = frame.contentWindow;
- if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
+ if (!fc) throw 'window is not found.'; // throw error if root is null due to exceeding MAX TRIAL
try {
- const { requestAnimationFrame, setInterval, setTimeout, clearInterval, clearTimeout } = fc;
- const res = { requestAnimationFrame, setInterval, setTimeout, clearInterval, clearTimeout };
+ const {
+ requestAnimationFrame,
+ setInterval,
+ setTimeout,
+ clearInterval,
+ clearTimeout,
+ } = fc;
+ const res = {
+ requestAnimationFrame,
+ setInterval,
+ setTimeout,
+ clearInterval,
+ clearTimeout,
+ };
for (let k in res) res[k] = res[k].bind(win); // necessary
- if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
+ if (removeIframeFn)
+ Promise.resolve(res.setTimeout).then(removeIframeFn);
return res;
} catch (e) {
if (removeIframeFn) removeIframeFn();
@@ -127,28 +158,27 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
}
};
-
const { _setAttribute, _insertBefore, _hasAttribute } = (() => {
let _setAttribute = Element.prototype.setAttribute;
try {
_setAttribute = ShadyDOM.nativeMethods.setAttribute || _setAttribute;
- } catch (e) { }
+ } catch (e) {}
let _hasAttribute = Element.prototype.hasAttribute;
try {
_hasAttribute = ShadyDOM.nativeMethods.hasAttribute || _hasAttribute;
- } catch (e) { }
+ } catch (e) {}
let _insertBefore = Node.prototype.insertBefore;
try {
_insertBefore = ShadyDOM.nativeMethods.insertBefore || _insertBefore;
- } catch (e) { }
- return { _setAttribute, _insertBefore, _hasAttribute};
+ } catch (e) {}
+ return { _setAttribute, _insertBefore, _hasAttribute };
})();
- cleanContext(win).then(__CONTEXT__ => {
-
+ cleanContext(win).then((__CONTEXT__) => {
if (!__CONTEXT__) return null;
- const { setTimeout, setInterval, clearTimeout, clearInterval } = __CONTEXT__;
+ const { setTimeout, setInterval, clearTimeout, clearInterval } =
+ __CONTEXT__;
/*
/-** @type {Function|null} *-/
@@ -160,14 +190,22 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
if (!_dm) {
_dm = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
_dm.id = 'd-m';
- _insertBefore.call(document.documentElement, _dm, document.documentElement.firstChild);
+ _insertBefore.call(
+ document.documentElement,
+ _dm,
+ document.documentElement.firstChild,
+ );
}
const dm = _dm;
dm._setAttribute = _setAttribute;
dm._hasAttribute = _hasAttribute;
let j = 0;
let attributeName_;
- while (dm._hasAttribute(attributeName_ = `dm-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`)) {
+ while (
+ dm._hasAttribute(
+ (attributeName_ = `dm-${Math.floor(Math.random() * 314159265359 + 314159265359).toString(36)}`),
+ )
+ ) {
// none
}
const attributeName = attributeName_;
@@ -180,9 +218,16 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
sr_.resolve();
}
});
- mo.observe(document, { childList: true, subtree: true, attributes: true });
+ mo.observe(document, {
+ childList: true,
+ subtree: true,
+ attributes: true,
+ });
return () => {
- return sr || (sr = (dm._setAttribute(attributeName, ++j), (new PromiseExternal()))); // mutationcallback in next macrotask
+ return (
+ sr ||
+ (sr = (dm._setAttribute(attributeName, ++j), new PromiseExternal()))
+ ); // mutationcallback in next macrotask
};
};
@@ -196,7 +241,7 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
const dmResolve = async (rX) => {
await dmSN();
rX.resolved = true;
- const t = dmix = (dmix & 1073741823) + 1;
+ const t = (dmix = (dmix & 1073741823) + 1);
return rX.resolve(t), t;
};
const eFunc = async () => {
@@ -210,12 +255,13 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
} else {
const vP = !uP ? (dmPromiseP = new PromiseExternal()) : null;
const vQ = !uQ ? (dmPromiseQ = new PromiseExternal()) : null;
- if (uQ) await uQ; else if (uP) await uP;
+ if (uQ) await uQ;
+ else if (uP) await uP;
if (vP) t = await dmResolve(vP);
if (vQ) t = await dmResolve(vQ);
}
return t;
- }
+ };
const inExec = new Set();
const wFunc = async (handler, wStore) => {
try {
@@ -237,9 +283,15 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
};
const sFunc = (propFunc) => {
return (func, ms = 0, ...args) => {
- if (typeof func === 'function') { // ignore all non-function parameter (e.g. string)
+ if (typeof func === 'function') {
+ // ignore all non-function parameter (e.g. string)
const wStore = { dt: Date.now() };
- return (wStore.cid = propFunc(wFunc, ms, (args.length > 0 ? func.bind(null, ...args) : func), wStore));
+ return (wStore.cid = propFunc(
+ wFunc,
+ ms,
+ args.length > 0 ? func.bind(null, ...args) : func,
+ wStore,
+ ));
} else {
return propFunc(func, ms, ...args);
}
@@ -262,8 +314,9 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
win.setInterval.toString = setInterval.toString.bind(setInterval);
win.clearTimeout.toString = clearTimeout.toString.bind(clearTimeout);
win.clearInterval.toString = clearInterval.toString.bind(clearInterval);
- } catch (e) { console.warn(e) }
-
+ } catch (e) {
+ console.warn(e);
+ }
})();
/*
@@ -277,5 +330,4 @@ export const injectCpuTamerByDomMutation = ((__CONTEXT__) => {
}, 125);
*/
});
-
-});
+};
diff --git a/src/plugins/performance-improvement/scripts/rm3/rm3.js b/src/plugins/performance-improvement/scripts/rm3/rm3.js
index 1d82e3a699..5ffaf4880d 100644
--- a/src/plugins/performance-improvement/scripts/rm3/rm3.js
+++ b/src/plugins/performance-improvement/scripts/rm3/rm3.js
@@ -24,7 +24,7 @@ SOFTWARE.
*/
-/* eslint-disable */
+/** biome-ignore-all lint: Third-party library maintained externally, modifications should be avoided to ease future updates */
export const rm3 = {};
@@ -54,7 +54,7 @@ export const injectRm3 = () => {
); // [[debug]]
};
- const insp = (o) => o ? o.polymerController || o.inst || o || 0 : o || 0;
+ const insp = (o) => (o ? o.polymerController || o.inst || o || 0 : o || 0);
const indr = (o) => insp(o).$ || o.$ || 0;
const getProto = (element) => {
@@ -339,9 +339,9 @@ export const injectRm3 = () => {
// rm3.list = [];
- const operations = rm3.operations = new Set(); // to find out the "oldest elements"
+ const operations = (rm3.operations = new Set()); // to find out the "oldest elements"
- const availablePools = rm3.availablePools = new Map(); // those "old elements" can be used
+ const availablePools = (rm3.availablePools = new Map()); // those "old elements" can be used
let lastTimeCheck = 0;
const reuseRecord_ = new LimitedSizeSet(256); // [[debug]]
@@ -419,7 +419,7 @@ export const injectRm3 = () => {
let availablePool = availablePools.get(eKey);
if (!availablePool)
- availablePools.set(eKey, availablePool = new LinkedArray());
+ availablePools.set(eKey, (availablePool = new LinkedArray()));
if (!(availablePool instanceof LinkedArray)) throw new Error();
DEBUG_OPT &&
console.log(3885, 'add key', eKey, availablePools.size);
@@ -431,7 +431,7 @@ export const injectRm3 = () => {
// }, 8000)
let pivotNode = pivotNodes.get(availablePool);
if (!pivotNode)
- pivotNodes.set(availablePool, pivotNode = availablePool.head); // cached the previous newest node (head) as pivotNode
+ pivotNodes.set(availablePool, (pivotNode = availablePool.head)); // cached the previous newest node (head) as pivotNode
availablePool.insertBeforeNode(pivotNode, entryRecord); // head = newest, tail = oldest
}
diff --git a/src/plugins/precise-volume/override.ts b/src/plugins/precise-volume/override.ts
index f8f3d3845c..2a3b06acf2 100644
--- a/src/plugins/precise-volume/override.ts
+++ b/src/plugins/precise-volume/override.ts
@@ -9,7 +9,6 @@ function overrideAddEventListener() {
// YO WHAT ARE YOU DOING NOW?!?!
// Save native addEventListener
// @ts-expect-error - We know what we're doing
- // eslint-disable-next-line @typescript-eslint/unbound-method
Element.prototype._addEventListener = Element.prototype.addEventListener;
// Override addEventListener to Ignore specific events in volume-slider
Element.prototype.addEventListener = function (
@@ -18,7 +17,7 @@ function overrideAddEventListener() {
useCapture = false,
) {
if (!(ignored.id.includes(this.id) && ignored.types.includes(type))) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
+ // biome-ignore lint/suspicious/noExplicitAny: Accessing custom property on Element prototype that stores original addEventListener
(this as any)._addEventListener(type, listener, useCapture);
} else if (window.electronIs.dev()) {
console.log(`Ignoring event: "${this.id}.${type}()"`);
@@ -32,12 +31,11 @@ export const overrideListener = () => {
window.addEventListener(
'load',
() => {
- /* eslint-disable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access */
- Element.prototype.addEventListener = (
- Element.prototype as any
- )._addEventListener;
+ Element.prototype.addEventListener =
+ // biome-ignore lint/suspicious/noExplicitAny: Restoring original addEventListener from custom property
+ (Element.prototype as any)._addEventListener;
+ // biome-ignore lint/suspicious/noExplicitAny: Cleaning up custom property after restoration
(Element.prototype as any)._addEventListener = undefined;
- /* eslint-enable @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access */
},
{ once: true },
);
diff --git a/src/plugins/scrobbler/services/lastfm.ts b/src/plugins/scrobbler/services/lastfm.ts
index 8397a7de50..2f312385cc 100644
--- a/src/plugins/scrobbler/services/lastfm.ts
+++ b/src/plugins/scrobbler/services/lastfm.ts
@@ -1,14 +1,12 @@
import crypto from 'node:crypto';
import { BrowserWindow, dialog, net } from 'electron';
-
-import { ScrobblerBase } from './base';
-
import { t } from '@/i18n';
+import { type SongInfo } from '@/providers/song-info';
-import type { ScrobblerPluginConfig } from '../index';
-import type { SetConfType } from '../main';
-import type { SongInfo } from '@/providers/song-info';
+import { type ScrobblerPluginConfig } from '../index';
+import { type SetConfType } from '../main';
+import { ScrobblerBase } from './base';
interface LastFmData {
method: string;
@@ -255,6 +253,7 @@ const createToken = async ({
let authWindowOpened = false;
let latestAuthResult = false;
+// biome-ignore lint/suspicious/useAwait: Function returns a Promise and contains nested async callbacks for window navigation
const authenticate = async (
config: ScrobblerPluginConfig,
mainWindow: BrowserWindow,
diff --git a/src/plugins/shortcuts/mpris-service.d.ts b/src/plugins/shortcuts/mpris-service.d.ts
index 44281819ad..25d6276865 100644
--- a/src/plugins/shortcuts/mpris-service.d.ts
+++ b/src/plugins/shortcuts/mpris-service.d.ts
@@ -61,7 +61,7 @@ declare module '@jellybrick/mpris-service' {
position: number;
}
- declare class Player extends EventEmitter {
+ declare abstract class Player extends EventEmitter {
constructor(opts: {
name: string;
identity: string;
@@ -180,10 +180,8 @@ declare module '@jellybrick/mpris-service' {
setProperty(property: string, valuePlain: unknown): void;
}
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface RootInterface {}
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface PlayerInterface {}
export interface TracklistInterface {
diff --git a/src/plugins/utils/main/fetch.ts b/src/plugins/utils/main/fetch.ts
index b36eaf3d9a..791b3a5e71 100644
--- a/src/plugins/utils/main/fetch.ts
+++ b/src/plugins/utils/main/fetch.ts
@@ -1,6 +1,7 @@
import { net } from 'electron';
export const getNetFetchAsFetch = () =>
+ // biome-ignore lint/suspicious/useAwait: Must remain async to match the fetch API signature which returns Promise
(async (input: RequestInfo | URL, init?: RequestInit) => {
const url =
typeof input === 'string'
diff --git a/src/plugins/visualizer/index.ts b/src/plugins/visualizer/index.ts
index 0d1dbbaaf2..78a1e03783 100644
--- a/src/plugins/visualizer/index.ts
+++ b/src/plugins/visualizer/index.ts
@@ -1,12 +1,12 @@
-import emptyStyle from './empty-player.css?inline';
+import { t } from '@/i18n';
import { createPlugin } from '@/utils';
-import { type Visualizer } from './visualizers/visualizer';
+import emptyStyle from './empty-player.css?inline';
import {
ButterchurnVisualizer as butterchurn,
VudioVisualizer as vudio,
WaveVisualizer as wave,
} from './visualizers';
-import { t } from '@/i18n';
+import { type Visualizer } from './visualizers/visualizer';
type WaveColor = {
gradient: string[];
@@ -151,7 +151,7 @@ export default createPlugin({
async onPlayerApiReady(_, { getConfig }) {
const config = await getConfig();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ // biome-ignore lint/suspicious/noExplicitAny: Visualizer constructors accept varying argument types depending on the visualizer implementation
let visualizerType: { new (...args: any[]): Visualizer } = vudio;
if (config.type === 'wave') {
diff --git a/src/providers/song-info-front.ts b/src/providers/song-info-front.ts
index 9bed8abc37..71e6f5baca 100644
--- a/src/providers/song-info-front.ts
+++ b/src/providers/song-info-front.ts
@@ -1,16 +1,13 @@
-import { singleton } from './decorators';
-
-import { LikeType, type GetState } from '@/types/datahost-get-state';
-
-import type { YoutubePlayer } from '@/types/youtube-player';
-import type {
- AlbumDetails,
- PlayerOverlays,
- VideoDataChangeValue,
+import { type GetState, LikeType } from '@/types/datahost-get-state';
+import {
+ type AlbumDetails,
+ type PlayerOverlays,
+ type VideoDataChangeValue,
} from '@/types/player-api-events';
-
-import type { SongInfo } from './song-info';
-import type { VideoDataChanged } from '@/types/video-data-changed';
+import { type VideoDataChanged } from '@/types/video-data-changed';
+import { type YoutubePlayer } from '@/types/youtube-player';
+import { singleton } from './decorators';
+import { type SongInfo } from './song-info';
const DATAUPDATED_FALLBACK_TIMEOUT_MS = 1500;
@@ -246,7 +243,6 @@ export const setupSongInfo = (api: YoutubePlayer) => {
const videoEventDispatcher = async (
name: string,
videoData: VideoDataChangeValue,
- // eslint-disable-next-line @typescript-eslint/require-await
) =>
document.dispatchEvent(
new CustomEvent('videodatachange', {
diff --git a/src/renderer.ts b/src/renderer.ts
index b535a89b09..fd86ddc40b 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -1,7 +1,15 @@
import i18next from 'i18next';
-
-import { startingPages } from './providers/extracted-data';
-import { setupSongInfo } from './providers/song-info-front';
+import { t as i18t, loadI18n, setLanguage } from '@/i18n';
+import { type PluginConfig } from '@/types/plugins';
+import { type QueueElement } from '@/types/queue';
+import { type SearchBoxElement } from '@/types/search-box-element';
+import { type YouTubeMusicAppElement } from '@/types/youtube-music-app-element';
+import { type QueueResponse } from '@/types/youtube-music-desktop-internal';
+import { type YoutubePlayer } from '@/types/youtube-player';
+import {
+ defaultTrustedTypePolicy,
+ registerWindowDefaultTrustedTypePolicy,
+} from '@/utils/trusted-types';
import {
createContext,
forceLoadRendererPlugin,
@@ -10,20 +18,8 @@ import {
getLoadedRendererPlugin,
loadAllRendererPlugins,
} from './loader/renderer';
-
-import { loadI18n, setLanguage, t as i18t } from '@/i18n';
-
-import {
- defaultTrustedTypePolicy,
- registerWindowDefaultTrustedTypePolicy,
-} from '@/utils/trusted-types';
-
-import type { PluginConfig } from '@/types/plugins';
-import type { YoutubePlayer } from '@/types/youtube-player';
-import type { QueueElement } from '@/types/queue';
-import type { QueueResponse } from '@/types/youtube-music-desktop-internal';
-import type { YouTubeMusicAppElement } from '@/types/youtube-music-app-element';
-import type { SearchBoxElement } from '@/types/search-box-element';
+import { startingPages } from './providers/extracted-data';
+import { setupSongInfo } from './providers/song-info-front';
let api: (Element & YoutubePlayer) | null = null;
let isPluginLoaded = false;
@@ -88,9 +84,9 @@ async function onApiLoaded() {
window.ipcRenderer.on('ytmd:seek-by', (_, t: number) => api!.seekBy(t));
window.ipcRenderer.on('ytmd:shuffle', () => {
document
- .querySelector<
- HTMLElement & { queue: { shuffle: () => void } }
- >('ytmusic-player-bar')
+ .querySelector void } }>(
+ 'ytmusic-player-bar',
+ )
?.queue.shuffle();
});
@@ -120,17 +116,17 @@ async function onApiLoaded() {
window.ipcRenderer.on('ytmd:switch-repeat', (_, repeat = 1) => {
for (let i = 0; i < repeat; i++) {
document
- .querySelector<
- HTMLElement & { onRepeatButtonClick: () => void }
- >('ytmusic-player-bar')
+ .querySelector void }>(
+ 'ytmusic-player-bar',
+ )
?.onRepeatButtonClick();
}
});
window.ipcRenderer.on('ytmd:update-volume', (_, volume: number) => {
document
- .querySelector<
- HTMLElement & { updateVolume: (volume: number) => void }
- >('ytmusic-player-bar')
+ .querySelector void }>(
+ 'ytmusic-player-bar',
+ )
?.updateVolume(volume);
});
@@ -169,9 +165,9 @@ async function onApiLoaded() {
window.ipcRenderer.on('ytmd:toggle-mute', (_) => {
document
- .querySelector<
- HTMLElement & { onVolumeClick: () => void }
- >('ytmusic-player-bar')
+ .querySelector void }>(
+ 'ytmusic-player-bar',
+ )
?.onVolumeClick();
});
@@ -402,10 +398,9 @@ async function onApiLoaded() {
* YouTube Music still using ES5, so we need to define custom elements using ES5 style
*/
const defineYTMDTransElements = () => {
+ // biome-ignore lint/suspicious/noEmptyBlockStatements: Empty constructor required for ES5-style custom element definition
const YTMDTrans = function () {};
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
YTMDTrans.prototype = Object.create(HTMLElement.prototype);
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
YTMDTrans.prototype.connectedCallback = function () {
const that = this as HTMLElement;
const key = that.getAttribute('key');
diff --git a/src/types/contexts.ts b/src/types/contexts.ts
index 166bdd98de..c95fa0fa2c 100644
--- a/src/types/contexts.ts
+++ b/src/types/contexts.ts
@@ -1,10 +1,10 @@
-import type {
- IpcMain,
- IpcRenderer,
- WebContents,
- BrowserWindow,
+import {
+ type BrowserWindow,
+ type IpcMain,
+ type IpcRenderer,
+ type WebContents,
} from 'electron';
-import type { PluginConfig } from '@/types/plugins';
+import { type PluginConfig } from '@/types/plugins';
export interface BaseContext {
getConfig: () => Promise | Config;
@@ -29,7 +29,6 @@ export interface MenuContext
refresh: () => Promise | void;
}
-// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface PreloadContext
extends BaseContext {}
diff --git a/src/types/datahost-get-state.ts b/src/types/datahost-get-state.ts
index 9a4de26eb8..1c3477c11b 100644
--- a/src/types/datahost-get-state.ts
+++ b/src/types/datahost-get-state.ts
@@ -1,4 +1,4 @@
-import type { PlayerConfig } from '@/types/get-player-response';
+import { type PlayerConfig } from '@/types/get-player-response';
export interface GetState {
castStatus: CastStatus;
@@ -31,7 +31,6 @@ export interface Download {
isLeaderTab: boolean;
}
-// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface Entities {}
export interface LikeStatus {
diff --git a/src/types/get-player-response.ts b/src/types/get-player-response.ts
index ac51b5beb9..b9250f3f3d 100644
--- a/src/types/get-player-response.ts
+++ b/src/types/get-player-response.ts
@@ -108,7 +108,6 @@ export interface Endpoint {
watchEndpoint: WatchEndpoint;
}
-// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export interface CommandMetadata {}
export interface WatchEndpoint {
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 427082ca77..6bde94e376 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -1,18 +1,18 @@
import { t } from '@/i18n';
-import type {
- BackendContext,
- PreloadContext,
- RendererContext,
+import {
+ type BackendContext,
+ type PreloadContext,
+ type RendererContext,
} from '@/types/contexts';
-import type {
- PluginDef,
- PluginConfig,
- PluginLifecycleExtra,
- PluginLifecycleSimple,
- PluginLifecycle,
- RendererPluginLifecycle,
+import {
+ type PluginConfig,
+ type PluginDef,
+ type PluginLifecycle,
+ type PluginLifecycleExtra,
+ type PluginLifecycleSimple,
+ type RendererPluginLifecycle,
} from '@/types/plugins';
export const LoggerPrefix = '[YTMusic]';
@@ -93,7 +93,6 @@ export const startPlugin = async (
if (defContext && typeof defContext !== 'function') {
Object.entries(defContext).forEach(([key, value]) => {
if (typeof value === 'function') {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
defContext[key as keyof typeof defContext] = value.bind(defContext);
}
});
diff --git a/web/youtube-music-hu.svg b/web/youtube-music-hu.svg
deleted file mode 100644
index da3401c83c..0000000000
--- a/web/youtube-music-hu.svg
+++ /dev/null
@@ -1,381 +0,0 @@
-
-
-
-
-
-
-
YouTube Music Asztali Alkalmazás
-
Beépített reklámblokkolóval
-
És beépített letöltővel
-
Többplatformos
-
- Ingyenes,
- Nyílt forráskódú
-
-
- Letöltés
-
-
-
-
-
-
diff --git a/web/youtube-music.svg b/web/youtube-music.svg
deleted file mode 100644
index a4d00070db..0000000000
--- a/web/youtube-music.svg
+++ /dev/null
@@ -1,381 +0,0 @@
-
-
-
-
-
-
-
YouTube Music Desktop App
-
With built-in ad blocker
-
And built-in downloader
-
Cross-platform
-
- Free,
- Open source
-
-
- Download
-
-
-
-
-
-