diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 5355e8ce..6fc167e2 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -12,7 +12,7 @@
- [ ] My pull request is programmed entirely or mostly with AI.
- [ ] My pull request only partially uses AI. \
- **If the above is applicable, I have used AI for:**
+ **If the above is applicable, I have used AI for:**
- [ ] I have only used AI for documentation of Firefox APIs or similar. **No code was written with it.**
- [ ] My pull request does not use any AI.
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index bdc8a4ae..3ce286cb 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -30,14 +30,12 @@ jobs:
- os: windows
arch: x64
runner: windows-latest
- generator: "Visual Studio 17 2022"
vs_arch: x64
triplet: x64-windows-static
- os: windows
arch: arm64
runner: windows-11-arm
- generator: "Visual Studio 17 2022"
vs_arch: ARM64
triplet: arm64-windows-static
@@ -69,7 +67,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -77,18 +75,47 @@ jobs:
run: |
git clone --recurse-submodules https://github.com/sineorg/installer.git external
- # ---------- Linux OpenGL / X11 ----------
- - name: Install OpenGL dependencies (Linux)
+ # ---------- Linux OpenGL / Wayland / X11 ----------
+ - name: Install GUI dependencies (Linux)
if: matrix.os == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y \
+ pkg-config \
libgl1-mesa-dev \
+ libegl1-mesa-dev \
libx11-dev \
libxrandr-dev \
libxinerama-dev \
libxcursor-dev \
- libxi-dev
+ libxi-dev \
+ libxext-dev \
+ libxfixes-dev \
+ libwayland-dev \
+ libwayland-bin \
+ wayland-protocols \
+ libxkbcommon-dev \
+ libxkbcommon-x11-dev \
+ extra-cmake-modules
+
+ - name: Enable Wayland feature for GLFW (Linux)
+ if: matrix.os == 'linux'
+ run: |
+ python3 -c "
+ import json
+ with open('external/vcpkg.json', 'r') as f:
+ data = json.load(f)
+ for i, dep in enumerate(data.get('dependencies', [])):
+ if dep == 'glfw3':
+ data['dependencies'][i] = {'name': 'glfw3', 'features': ['wayland']}
+ elif isinstance(dep, dict) and dep.get('name') == 'glfw3':
+ features = dep.get('features', [])
+ if 'wayland' not in features:
+ features.append('wayland')
+ dep['features'] = features
+ with open('external/vcpkg.json', 'w') as f:
+ json.dump(data, f, indent=2)
+ "
# ---------- Ninja ----------
- name: Install Ninja (Linux)
@@ -98,6 +125,13 @@ jobs:
sudo apt-get install -y ninja-build
# ---------- vcpkg ----------
+ - name: Adjust config for macOS
+ if: matrix.os == 'macos'
+ run: |
+ git config --global http.lowSpeedLimit 1000
+ git config --global http.lowSpeedTime 300
+ git config --global http.postBuffer 524288000
+
- name: Setup vcpkg
uses: lukka/run-vcpkg@b1a0dd252f06b9e25b3c022a9a03bd7a427fb6a2 # v11.6
with:
@@ -110,7 +144,6 @@ jobs:
if: matrix.os == 'windows'
run: |
cmake -S external -B build `
- -G "$env:GENERATOR" `
-A "$env:ARCH" `
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" `
-DVCPKG_TARGET_TRIPLET="$env:TRIPLET" `
@@ -118,7 +151,6 @@ jobs:
-DBOOT_VERSION="$env:BOOT_VERSION"
env:
VCPKG_ROOT: ${{ github.workspace }}\vcpkg
- GENERATOR: ${{ matrix.generator }}
ARCH: ${{ matrix.vs_arch }}
TRIPLET: ${{ matrix.triplet }}
SINE_VERSION: ${{ inputs.sine_version }}
@@ -129,8 +161,12 @@ jobs:
run: |
cmake -S external -B build \
-G "${GENERATOR}" \
+ -DCMAKE_TOOLCHAIN_FILE="${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" \
+ -DVCPKG_TARGET_TRIPLET="${VCPKG_DEFAULT_TRIPLET}" \
-DSINE_VERSION=${SINE_VERSION} \
- -DBOOT_VERSION=${BOOT_VERSION}
+ -DBOOT_VERSION=${BOOT_VERSION} \
+ -DGLFW_BUILD_WAYLAND=ON \
+ -DGLFW_BUILD_X11=ON
env:
VCPKG_ROOT: ${{ github.workspace }}/vcpkg
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
@@ -224,3 +260,75 @@ jobs:
with:
name: sine-osx-${{ matrix.arch }}
path: artifacts/sine-osx-${{ matrix.arch }}
+
+ post-build:
+ runs-on: ubuntu-latest
+ needs: build
+ name: Handle post-build steps
+ steps:
+ - name: Check signing requirements
+ id: status
+ env:
+ REF_NAME: ${{ github.ref_name }}
+ run: |
+ if [[ "$REF_NAME" == "main" ]]; then
+ echo "should-sign=yes" >> $GITHUB_OUTPUT
+ else
+ echo "should-sign=no" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Download all artifacts
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ path: ./artifacts
+
+ - name: Attest artifacts
+ uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
+ with:
+ subject-path: |
+ ./artifacts/sine-linux-*/*
+ ./artifacts/sine-osx-*/*
+ ./artifacts/sine-win-*-unsigned/*
+
+ - name: Prepare SignPath Workspace
+ if: steps.status.outputs.should-sign == 'yes'
+ run: |
+ mkdir -p ./unsigned
+ find ./artifacts/sine-win-*-unsigned/ -type f -exec cp {} ./unsigned/ \;
+
+ - name: Upload Windows artifacts (for code signing)
+ if: steps.status.outputs.should-sign == 'yes'
+ id: upload-unsigned-zip
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: sine-package-for-signing
+ path: ./unsigned
+
+ - name: Submit signing request
+ if: steps.status.outputs.should-sign == 'yes'
+ id: signpath-code-signing
+ uses: signpath/github-action-submit-signing-request@c92b958760219087e01f8d67a1669ed57afe2627 # v2.3
+ with:
+ api-token: "${{ secrets.SIGNPATH_API_TOKEN }}"
+ organization-id: "1324b51a-cb3d-4d1e-aab7-27b1169bd402"
+ project-slug: "Sine"
+ signing-policy-slug: "release-signing"
+ github-artifact-id: "${{ steps.upload-unsigned-zip.outputs.artifact-id }}"
+ wait-for-completion: false
+
+ - name: Save code signing info
+ if: steps.status.outputs.should-sign == 'yes'
+ env:
+ SIGNING_REQUEST_ID: ${{ steps.signpath-code-signing.outputs.signing-request-id }}
+ SIGNING_REQUEST_WEB_URL: ${{ steps.signpath-code-signing.outputs.signing-request-web-url }}
+ run: |
+ mkdir -p artifacts/info
+ echo "$SIGNING_REQUEST_ID" | tee artifacts/info/signing-request-id.txt
+ echo "$SIGNING_REQUEST_WEB_URL" | tee artifacts/info/signing-request-web-url.txt
+
+ - name: Upload Artifact (signing info)
+ if: steps.status.outputs.should-sign == 'yes'
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: info
+ path: ./artifacts/info
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 9c800eb2..1e7779a2 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -60,7 +60,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -72,7 +72,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
+ uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -100,6 +100,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
+ uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml
index cd621308..9b7d019e 100644
--- a/.github/workflows/pr-test.yml
+++ b/.github/workflows/pr-test.yml
@@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -26,7 +26,7 @@ jobs:
bun-version: latest
- name: Set up uv
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
+ uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
# Run ci script to install bun and uv deps
- name: Install dependencies
@@ -45,19 +45,19 @@ jobs:
security-events: write
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run zizmor
- uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
+ uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2
test:
name: Run tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -73,4 +73,7 @@ jobs:
run: bunx browsercfg select --browser zen-twilight --download
- name: Run tests
- run: bun run test
+ run: |
+ # Disable mozilla sandbox to prevent hanging process
+ export MOZ_DISABLE_CONTENT_SANDBOX=1
+ bun run test
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 46931478..5a2345fe 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,6 +11,15 @@ on:
type: number
description: "Version type (0: normal, 1: abnormal, 2: bootloader, see docs/updates.md)"
required: true
+ run_id:
+ description: "GitHub Actions run_id when created the corresponding release"
+ required: false
+ type: string
+ publish_draft:
+ description: "If true, will publish draft release"
+ required: false
+ default: false
+ type: boolean
permissions:
id-token: write
@@ -25,7 +34,7 @@ jobs:
version: ${{ steps.format_inputs.outputs.sine_version }}
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -101,7 +110,7 @@ jobs:
VERSION_TYPE: ${{ inputs.version_type }}
- name: Set up uv
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
+ uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
- name: Generate packages
run: |
@@ -109,7 +118,7 @@ jobs:
mv engine.zip artifacts/engine.zip
- name: Attest artifacts
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
+ uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: artifacts/*
@@ -121,10 +130,20 @@ jobs:
inputs: '{ "sine_version": "${{ steps.format_inputs.outputs.sine_version }}", "boot_version": "${{ steps.format_inputs.outputs.boot_version }}" }'
wait-for-completion: true
+ - name: Trigger upload workflow
+ if: steps.extract_branch.outputs.suffix != 'c'
+ id: sign_job
+ uses: benc-uk/workflow-dispatch@31e2b3319479a63f0ab15bf800eff9e913504e26 # v1.3.2
+ with:
+ workflow: upload-signed-files.yml
+ inputs: '{ "run_id": "${{ inputs.run_id }}" }'
+ wait-for-completion: true
+
- name: Download artifacts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- RUN_ID: ${{ steps.build_job.outputs.runId }}
+ RUN_ID: ${{ steps.build_job.outputs.runId || steps.sign_job.outputs.runId }}
+ INPUT_RUN_ID: ${{ inputs.run_id }}
run: |
gh run download $RUN_ID -D build/
@@ -138,12 +157,22 @@ jobs:
filename=$(basename "$file")
foldername=$(basename "$folder")
- if [ "$filename" = "$foldername" ]; then
- extension="${filename##*.}"
- tempname="${foldername}_file.$extension"
- mv "$file" "artifacts/$tempname"
- rmdir "$folder"
- mv "artifacts/$tempname" "artifacts/$filename"
+ if [[ "$filename" == *"-unsigned.exe" ]]; then
+ new_name="${file/-unsigned/}"
+ mv "$file" "$new_name"
+ file="$new_name"
+ filename=$(basename "$file")
+ fi
+
+ if [[ "$filename" == "engine.zip" || "$filename" == "updater.bat" || "$filename" == "updater.sh" ]]; then
+ echo "Preserving core asset: artifacts/$filename"
+ continue
+ fi
+
+ if [[ "$filename" =~ ^sine-(linux|osx|win)- ]]; then
+ echo "Verifying attestation for $filename..."
+ gh attestation verify "$file" --repo CosmoCreeper/Sine || echo "Warning: Attestation verification failed for $filename"
+ echo "Processed 'artifacts/$filename'"
else
mv "$file" artifacts/
rmdir "$folder"
@@ -178,12 +207,12 @@ jobs:
deploy:
needs: build-and-upload
- if: success()
+ if: success() && inputs.publish_draft == true
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
diff --git a/.github/workflows/sync-locales.yml b/.github/workflows/sync-locales.yml
index e8867f1f..09474a23 100644
--- a/.github/workflows/sync-locales.yml
+++ b/.github/workflows/sync-locales.yml
@@ -15,12 +15,12 @@ jobs:
steps:
- name: Checkout
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: crowdin action
- uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2
+ uses: crowdin/github-action@8f01d54f70f1713ee3f09d82c2bbb2daeac28689 # v2.17.1
with:
upload_sources: true
upload_translations: false
diff --git a/.github/workflows/upload-signed-files.yml b/.github/workflows/upload-signed-files.yml
new file mode 100644
index 00000000..1bfd613b
--- /dev/null
+++ b/.github/workflows/upload-signed-files.yml
@@ -0,0 +1,91 @@
+name: Upload signed executables
+
+on:
+ workflow_dispatch:
+ inputs:
+ run_id:
+ description: "GitHub Actions run_id when created the corresponding release"
+ required: true
+ type: string
+
+permissions:
+ id-token: write
+ attestations: write
+
+jobs:
+ download:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ persist-credentials: false
+
+ - name: Download build info
+ shell: bash
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ RUN_ID: ${{ inputs.run_id }}
+ run: gh run download "${RUN_ID}" --name "info" --dir info
+
+ - name: Download signed files
+ shell: bash
+ timeout-minutes: 10
+ env:
+ SIGNPATH_API_TOKEN: ${{ secrets.SIGNPATH_API_TOKEN }}
+ ORGANIZATION_ID: 1324b51a-cb3d-4d1e-aab7-27b1169bd402
+ run: |
+ SIGNING_REQUEST_ID=$(cat info/signing-request-id.txt)
+ REQUEST_URL=https://app.signpath.io/API/v1/${ORGANIZATION_ID}/SigningRequests/${SIGNING_REQUEST_ID}
+
+ # Check SignPath status
+ status=InProgress
+ while [ "$status" = "InProgress" ]; do
+ status=$(curl -f --silent -H "Authorization: Bearer ${SIGNPATH_API_TOKEN}" ${REQUEST_URL} \
+ | jq -r .status)
+
+ echo "SignPath status: $status"
+ case "$status" in
+ WaitingForApproval)
+ echo "Not approved yet. Approve it first:"
+ cat info/signing-request-web-url.txt
+ exit 1
+ ;;
+ InProgress)
+ ;;
+ Completed)
+ break
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+
+ sleep 10
+ done
+
+ # Download the signed files
+ curl -f -H "Authorization: Bearer ${SIGNPATH_API_TOKEN}" \
+ -o package.zip \
+ ${REQUEST_URL}/SignedArtifact
+ unzip package.zip -d package
+
+ rm -f package/*_pdb.*
+
+ for i in package/sine-win-*-unsigned.exe; do
+ [ -f "$i" ] || continue
+ mv "$i" "${i/-unsigned/}"
+ done
+
+ ls -l package
+
+ - name: Upload signed executables
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: signed-package
+ path: |
+ ./package/*
+
+ - name: Attest
+ uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
+ with:
+ subject-path: ./package/*
diff --git a/.oxfmtrc.json b/.oxfmtrc.json
index 8f98d570..a70a1412 100644
--- a/.oxfmtrc.json
+++ b/.oxfmtrc.json
@@ -1,5 +1,6 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"trailingComma": "es5",
+ "jsdoc": true,
"ignorePatterns": ["src/assets/imports/"]
}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5de943a0..24f95582 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,7 +1,47 @@
# Contributing to Sine
-If you wish to contribute to Sine, you can do so by forking this repository, making your changes, and creating a pull request to the **cosine** branch here. Do not make changes to the main branch as that's where we merge changes after they've been tested and verified on the cosine one.
+We invite all users, whether unskilled or skilled in this region of programming, to contribute to Sine. We are a small team, mostly comprised of [@CosmoCreeper](https://github.com/CosmoCreeper) and a few other members. If you are found to be interested and skilled in contributing to Sine, you may be added to our official team.
-- Please use our formatting configuration to format the files first.
-- Please test your code before creating a pull request. If your pull request adds a feature or improves something that the user would be able to notice, please share a screen recording of the actual feature in your pull request.
-- Please ensure that your pull request does not add any AI features and is not heavily vibecoded, as we are attempting to push against using AI for production development in our code.
+## Setting up a developer environment
+
+Before you can write production-level code for Sine that runs in the browser, you must first configure your developer environment.
+
+### Prerequisites
+
+- **Windows**: [Git Bash](https://git-scm.com/install/windows)
+- **Linux/macOS**: [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+- [Bun](https://bun.sh)
+- [uv](https://docs.astral.sh/uv/)
+
+### Steps
+
+If you're on Windows, open Git Bash. If you're on Linux/macOS, open your terminal (must have git installed). This is where we will perform all the actions required to get your developer environment set up.
+
+Navigate to the folder you want to place your Sine code clone into (you can use the `cd` command to do so). Now paste these commands into your terminal and press enter:
+
+```sh
+git clone https://github.com/CosmoCreeper/Sine.git sine
+cd sine
+```
+
+Now you have to use Bun to initialize the project's dependencies:
+
+```sh
+bun run init
+```
+
+And now you can contribute in any way you like!
+
+Below are some of our common scripts for developing.
+
+```sh
+bun lint # Lints all files
+bun lint:fix # Fixes linter errors where possible
+
+bun fmt:check # Checks formatting
+bun fmt # Formats files
+
+bun run test # Runs test suite
+
+bun dev # Executes code in an isolated browser env
+```
diff --git a/README.md b/README.md
index 49e1ac4f..488f34cd 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ Thatβs it! Sine should now be installed and ready to use.
Sine boasts a powerful suite of easy-to-use tools for everyone, technical, or non-technical. Let's look through some of these features:
π A built-in marketplace.
-
+
Sine has a marketplace that is built-in to the settings gui for easy access. This marketplace is where the user adds and views Sine-compatible mods.
**Am I limited to this settings gui?:** Absolutely not. Sine provides support for installing mods from [our website](https://sineorg.github.io/store/) too.
@@ -71,7 +71,7 @@ Sine has a marketplace that is built-in to the settings gui for easy access. Thi
π» Easy to publish and update your mods.
-
+
Every time a pull request gets published to a repository, it seems like it just adds to the stack of never-ending overflow. Sine makes this process simple. All you have to do is make an issue with a template. Assuming your project is already Sine-compatible, it'll work just fine. Plus, the developers of Sine are active enough to handle your pull requests quickly.
**What about updating?:** Sine does not require update requests and pulls them straight from your repository. This means that you will never have to worry about github issues being outdated or have to tell your user to update to the latest version.
@@ -79,7 +79,7 @@ Every time a pull request gets published to a repository, it seems like it just
π Test mods in a snap.
-
+
Sine makes the process of adding unpublished mods easy as long as they have a valid mod format. You simply type in the name of the repository (folder if needed) and Sine handles the rest.
@@ -107,6 +107,7 @@ Sine is designed to be highly compatible and as such, it offers support for user
- [Discord](https://discord.gg/P76BvB2MXS)
- [Reddit](https://reddit.com/r/sine_mods)
- [x.com](https://x.com/sine_mods)
+- [sineorg](https://github.com/sineorg)
- [Documentation](https://github.com/sineorg/docs)
- Marketplace: [Site](https://sineorg.github.io/store) | [Repository](https://github.com/sineorg/store)
- [Releases](https://github.com/CosmoCreeper/Sine/releases)
diff --git a/bun.lock b/bun.lock
index bc9a62d1..286e7657 100644
--- a/bun.lock
+++ b/bun.lock
@@ -7,26 +7,26 @@
"devDependencies": {
"@chromejs/browsercfg": "^0.1.8",
"@types/bun": "latest",
- "oxfmt": "^0.52.0",
- "oxlint": "^1.67.0",
- "oxlint-plugin-eslint": "^1.68.0",
- "svgo": "^4.0.1",
+ "eslint-plugin-jsdoc": "^64.2.1",
+ "oxfmt": "^0.65.0",
+ "oxlint": "^1.80.0",
+ "oxlint-plugin-eslint": "^1.80.0",
+ "svgo": "^4.1.0",
},
},
"tools/oxlint-plugin-mozilla": {
"name": "mozilla",
"version": "4.4.0",
"dependencies": {
- "@typescript-eslint/parser": "^8.60.1",
- "eslint-scope": "^8.4.0",
- "eslint-visitor-keys": "^4.2.1",
+ "@typescript-eslint/parser": "^8.67.0",
+ "eslint-scope": "^9.1.2",
+ "eslint-visitor-keys": "^5.0.1",
"estraverse": "^5.3.0",
- "htmlparser2": "^10.0.0",
- "toml-eslint-parser": "1.0.0",
+ "htmlparser2": "^12.0.0",
+ "toml-eslint-parser": "1.0.3",
},
"devDependencies": {
- "eslint": "9.39.1",
- "mocha": "11.7.5",
+ "eslint": "^10.9.0",
},
},
},
@@ -49,23 +49,23 @@
"@chromejs/browsercfg-win32-x64": ["@chromejs/browsercfg-win32-x64@0.1.8", "", { "os": "win32", "cpu": "x64" }, "sha512-kAt23theSTylg3PdiHIngboLH7HmUSS8eck3TmiHyamv3H2W7Iw/xYQHsSMHltrsVpNvW87C5h+Z3SSygwgONg=="],
- "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
+ "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.95.1", "", { "dependencies": { "@types/estree": "^1.0.9", "@typescript-eslint/types": "^8.67.0", "comment-parser": "1.4.8", "esquery": "^1.7.0", "jsdoc-type-pratt-parser": "~9.1.2" } }, "sha512-LO/RI08Fo9bhXwB7Od9G+1j3eSNq63+ZS5CQO8YLXHbDg6kx6S/DhTeY0+Fc9uZrjK1zZSyTx8Sg5gv5DIoCnA=="],
- "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
+ "@es-joy/resolve.exports": ["@es-joy/resolve.exports@1.2.0", "", {}, "sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g=="],
- "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
+ "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
- "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
+ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
- "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
+ "@eslint/config-array": ["@eslint/config-array@0.23.5", "", { "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA=="],
- "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
+ "@eslint/config-helpers": ["@eslint/config-helpers@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.1" } }, "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw=="],
- "@eslint/js": ["@eslint/js@9.39.1", "", {}, "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw=="],
+ "@eslint/core": ["@eslint/core@1.2.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ=="],
- "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
+ "@eslint/object-schema": ["@eslint/object-schema@3.0.5", "", {}, "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw=="],
- "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
+ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.2", "", { "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" } }, "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A=="],
"@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="],
@@ -77,191 +77,163 @@
"@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
- "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
+ "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.65.0", "", { "os": "android", "cpu": "arm" }, "sha512-M10Gs1SSpTNI6ahGx3M/OlIdUF4hkaP6OgUb+MS79t/Pgflk3r1nW5gPFqsZGUAXg0H1AfANT9AvLdBSTIhZKg=="],
- "@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.52.0", "", { "os": "android", "cpu": "arm" }, "sha512-17EMSJnQ9g+upVHrAUYDMfH5lvRKQ9Nvg8WtEoH72oDr1VpWz+7/o3tD97U1EToen2YAQ/68JmtDYkQUi20dfQ=="],
+ "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.65.0", "", { "os": "android", "cpu": "arm64" }, "sha512-6DXH5sftNlaHpWJG50hFMF+Qxtq5D2TmahvcDPxWNcGIf8qrC9Y0YgHYcYZ2hlWzaccKXh/f3GcssH8vtkl4JA=="],
- "@oxfmt/binding-android-arm64": ["@oxfmt/binding-android-arm64@0.52.0", "", { "os": "android", "cpu": "arm64" }, "sha512-A2G1IdwGEW2lLJkIxcvuirRH1CzSl/e0NX11zTlW1gvxJThfwbI/BEoaKrTNpm7M2FchvIf6guvIQU7d5iz+OQ=="],
+ "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.65.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-K9m7lr53pcOLETNsC88sWes/GWHUGjZyHx95UhYcSXy0r30haLdeXlSufSenEAtoLaW753WN8/l4M7GYcRt6cg=="],
- "@oxfmt/binding-darwin-arm64": ["@oxfmt/binding-darwin-arm64@0.52.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-f9+bLvOYxy7NttCLFTvQ7afmqDOWY4wIP9xdvfj5trQ1qj6f2UFAGwZESlfsMjvJNTyRpXfIlOanCI9FOvoeQA=="],
+ "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.65.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-sTNwIx1gre3MyiHOPLu7IGW4UyMScYL4DTmJT01p4vzB0En+OJUQz6KuH8t0PpsClRSaMuY3b0QmtoPItfO8Lg=="],
- "@oxfmt/binding-darwin-x64": ["@oxfmt/binding-darwin-x64@0.52.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-YSTB9sJ5nnQd/Q0ddHkgof0ZCHPAnWZT1IW2SJ8omz7CP7KluJhO1fNHrpqdxCtpztJwSs4hY1uAee35wKxxaw=="],
+ "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.65.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lYZMVIiIpnjGu5hJb2jxA8NYQ/e0OTGuaiAf4dqlGPNnPmUTu23FZRMltmjro/KkQm1uE4NT4n5yJ2zWmKcpfA=="],
- "@oxfmt/binding-freebsd-x64": ["@oxfmt/binding-freebsd-x64@0.52.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-NIrRNTTPCs4UbmVs0bxLSCDlLCtIRMJIXklNKaXa5Oj2/K1UIMBvgE8+uPVo01Io3N9HF0+GAX+aAHjUgZS7vA=="],
+ "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.65.0", "", { "os": "linux", "cpu": "arm" }, "sha512-gIdXFAt/bURnjxuoedDEWdZ0PEWEmdDcm8qdpoFYYvW3QMk/5D4vUaH4mlMeRpeTdST4izUgHVO6RawQ4QulJw=="],
- "@oxfmt/binding-linux-arm-gnueabihf": ["@oxfmt/binding-linux-arm-gnueabihf@0.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-JXUCde8mn3GpgQouz2PXUokgy/uT1QrRJBL2s983VWcSQp62wTFYiNXgTKdeo1Jgbr0IgUnKKvzIk/YBlj/nVQ=="],
+ "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.65.0", "", { "os": "linux", "cpu": "arm" }, "sha512-jJVyADto7gA2AaX5qAjAexrxx9PJQaKWOe8PICE7yKMbjBRyOHcmj9TtVJ+MZYDUQ3hodU0AcoTj0jFQ1W4C6Q=="],
- "@oxfmt/binding-linux-arm-musleabihf": ["@oxfmt/binding-linux-arm-musleabihf@0.52.0", "", { "os": "linux", "cpu": "arm" }, "sha512-psbUXaRZ+V8DaXz10Qf7LSHtdtdKAmC8fxXgeU608jjzrmWK4quamZMOpl6sf+dikoFHA85uE93Q0BqxrCdQrQ=="],
+ "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.65.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-p3RFkB+u7u+8up99b/NEcI1hdpLDiGgJYNwDorB60n7eH+eKposAKuMBxx+NqB3b+sJP4CZmYDh9G7X62tUsKg=="],
- "@oxfmt/binding-linux-arm64-gnu": ["@oxfmt/binding-linux-arm64-gnu@0.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-Jw7MgWUU9lcLCcy82updISP3EthTlfvAwR6gWNxPzqly7+fLvOi2gHQE9xXQjpqaVLm/8P+gOzlv9ODuoVlaaw=="],
+ "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.65.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Prb0uFzJHr+OUD/qS/TmU526wD+PaHDsm3KoRiUXbMIDpTSErjeQYkK3OQeshAvD/PuLa9WGEi9WPajjdOZJg=="],
- "@oxfmt/binding-linux-arm64-musl": ["@oxfmt/binding-linux-arm64-musl@0.52.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-wZg6bLjDvh2KibyI3QFUYo8GTXneIFsd0JvehtvJiUmQ8WRPERgxd/VM4ctWb86U5FT1FkqgS8/wZKVB+AZScg=="],
+ "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.65.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-S8svxTp81obnF3admN9yd+u2rOYXtyzThLGBTg1PY6TPtGcC09BaaXLQD+TBSMa7yvqhCDZ8DFri+S/yG60qCg=="],
- "@oxfmt/binding-linux-ppc64-gnu": ["@oxfmt/binding-linux-ppc64-gnu@0.52.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-IngE8uxhNvxcMrLjZNDo9xNLY7rEK33AKnaMd2B46he1e/mz2CfcW6If/U1wUjdRZddm1QzQaciqZkuMkdh1FA=="],
+ "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.65.0", "", { "os": "linux", "cpu": "none" }, "sha512-WtXBr75G/h2qOHy8SiGtC1R6aS3jt4mE52v1D8AtwMXIgoOmSNP9lKvbSaTRoL0e5wsMPoi6T72QWDYPu+S+nA=="],
- "@oxfmt/binding-linux-riscv64-gnu": ["@oxfmt/binding-linux-riscv64-gnu@0.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-H3+DdFMv/efN3Efmhsv18jDrpiWWqKG7wsfAlQBqAt6z/E2Bx+TwEj2Nowe51CPOWB8/mFBC2dAMSgVFLvvowA=="],
+ "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.65.0", "", { "os": "linux", "cpu": "none" }, "sha512-YwSLVvpaz4o/nv/miiPEBJz+eJ+VmbgNIrao6RccK9ce+L5EA8wP+ZD0uFeq6wKOza6zoWv/dR0sj6lip6R3EA=="],
- "@oxfmt/binding-linux-riscv64-musl": ["@oxfmt/binding-linux-riscv64-musl@0.52.0", "", { "os": "linux", "cpu": "none" }, "sha512-zji+1kb7lJKohSDjzC1IsS+K/cKRs1hdVf0ZH0VbdbiakmtLvN9twBoXo/k8VdjFax7kfo+DyPxS7vv52br1aw=="],
+ "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.65.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-XQTPqgvyrgkKcFq+Tp2eK6JS7sqqJ+nRmy2Fav4j3I+i4dJoPJm7YwEdoeSDX9xkqj9jZ/lWfF3bXUWztIrn6A=="],
- "@oxfmt/binding-linux-s390x-gnu": ["@oxfmt/binding-linux-s390x-gnu@0.52.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-hcLBYedpCy7ToUvvBidWk7+11Yhg1oAZ4+6hKPic/mQI6NaqXJSXMps5nFlwUuX2ewhtLZZDPg63TI042qGKBg=="],
+ "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.65.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cjZlx6S/VkeCNWCbwZriTnLnZeTcV3DEyeRGSw/2wwLP9viq+C0bJ4bC1k/ZLkFxDcB1lUgSasPkYGP1bdraOg=="],
- "@oxfmt/binding-linux-x64-gnu": ["@oxfmt/binding-linux-x64-gnu@0.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-IDO2loXK2OtTOhSPchU9MW25mWL2QCDGdJbjN8MXKZVS80qXe5gMTwQWu/gMJ3juoBHbkuUZNB2N1LHzNT7DoA=="],
+ "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.65.0", "", { "os": "linux", "cpu": "x64" }, "sha512-2azCjxdLtK4zCcIOU1dlXlU0xxfbPi6EjwWx7Ac7teWPidIIDOcIhudup83xNCKYhtqeVd/gaVDOxbUq4syXWA=="],
- "@oxfmt/binding-linux-x64-musl": ["@oxfmt/binding-linux-x64-musl@0.52.0", "", { "os": "linux", "cpu": "x64" }, "sha512-mAV2Hjn0SatJ+KoAzKUC3eJhdJ8wv+3m1KyuS0dTsbF0c5weq+QrCt/DRZZM+uj/XiKzCDEUKYsBF30e2qkcyw=="],
+ "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.65.0", "", { "os": "none", "cpu": "arm64" }, "sha512-KXQ7xi1e/voP0IQaw6fG6XY4Z5+Llf1XmRSZS1t7pVFCecFJ0iXaboKmVwjFtp5MLlT5iWQrJ2U1C3GJdZ2u+Q=="],
- "@oxfmt/binding-openharmony-arm64": ["@oxfmt/binding-openharmony-arm64@0.52.0", "", { "os": "none", "cpu": "arm64" }, "sha512-vd4npaUIwChxp7XzkqmepBWTT9YMcSe/NBApVGPC30/lLyOVaV3dvma1SKo03t8O73BPRAG7EyJzGlN5cJM5hQ=="],
+ "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.65.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-2FbbjG5jEqLSLKVJwBap84uJfpn5Y5A53KEO0aUNr+zeiRB9nyPUIFMcSbZVMFLitfBytFWRNngozXYjb6Rsbw=="],
- "@oxfmt/binding-win32-arm64-msvc": ["@oxfmt/binding-win32-arm64-msvc@0.52.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-k2sz6gWQdMfh5HPpIS+Bw/0UEV/kaK2xuqJRrWL233sEHx9WLlsmvlPFM4HUNThkYbSN0U0vPW7LVKZWDS8hPQ=="],
+ "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.65.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-LJ+ZacAPSjegDOnSLyA1TMWAhdDrsK4el3REdr1oL2UtVBCMhO2II/Sb3cEW6mF2MfLhl8hDNCSvc7KSbgk3LQ=="],
- "@oxfmt/binding-win32-ia32-msvc": ["@oxfmt/binding-win32-ia32-msvc@0.52.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-rhke69GTcArodLHpjMTfNnvjTEBryDeZcUCKK/VjXDMtfTULl6QRh0ymX5/hbCUv2WjYm9h/QbW++q2vE15gWQ=="],
+ "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.65.0", "", { "os": "win32", "cpu": "x64" }, "sha512-higu9cWEO6XXFzATD1jf0mCK34rNfN2H9JrJie7QB1IhleVpTh0QlLH9Ip2C1H/Nd5n0v5pvRtC+5R0uE4HpVg=="],
- "@oxfmt/binding-win32-x64-msvc": ["@oxfmt/binding-win32-x64-msvc@0.52.0", "", { "os": "win32", "cpu": "x64" }, "sha512-q5xL7oeXkZdEtNZWBdvehJcmt+GRu9l2bK40yJs1jJXlqq+r0Hygb1rTjq+FM2o/2xyt4cufH6KRplHp3Jjsvw=="],
+ "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.80.0", "", { "os": "android", "cpu": "arm" }, "sha512-RM3Plj+biQpxa5d1GOOX6ciDlcUROmm4OZ/pLTpitkQt2mJv4jhtY4cbgaetOm5UKWZe05/TGQ6o1Vl8EOHkrA=="],
- "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.67.0", "", { "os": "android", "cpu": "arm" }, "sha512-VrSi571rDv1N8HaEDM+DEX8nmT0y9jJo8tzzW13vsOWTx59xQczCIJx68n2zWOXRT5YKZsOZXp4qkHN/10x4mw=="],
+ "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.80.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YlO5JEf0Yr2bUUlu8O8daVcUxtcGGbcSmyV7E7nSbJbfAdxTE0PFPwgnIlw7wXJaTYjb+qs5hI5q3jxUkI7cAw=="],
- "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.67.0", "", { "os": "android", "cpu": "arm64" }, "sha512-l6+NdYxMoRohix5r5bbigW16LPicceCwGcQ6LKKuE1kUdjgFfQolJjrJsQYPFetIs78Gxj/G/f5TEGoTCwj9nQ=="],
+ "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.80.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-BULDOyO3AhsmdWfQeIUCykDt3dd7XZBGLhp1eIh56skRv01O+cNjNPwXMIbeW1x4+pxcln5if72wcRgViVo7PA=="],
- "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.67.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jOzXxS1AxFxhImLIRbtGIMrEwaXcgMw3gR57WB1cRk8ai+vpr6726kxXqVvlNsrXtJ/FrmOm8RxlC0m8SW24Qg=="],
+ "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.80.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-YJ4JzLw7N5TDSQFlA0hAQGHvnDZgyypm1yunObVWcWiF9KM7eGCJKYKLgTC2Fi/57OdnBhbj4OkzPGdFQJ6HyA=="],
- "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.67.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-3DFAVY94OqjIZHXIPz37yGRSWwOFTAqChQ64/M69GYLawzP0KiwdhDNfqdKKYT0bTR/DNxmMnQsj3ns+8+X/Lg=="],
+ "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.80.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-AYUIk5QnL0s8oWAYsREZwkRYy1SupJTXALo93J1TgzHywxQtdM99FecRMQ87MXEdPQ0j1TmEpeeq3fGNkpvMqg=="],
- "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.67.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-e4dDKZuLu8TR9DEBssWSDahlPgZBwojTTHZUvnjBRJfJJbpxYCjfjKfi0Z1+CSLMiJBwI2yCDtRM1XJQaARjmg=="],
+ "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.80.0", "", { "os": "linux", "cpu": "arm" }, "sha512-9hBZVANupQ89W9dXyE0n8doCyaW5pDyGn3y6XlIMPZ+rIKuyqkr3SNUXmVJIhuvUq0NBU3RBiSXXE69l4XI6KA=="],
- "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.67.0", "", { "os": "linux", "cpu": "arm" }, "sha512-BKytFdcQzbITV3xlnzDUDTEDtbUMCCiC4EaNTDZ4FyT8gdNvBC4gfiLucXp/sQl0XU3p7syTlorUWVVVBZab2g=="],
+ "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.80.0", "", { "os": "linux", "cpu": "arm" }, "sha512-SvS2uKqzY+pbfuvAHzH4338R6Zwo805GAwrIMVvK1KxoOWCIjZUdfzTCvilD7z6JK91v011+zYMryabhDo2AsQ=="],
- "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.67.0", "", { "os": "linux", "cpu": "arm" }, "sha512-XYAv0esBDX7BpTzRDjVX2Vdj+zndd8ll2dFQiaeQ6zTZr7A8GRDTN7fH3FP3jU+O0vCDx85oH/EtG7BzPgAXuw=="],
+ "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.80.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-tCLadyqRVL3pQTRPNg7cjXKvcvS4fbyXeQHhKk5BTJ1oftQln5/yIIWbu/Xom/DX41zv2P9QGt6+D/TtQVtY3A=="],
- "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.67.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zizRMjA0i6u/2B0evgda04iycu+MoNuf1pBy6Eh+1CjC5wMEG7qN5zdDKTCvFc0KSYSDM9QTG3gjZHirgtQuKg=="],
+ "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.80.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-XfpCNRlOPcLlJl4Bn/FUhjqlR6BVavEykERBf/MV7YA9VZDa5g5znVqYhyviMafcxS9Pe/i/kPvHNO0U6svEHQ=="],
- "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.67.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-zB/Tf6sUjmmvvbva9Gj3JTJ8rJ9t4I8/U0o6vSRtd0DRIsIuyegBwJAzhSUFQHdMijIRJkW0exs/yBhpw2S20w=="],
+ "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.80.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-3I4yMwcFG9NeO8ioY6JBBuKsIm5GL/x7MATt1S4tVWaxPu5HcJ+XnLUbcVBTxG8q2Wu56HSj+NmXQiVYb1lp6A=="],
- "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.67.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-kgU40Gt74CK0TCsF51KZymkIwN9U0BajKsMijB52zPqOeZU9NAHkA/NSQkZDHEaCakx42DxhXkODiAqf2b4Gug=="],
+ "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.80.0", "", { "os": "linux", "cpu": "none" }, "sha512-E1wAKymkpe1/E8helzBKdm81OBOF+ezxRyXRMEuik3ZpWDER5CPOKZwF66RsdwW98uwZv8UTFremUQtC1CzdJA=="],
- "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.67.0", "", { "os": "linux", "cpu": "none" }, "sha512-tOYhkk/iaG9aD3FvGpBFd1Lrw0x0RaVoJBxjUkfNzS50rC5NS5BteNCwgr8A2zCdADrIIoze6D7u6U5Ic++/iQ=="],
+ "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.80.0", "", { "os": "linux", "cpu": "none" }, "sha512-+gLRGD4sIo3+VA++iham5UxD9tKSoJ/VOrROCEXIcknrYtQg6iIQgvjN0cpiRF7N6UYC7pJbvHJlDnMge5LRpQ=="],
- "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.67.0", "", { "os": "linux", "cpu": "none" }, "sha512-sEtywrPb+0b+tHYl1SDCrw903fiC4eyKoNqzP3v+f2JT3Xcv4NEYG+P8rj+eEnX7IWhqV/xj8/JmcmVj21CXaA=="],
+ "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.80.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-aR0PrzHj9leW3NmzBAAP4EzdoBNoJcs9sjnIQPIwyRnBGYrRbXUIpEB5Q39AqK3PLY5JK5uEhDQDiUa1QSAstw=="],
- "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.67.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-BvR8Moa0zCLxroOx4vZaZN9nUfwAUpSTwjZdxZyKy4bv3PrzrXrxKR/ZQ0L9wNSvlPhnMJeZfa3q5w6ZCTuN6Q=="],
+ "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.80.0", "", { "os": "linux", "cpu": "x64" }, "sha512-vSVh5cSo3Xxs6ghBCcFJlpbkbENzDog1qXtoXLa/HC3aCrR4XO76GZbXmQoCPHnu99nQpdCeC3H9tdNICfDh7A=="],
- "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.67.0", "", { "os": "linux", "cpu": "x64" }, "sha512-mm2cxM6fksOpq6l0uFws8BUGKAR4dNa/cZCn37Npq7PFbhD5HDJqWfnoIvTaeRKMy5XdS2tO0MA0qbHDrnXAAA=="],
+ "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.80.0", "", { "os": "linux", "cpu": "x64" }, "sha512-FfzBXpNQ8u7/ZI/p8bl73MeZ508Ax3hxWp3SiJpEFiC+BB9XcXy5FAZHTLKDPSzrUpxQZSZJAVdDmuJp/+HDBQ=="],
- "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.67.0", "", { "os": "linux", "cpu": "x64" }, "sha512-WmbMuLapKyDlobMkXAaAL0Y+Uczh4LETfIfQsUpbId4Ip8Ai82/jqeYTOoUCkuuhBFapgqP253+d83tLKOksJg=="],
+ "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.80.0", "", { "os": "none", "cpu": "arm64" }, "sha512-zMzbkumtmprCgRwoYNzcB3iC39fXdJIMLMU33KdCjEGLlJGOEt1+LwQ4LF8ndLzAEKVz4BR0y3V6Xrkk3Nm3yA=="],
- "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.67.0", "", { "os": "none", "cpu": "arm64" }, "sha512-9g/PqxYJelzzTAOR5Y+RiRqdeydhEuXv2KxNeFcAKQ7UsvnWSY1OP4MsuPMbTO2Pf70tz7mFhl1j13H3fyh+8g=="],
+ "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.80.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-ib6iRcrXsk4t1fm3iKcwksyWh1ZkZXC/2mEzakl0ai2+6HZunf1WWMZ/xP9EJAvw9g9K4UVTC3NF/+G2qLrbTQ=="],
- "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.67.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-2VhwE6Gatb0vJGnN0TBuQMbKCOiZlSQ/zJvVWYLK4a9d4iDiJOen/yVQkGpmsJ90MuH66fzi0kEKI0jRQMDxGA=="],
+ "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.80.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-xhRWBMpLxZvgKAH6+DJZmpP+W8Y8UdQOSU1JfxSWNXsaBaRGW77j+1hCuNHlzj7OH4SPN8fYd1q0o2qrDtoVyw=="],
- "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.67.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-EQ3VExXfeM1InbE5+JjufhZZTWy+kHUwgt3yZR7gQ47Je/mE0WspQPan0OJznh493L5anM210YNJtH1PXjTSFg=="],
+ "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.80.0", "", { "os": "win32", "cpu": "x64" }, "sha512-yAnO7lwBYQnz2pcfBPIGQQZWIX5zd5R/1aAKIF3oE+TVj7IhoHcROjOkz3sRDngzqhfPKfFaXqug5j5rE5dn6Q=="],
- "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.67.0", "", { "os": "win32", "cpu": "x64" }, "sha512-bw24y+/1MHS4QDkons3YyHkPT9uCMoLHHgQhb+mb8NOjTYwub1CZ+K9Ngr8aO5DMrDrkqHwTzlTwFP2vS8Y/ZQ=="],
+ "@sindresorhus/base62": ["@sindresorhus/base62@1.0.0", "", {}, "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA=="],
- "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
+ "@types/bun": ["@types/bun@1.4.0", "", { "dependencies": { "bun-types": "1.4.0" } }, "sha512-K+lZULY23vRgK/CfTjFIV+tyifaNdSMlPh9j+6mQ/cLfpOznLyAuzgV/JQysyECpkBQLVMSyvjlr2fBUSA9wFQ=="],
- "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
+ "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="],
"@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
- "@types/node": ["@types/node@25.9.2", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-G05zqtJhcDLb8uslf5EjCxXg9G1KQxiV8OS0R26IC//Eoyitzqe8z37I7cqvnZlrlSfgocQRfSn/AHBZJJFyGw=="],
+ "@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="],
- "@typescript-eslint/parser": ["@typescript-eslint/parser@8.60.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.60.1", "@typescript-eslint/types": "8.60.1", "@typescript-eslint/typescript-estree": "8.60.1", "@typescript-eslint/visitor-keys": "8.60.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA=="],
+ "@typescript-eslint/parser": ["@typescript-eslint/parser@8.67.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.67.0", "@typescript-eslint/types": "8.67.0", "@typescript-eslint/typescript-estree": "8.67.0", "@typescript-eslint/visitor-keys": "8.67.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-fUBfTuuEulWqX6V8+O3PtScV01tzYYRUDTAirHFKoRAt7nOzoGiPt0M/bB47wWNy0coOOcgEwAMUtBpykMxl6w=="],
- "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.60.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.60.1", "@typescript-eslint/types": "^8.60.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw=="],
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.67.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.67.0", "@typescript-eslint/types": "^8.67.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-cvE8c7ulYeXN9fYuszhCeCsbzyVEXuhrRCybnBre7TUmqb5nRmBfQAwCj0O3WJFDeyAZt4VYv51vMCC9LHSdYw=="],
- "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.60.1", "", { "dependencies": { "@typescript-eslint/types": "8.60.1", "@typescript-eslint/visitor-keys": "8.60.1" } }, "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w=="],
+ "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.67.0", "", { "dependencies": { "@typescript-eslint/types": "8.67.0", "@typescript-eslint/visitor-keys": "8.67.0" } }, "sha512-EgvsleTwS4E+WzzSvem8fAUubLwatMNF1B5hHSLQxcvs7q2dtRhGyujHwLJSYlG41niJ7GP24Aha2+0mb1b2kg=="],
- "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.60.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA=="],
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.67.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-vV+LUSv5njUWsknE71fqKTlXUva+R76SaeORd6Zojcunk/6DvKFXONU3BrAs2H49mbygUXt6gbYunzwqNwlhdg=="],
- "@typescript-eslint/types": ["@typescript-eslint/types@8.60.1", "", {}, "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w=="],
+ "@typescript-eslint/types": ["@typescript-eslint/types@8.67.0", "", {}, "sha512-sBtgslww8nsMYUjhdPBiSyUqSzT8uR6g93A2QXnQC8+cGdjz0CyaOdqHDRJb1AtORbZCNUJBBeFA/tNR2uQmww=="],
- "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.60.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.60.1", "@typescript-eslint/tsconfig-utils": "8.60.1", "@typescript-eslint/types": "8.60.1", "@typescript-eslint/visitor-keys": "8.60.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew=="],
+ "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.67.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.67.0", "@typescript-eslint/tsconfig-utils": "8.67.0", "@typescript-eslint/types": "8.67.0", "@typescript-eslint/visitor-keys": "8.67.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-EKQBCE9yNlRJYm7jdTW5AhDacDUmSwQb0FAJAmK2EKYrNXIsa2vxcSZx6PvJ/dEdI6lS+Y9W+EXckLj0iPFGcw=="],
- "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.60.1", "", { "dependencies": { "@typescript-eslint/types": "8.60.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag=="],
+ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.67.0", "", { "dependencies": { "@typescript-eslint/types": "8.67.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-fkv8dHRDqfGtTHuJeebdrQ7cX6Ad4WAS00rgHh9UGvMycF1mjBfsxry1XsLIFhWZ6Judlh6UdzK+TYlbpCXgnA=="],
- "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
+ "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
- "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+ "are-docs-informative": ["are-docs-informative@0.1.1", "", {}, "sha512-sqRsNQBwbKLRX0jV5Cu5uzmtflf892n4Vukz7T659ebL4pz3mpOqCMU7lxMoBTFwnp10E3YB5ZcyHM41W5bcDA=="],
- "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
-
- "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
-
- "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+ "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
- "brace-expansion": ["brace-expansion@1.1.14", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g=="],
-
- "browser-stdout": ["browser-stdout@1.3.1", "", {}, "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="],
-
- "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
+ "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
- "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
-
- "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
-
- "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
-
- "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
-
- "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
-
- "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
-
- "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+ "bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="],
"commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="],
- "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
+ "comment-parser": ["comment-parser@1.4.8", "", {}, "sha512-rKZTGo4fzKYna8UcL0isTg5wkBNla7bxTypLwZQXjIdi++IdP1OJ41rI5Mti3/jltkPujbu4i9LIARYA+zpotQ=="],
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
- "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="],
+ "css-select": ["css-select@6.0.0", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^7.0.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "nth-check": "^2.1.1" } }, "sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw=="],
"css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
- "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="],
+ "css-what": ["css-what@7.0.0", "", {}, "sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ=="],
"csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="],
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
- "decamelize": ["decamelize@4.0.0", "", {}, "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ=="],
-
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
- "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="],
-
- "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
+ "dom-serializer": ["dom-serializer@3.1.1", "", { "dependencies": { "domelementtype": "^3.0.0", "domhandler": "^6.0.0", "entities": "^8.0.0" } }, "sha512-4MEa38/QexBob6gFNwu+EGdWvhJ1OKuNwdYY3Y3NyeWDQfnGeDYQUDfIRzWu5B5gsv03so2Uxd28YC6zrsx3Lw=="],
- "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
+ "domelementtype": ["domelementtype@3.0.0", "", {}, "sha512-umCQid3jKbDmVjx8jGaW7uUykm4DEUeyV21hPxNMo2nV955DhUThwqyOIDtreepP31hl84X7G5U9ZfsWvIB3Pg=="],
- "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
+ "domhandler": ["domhandler@6.0.1", "", { "dependencies": { "domelementtype": "^3.0.0" } }, "sha512-gYzvtM72ZtxQO0T048kd6HWSbbGCNOUwcnfQ01cqIJ4X2IYKFFHZ5mKvrQETcFXxsRObZulDaKmy//R7TPtsBg=="],
- "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
+ "domutils": ["domutils@4.0.2", "", { "dependencies": { "dom-serializer": "^3.0.0", "domelementtype": "^3.0.0", "domhandler": "^6.0.0" } }, "sha512-qI4JLRKnSzqFqr7hAlS5xQDusBCjKSEG4t4+7aNrIQMHBcsC2TGEhuyABJdYkgSewL57PNLYEiibY2iPKhKpaA=="],
- "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
+ "entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="],
- "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+ "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
- "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="],
+ "eslint": ["eslint@10.9.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.7.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-5KeEOJZBfEVA47boFiBsf+6MmmJpffM7qEBg4pLla2e4nlKgdKlqCW0oSLOGsT8Wl5uCGJptLV1bkaiShj90Gw=="],
- "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+ "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@64.2.1", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.95.1", "@es-joy/resolve.exports": "1.2.0", "are-docs-informative": "^0.1.1", "comment-parser": "1.4.8", "debug": "^4.4.3", "escape-string-regexp": "^5.0.0", "espree": "^11.2.0", "esquery": "^1.7.0", "html-entities": "^2.6.0", "object-deep-merge": "^2.0.1", "parse-imports-exports": "^0.2.4", "semver": "^7.8.5", "spdx-expression-parse": "^5.0.0", "to-valid-identifier": "^1.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0" } }, "sha512-6GpSYxLPcbMw38S94Cngrgs1Zv8yLinQS1O17OxJVZ6deLbrMRCERUYQKceweSqEuG2kx5Amn4l3aKPkCp4geQ=="],
- "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+ "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="],
- "eslint": ["eslint@9.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "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.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g=="],
+ "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
- "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
-
- "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
-
- "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
+ "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="],
"esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
@@ -283,51 +255,27 @@
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
- "flat": ["flat@5.0.2", "", { "bin": { "flat": "cli.js" } }, "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="],
-
"flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
- "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
-
- "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
-
- "glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
-
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
- "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
-
- "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
-
- "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="],
+ "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="],
- "htmlparser2": ["htmlparser2@10.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.2.2", "entities": "^7.0.1" } }, "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ=="],
+ "htmlparser2": ["htmlparser2@12.0.0", "", { "dependencies": { "domelementtype": "^3.0.0", "domhandler": "^6.0.0", "domutils": "^4.0.2", "entities": "^8.0.0" } }, "sha512-Tz7u1i95/g2x2jz81+x0FBVhBhY5aRTvD3tXXdFaljuNdzDLJ8UGNRrTcj2cgQvAg3iW/h77Fz15nLW0L0CrZw=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
- "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
-
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
- "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
-
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
- "is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="],
-
- "is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="],
-
- "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="],
-
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
- "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
-
- "js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
+ "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@9.1.2", "", { "dependencies": { "@types/estree": "^1.0.9" } }, "sha512-9EXymowgk1mb9RY1VxuwKc+AhaxfBk2CV0dWxgGM+l5RURTtiUoAx7MlKwcsiVcEXK5HEPa7FeH/tsRpqjEPRg=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
@@ -341,19 +289,9 @@
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
- "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
-
- "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="],
-
- "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
-
"mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="],
- "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
-
- "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
-
- "mocha": ["mocha@11.7.5", "", { "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", "debug": "^4.3.5", "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", "minimatch": "^9.0.5", "ms": "^2.1.3", "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^9.2.0", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { "mocha": "bin/mocha.js", "_mocha": "bin/_mocha" } }, "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig=="],
+ "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
"mozilla": ["mozilla@workspace:tools/oxlint-plugin-mozilla"],
@@ -363,28 +301,28 @@
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
+ "object-deep-merge": ["object-deep-merge@2.0.1", "", {}, "sha512-aKttDKcU3pyZqKcCkDhsMn70WmZFG2JGDQLP9EcLyTSIFQRCPWLAmBZRLJnrVUrhPG1jETEEbfdgbNtJf1LyMg=="],
+
"optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
- "oxfmt": ["oxfmt@0.52.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.52.0", "@oxfmt/binding-android-arm64": "0.52.0", "@oxfmt/binding-darwin-arm64": "0.52.0", "@oxfmt/binding-darwin-x64": "0.52.0", "@oxfmt/binding-freebsd-x64": "0.52.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.52.0", "@oxfmt/binding-linux-arm-musleabihf": "0.52.0", "@oxfmt/binding-linux-arm64-gnu": "0.52.0", "@oxfmt/binding-linux-arm64-musl": "0.52.0", "@oxfmt/binding-linux-ppc64-gnu": "0.52.0", "@oxfmt/binding-linux-riscv64-gnu": "0.52.0", "@oxfmt/binding-linux-riscv64-musl": "0.52.0", "@oxfmt/binding-linux-s390x-gnu": "0.52.0", "@oxfmt/binding-linux-x64-gnu": "0.52.0", "@oxfmt/binding-linux-x64-musl": "0.52.0", "@oxfmt/binding-openharmony-arm64": "0.52.0", "@oxfmt/binding-win32-arm64-msvc": "0.52.0", "@oxfmt/binding-win32-ia32-msvc": "0.52.0", "@oxfmt/binding-win32-x64-msvc": "0.52.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-nJlYM35F64zTDMecCNhoHNkf+D/eHv7xcjj9XDSj+bFAVtN93m7v8DQMdHd6nDG6Akf/kEYYHmDUBs2Dz27Sug=="],
+ "oxfmt": ["oxfmt@0.65.0", "", { "dependencies": { "tinypool": "2.1.0" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.65.0", "@oxfmt/binding-android-arm64": "0.65.0", "@oxfmt/binding-darwin-arm64": "0.65.0", "@oxfmt/binding-darwin-x64": "0.65.0", "@oxfmt/binding-freebsd-x64": "0.65.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.65.0", "@oxfmt/binding-linux-arm-musleabihf": "0.65.0", "@oxfmt/binding-linux-arm64-gnu": "0.65.0", "@oxfmt/binding-linux-arm64-musl": "0.65.0", "@oxfmt/binding-linux-ppc64-gnu": "0.65.0", "@oxfmt/binding-linux-riscv64-gnu": "0.65.0", "@oxfmt/binding-linux-riscv64-musl": "0.65.0", "@oxfmt/binding-linux-s390x-gnu": "0.65.0", "@oxfmt/binding-linux-x64-gnu": "0.65.0", "@oxfmt/binding-linux-x64-musl": "0.65.0", "@oxfmt/binding-openharmony-arm64": "0.65.0", "@oxfmt/binding-win32-arm64-msvc": "0.65.0", "@oxfmt/binding-win32-ia32-msvc": "0.65.0", "@oxfmt/binding-win32-x64-msvc": "0.65.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-SgS5VgnP42T0zl3zWD+xoH8FCqg1SAFnSRoOT/qeoa6gxcYIqrDMOmcXIg/EWSN92Du4ogB4riuKhKd6Y4CGhw=="],
- "oxlint": ["oxlint@1.67.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.67.0", "@oxlint/binding-android-arm64": "1.67.0", "@oxlint/binding-darwin-arm64": "1.67.0", "@oxlint/binding-darwin-x64": "1.67.0", "@oxlint/binding-freebsd-x64": "1.67.0", "@oxlint/binding-linux-arm-gnueabihf": "1.67.0", "@oxlint/binding-linux-arm-musleabihf": "1.67.0", "@oxlint/binding-linux-arm64-gnu": "1.67.0", "@oxlint/binding-linux-arm64-musl": "1.67.0", "@oxlint/binding-linux-ppc64-gnu": "1.67.0", "@oxlint/binding-linux-riscv64-gnu": "1.67.0", "@oxlint/binding-linux-riscv64-musl": "1.67.0", "@oxlint/binding-linux-s390x-gnu": "1.67.0", "@oxlint/binding-linux-x64-gnu": "1.67.0", "@oxlint/binding-linux-x64-musl": "1.67.0", "@oxlint/binding-openharmony-arm64": "1.67.0", "@oxlint/binding-win32-arm64-msvc": "1.67.0", "@oxlint/binding-win32-ia32-msvc": "1.67.0", "@oxlint/binding-win32-x64-msvc": "1.67.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.22.1", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-blwwaHPdoH8piQ5/z0KHeoHFR7FZgl12WluKJfu4qFLPkZl6mK04PkLE45Fw1NxfBRSlh40Gu7MkxHUw++ociQ=="],
+ "oxlint": ["oxlint@1.80.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.80.0", "@oxlint/binding-android-arm64": "1.80.0", "@oxlint/binding-darwin-arm64": "1.80.0", "@oxlint/binding-darwin-x64": "1.80.0", "@oxlint/binding-freebsd-x64": "1.80.0", "@oxlint/binding-linux-arm-gnueabihf": "1.80.0", "@oxlint/binding-linux-arm-musleabihf": "1.80.0", "@oxlint/binding-linux-arm64-gnu": "1.80.0", "@oxlint/binding-linux-arm64-musl": "1.80.0", "@oxlint/binding-linux-ppc64-gnu": "1.80.0", "@oxlint/binding-linux-riscv64-gnu": "1.80.0", "@oxlint/binding-linux-riscv64-musl": "1.80.0", "@oxlint/binding-linux-s390x-gnu": "1.80.0", "@oxlint/binding-linux-x64-gnu": "1.80.0", "@oxlint/binding-linux-x64-musl": "1.80.0", "@oxlint/binding-openharmony-arm64": "1.80.0", "@oxlint/binding-win32-arm64-msvc": "1.80.0", "@oxlint/binding-win32-ia32-msvc": "1.80.0", "@oxlint/binding-win32-x64-msvc": "1.80.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-5nTiSps4qdbCWLbxzuO00alHkEO2exR9YMN/ig6QXWrLsYSG0KaObOAM+l6oU2LcKPWoSAGYbkZIGEu1ViiWKA=="],
- "oxlint-plugin-eslint": ["oxlint-plugin-eslint@1.68.0", "", {}, "sha512-VuHdZ4go8jb0IGBBonehCC2QTy8KsuK/vj3b0MQJ3S7LlIF+o6FfNbmsekKSBtEU0f0egxnbY8h5T23gj/KwfA=="],
+ "oxlint-plugin-eslint": ["oxlint-plugin-eslint@1.80.0", "", {}, "sha512-ElAyNkGRwxc+sMiSn/aJG0Qta7DkPqeLqDENz3iRm5UMgVaISO1Golm0vRo3UM8+DYQhHos2548gjS7lrjHc1w=="],
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
- "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
+ "parse-imports-exports": ["parse-imports-exports@0.2.4", "", { "dependencies": { "parse-statements": "1.0.11" } }, "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ=="],
- "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
+ "parse-statements": ["parse-statements@1.0.11", "", {}, "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
- "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
-
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
"picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
@@ -393,49 +331,33 @@
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
- "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="],
-
- "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
-
- "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
-
- "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
+ "reserved-identifiers": ["reserved-identifiers@1.2.0", "", {}, "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw=="],
- "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+ "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="],
- "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="],
-
- "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
-
- "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="],
+ "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
- "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
-
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
- "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
-
- "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+ "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
- "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+ "spdx-expression-parse": ["spdx-expression-parse@5.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-vngmw3Rgn+o2arXNbnZaj5UtOEBuWBfvaI+Wc8GFfykIhA5/vdK9/Sp/XkLv63dykz2rxKDvKEHupF5P0FORcQ=="],
- "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+ "spdx-license-ids": ["spdx-license-ids@3.0.23", "", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="],
- "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
-
- "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
-
- "svgo": ["svgo@4.0.1", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.5.0" }, "bin": "./bin/svgo.js" }, "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w=="],
+ "svgo": ["svgo@4.1.0", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^6.0.0", "css-tree": "^3.0.1", "css-what": "^7.0.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "1.6.1" }, "bin": { "svgo": "bin/svgo.js" } }, "sha512-bkxnTg1kSU0guhIBmibA6UUhrQmPVA1XsQLN+ylCd+UWzbnLkySOcXpyk1mrl05f+pcaCx2eHb+sp6BgMZWX+Q=="],
"tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
"tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
- "toml-eslint-parser": ["toml-eslint-parser@1.0.0", "", { "dependencies": { "eslint-visitor-keys": "^5.0.0" } }, "sha512-syGkwm4fa+uOzswyJQy6aFmmpcSBm/M0+F/iOAWfDkFuz33OnPMJkVQzaCk10WpqwzKcbaeAJWxfSGkkH8GiBw=="],
+ "to-valid-identifier": ["to-valid-identifier@1.0.0", "", { "dependencies": { "@sindresorhus/base62": "^1.0.0", "reserved-identifiers": "^1.0.0" } }, "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw=="],
+
+ "toml-eslint-parser": ["toml-eslint-parser@1.0.3", "", { "dependencies": { "eslint-visitor-keys": "^5.0.0" } }, "sha512-A5F0cM6+mDleacLIEUkmfpkBbnHJFV1d2rprHU2MXNk7mlxHq2zGojA+SRvQD1RoMo9gqjZPWEaKG4v1BQ48lw=="],
"ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
@@ -451,60 +373,26 @@
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
- "workerpool": ["workerpool@9.3.4", "", {}, "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg=="],
-
- "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
-
- "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
-
- "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
-
- "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
-
- "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
-
- "yargs-unparser": ["yargs-unparser@2.0.0", "", { "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" } }, "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA=="],
-
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
- "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
-
- "@isaacs/cliui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
-
- "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
+ "css-select/domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
- "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
-
- "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
-
- "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+ "css-select/domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
"csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="],
- "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
-
- "glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
-
- "mocha/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
+ "eslint/escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
- "toml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
+ "css-select/domhandler/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
- "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
+ "css-select/domutils/dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
- "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
-
- "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
-
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
+ "css-select/domutils/domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
- "glob/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
-
- "mocha/minimatch/brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="],
-
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+ "css-select/domutils/dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
}
}
diff --git a/docs/updates.md b/docs/updates.md
index 9afe0786..209a73a9 100644
--- a/docs/updates.md
+++ b/docs/updates.md
@@ -17,3 +17,27 @@ Here are the standardized rules that the `engine.json` file and `release.yml` wo
The `release.yml` workflow must handle all of these possible human mistakes, and ensure that these never happen in production.
This workflow must allow for the only necessary human interaction to be to start the workflow with the proper options, while everything forwards must always remain automated.
+
+## Triggering a new release
+
+Due to our collaboration with SignPath, we now sign all of our stable releases. This results in our stable release workflow being different than our beta release workflow.
+
+### Beta (Cosine)
+
+- Initialize a new release with the tag of the new version you want to deploy, with a 'c' suffix. (meaning Cosine, e.g. v2.3.4.0c)
+- Fill in details regarding the main goal of this release and the changelog.
+- Save the release as a draft, **do not publish, releases are immutable once published**.
+- Trigger the "Deploy latest assets" workflow (our main deploy workflow) on the Cosine branch with the release version (excluding 'v' prefix and 'c' suffix) and the version type (0, 1, 2).
+- Once the asset deployment workflow is complete, you may publish the draft release (assuming all data appears as intended).
+
+### Stable
+
+- Initialize a new release with the tag of the new version you want to deploy. (e.g. v2.3.4.0)
+- Fill in details regarding the main goal of this release and the changelog.
+- Save the release as a draft, **do not publish, releases are immutable once published**.
+- Trigger the "Build cross-platform installers" workflow on the main branch with release version, excluding 'v' prefix. (e.g. 2.3.4.0), as well as the version of the Sine bootloader that should be bundled with the release, excluding 'v' prefix (e.g. 0.1.4).
+- The installer-building workflow should then submit the assets to SignPath for reviewal and signing.
+- When SignPath approves and signs the assets (1-3 business days), the "Deploy latest assets" workflow will then be ready to be triggered.
+ Trigger it with the release version (excluding 'v' prefix), the version type (0, 1, 2), and the run_id for the build workflow specified earlier.
+- Once the asset deployment workflow is complete, you may publish the draft release (assuming all data appears as intended), but it is recommended to first verify that the Windows installer does not have a SmartScreen prompt when downloaded and executed from the draft release.
+ If the SmartScreen prompt does appear, it means the installer was not properly signed, and a reviewal of our submission process must be performed, as well as a checkup with SignPath.
diff --git a/engine.json b/engine.json
index 5cb46b4c..3fcaafa1 100644
--- a/engine.json
+++ b/engine.json
@@ -5,6 +5,14 @@
"enginePath": "engine.zip",
"profilePath": "profile.zip",
"updates": [
+ {
+ "version": "2.3.4.1c",
+ "type": 0
+ },
+ {
+ "version": "2.3.4.0c",
+ "type": 0
+ },
{
"version": "2.3.3.0",
"type": 0
diff --git a/oxlint.config.ts b/oxlint.config.ts
index 55f3d431..1c4f8e7c 100644
--- a/oxlint.config.ts
+++ b/oxlint.config.ts
@@ -1,29 +1,40 @@
/**
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ * @file Oxlint configuration. This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at
+ * http://mozilla.org/MPL/2.0/.
*/
import { defineConfig } from "oxlint";
-import type { OxlintConfig } from "oxlint";
+import type { OxlintConfig, OxlintGlobals } from "oxlint";
import mozilla from "./tools/oxlint-plugin-mozilla/lib/index.mjs";
+import browserWindow from "./tools/oxlint-plugin-mozilla/lib/environments/browser-window.mjs";
const mozillaConfig = (mozilla.configs as Record)["flat/recommended"];
+const requireJsdoc = (mozilla.configs as Record)["flat/require-jsdoc"];
+const validJsdoc = (mozilla.configs as Record)["flat/valid-jsdoc"];
+
+const browserGlobals = browserWindow.globals as OxlintGlobals;
export default defineConfig({
- extends: [mozillaConfig],
- plugins: ["jsdoc"],
+ extends: [mozillaConfig, validJsdoc, requireJsdoc],
jsPlugins: [
"./tools/oxlint-plugin-mozilla/lib/index.mjs",
"./tools/oxlint-plugin-mpl/lib/index.mjs",
],
+ rules: {
+ "oxlint-plugin-mpl/require-mpl-header": "error",
+ },
overrides: [
{
- files: ["**/*.{tsx,ts,mjs,js,jsx,cjs}"],
- rules: {
- "oxlint-plugin-mpl/require-mpl-header": "error",
+ files: ["src/core/settings.mjs"],
+ globals: {
+ gCategoryInits: "readonly",
},
},
+ {
+ files: ["src/core/browser.mjs", "src/services/updates.mjs"],
+ globals: Object.assign({}, browserGlobals, { gZenMods: "readonly" }),
+ },
],
ignorePatterns: ["src/assets/imports/"],
});
diff --git a/package.json b/package.json
index 224b4e52..34c2917a 100644
--- a/package.json
+++ b/package.json
@@ -30,9 +30,10 @@
"devDependencies": {
"@chromejs/browsercfg": "^0.1.8",
"@types/bun": "latest",
- "oxfmt": "^0.52.0",
- "oxlint": "^1.67.0",
- "oxlint-plugin-eslint": "^1.68.0",
- "svgo": "^4.0.1"
+ "eslint-plugin-jsdoc": "^64.2.1",
+ "oxfmt": "^0.65.0",
+ "oxlint": "^1.80.0",
+ "oxlint-plugin-eslint": "^1.80.0",
+ "svgo": "^4.1.0"
}
}
diff --git a/src/actors/MarketplaceChild.sys.mjs b/src/actors/MarketplaceChild.sys.mjs
index 75eb80ef..4545d832 100644
--- a/src/actors/MarketplaceChild.sys.mjs
+++ b/src/actors/MarketplaceChild.sys.mjs
@@ -1,15 +1,23 @@
/**
+ * @file Defines child window actor class for Sine store and Zen Mods site.
+ * @license
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-// ===========================================================
-// This module interacts with the site in the JS Window Actor
-// for the Zen Mods site.
-// ===========================================================
-
+/**
+ * Child window actor class for Sine store and Zen Mods mod installation from site.
+ *
+ * @class
+ */
export class SineModsMarketplaceChild extends JSWindowActorChild {
+ /**
+ * Main entrypoint of class. Handles new window loading.
+ *
+ * @param {object} event - Event to handle.
+ * @param {string} event.type - The name of the event. (only care if DOMContentLoaded)
+ */
handleEvent(event) {
if (event.type === "DOMContentLoaded") {
const verifier = this.contentWindow.document.querySelector(
@@ -24,6 +32,7 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
}
}
+ /** Executes main functions to load main child actor functionality. */
initiateModsMarketplace() {
this.contentWindow.setTimeout(() => {
this.addButtons();
@@ -31,19 +40,41 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
}, 0);
}
+ /**
+ * Returns install theme button on Zen Mods site.
+ *
+ * @returns {HTMLElement} Install theme button on Zen Mods site.
+ */
get actionButton() {
- return this.contentWindow.document.getElementById("install-theme");
+ return this.contentWindow.document.querySelector("#install-theme");
}
+ /**
+ * Returns uninstall theme button on Zen Mods site.
+ *
+ * @returns {HTMLElement} Uninstall theme button on Zen Mods site.
+ */
get actionButtonUninstall() {
- return this.contentWindow.document.getElementById("install-theme-uninstall");
+ return this.contentWindow.document.querySelector("#install-theme-uninstall");
}
+ /**
+ * Checks if a theme with an id is installed.
+ *
+ * @param {string} themeId - Theme id to check installation status of.
+ * @returns {boolean} Is theme installed boolean.
+ */
async isThemeInstalled(themeId) {
return await this.sendQuery("SineModsMarketplace:IsModInstalled", { themeId });
}
- getModId(event) {
+ /**
+ * Extracts mod id from event.
+ *
+ * @param {object} event - Event to extract mod id from.
+ * @returns {string} Mod id.
+ */
+ static getModId(event) {
if (event.target) {
const button = event.target;
button.disabled = true;
@@ -55,13 +86,26 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
return event.themeId ?? event.modId ?? event.id;
}
+ /**
+ * Returns a single mod install button, given a mod id.
+ *
+ * @param {string} modId - Mod id to fetch install button of.
+ * @returns {HTMLElement} Install button element.
+ */
getInstallButton(modId) {
return (
this.contentWindow.document.querySelector(`.action-install[theme-id="${modId}"]`) ??
- this.contentWindow.document.getElementById("install-theme")
+ this.contentWindow.document.querySelector("#install-theme")
);
}
+ /**
+ * Message handler.
+ *
+ * @param {object} message - Message received.
+ * @param {string} message.name - Name of message received.
+ * @param {object} message.data - Optional data received for message.
+ */
async receiveMessage(message) {
switch (message.name) {
case "SineModsMarketplace:ModChanged": {
@@ -95,9 +139,15 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
break;
}
+
+ default: {
+ console.error("[Sine:MarketplaceChild]: Unknown message received.");
+ break;
+ }
}
}
+ /** Injects installation API into site. */
injectMarketplaceAPI() {
// Remove the original Zen variable for injection.
delete window.ZenInstallMod;
@@ -107,12 +157,13 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
});
}
+ /** Displays and adds functionality to install and uninstall buttons. */
async addButtons() {
- this.contentWindow.document.getElementById("install-theme-error").classList.add("hidden");
+ this.contentWindow.document.querySelector("#install-theme-error").classList.add("hidden");
const actionButtons = [
- ...this.contentWindow.document.getElementsByClassName("action-install"),
- this.contentWindow.document.getElementById("install-theme"),
+ ...this.contentWindow.document.querySelectorAll(".action-install"),
+ this.contentWindow.document.querySelector("#install-theme"),
];
const promises = [];
for (const actionButton of actionButtons) {
@@ -140,14 +191,24 @@ export class SineModsMarketplaceChild extends JSWindowActorChild {
await Promise.all(promises);
}
+ /**
+ * Handles uninstall event for the corresponding buttons.
+ *
+ * @param {object} event - Event to extract mod id from.
+ */
handleModUninstallEvent(event) {
- const modId = this.getModId(event);
+ const modId = this.constructor.getModId(event);
this.sendAsyncMessage("SineModsMarketplace:UninstallMod", { modId });
}
+ /**
+ * Handles install event for the corresponding buttons.
+ *
+ * @param {object} event - Event to extract mod id from.
+ */
handleModInstallationEvent(event) {
// Object can be an event or a theme id
- const modId = this.getModId(event);
+ const modId = this.constructor.getModId(event);
this.sendAsyncMessage("SineModsMarketplace:InstallMod", { modId });
}
}
diff --git a/src/actors/MarketplaceParent.sys.mjs b/src/actors/MarketplaceParent.sys.mjs
index e61b60d3..e47d495c 100644
--- a/src/actors/MarketplaceParent.sys.mjs
+++ b/src/actors/MarketplaceParent.sys.mjs
@@ -1,19 +1,35 @@
/**
+ * @file Defines parent window actor class for Sine store and Zen Mods site.
+ * @license
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-// ===========================================================
-// This module allows the JS Window Actor for the Zen Mods
-// site to interact with global variables.
-// ===========================================================
-
+/**
+ * Parent window actor class for Sine store and Zen Mods mod installation from site.
+ *
+ * @class
+ */
export class SineModsMarketplaceParent extends JSWindowActorParent {
+ /**
+ * Returns mod manager API.
+ *
+ * @returns {object} Mod manager API in the form of { utils, manager }.
+ */
get modsManager() {
return this.browsingContext.topChromeWindow.SineAPI;
}
+ /**
+ * Message handler.
+ *
+ * @param {object} message - Received message.
+ * @param {string} message.name - Name of received message.
+ * @param {object} message.data - Optional message data.
+ * @returns {boolean | null} Returns boolean for theme installation status, or null for other
+ * messages.
+ */
async receiveMessage(message) {
switch (message.name) {
case "SineModsMarketplace:InstallMod": {
@@ -32,10 +48,6 @@ export class SineModsMarketplaceParent extends JSWindowActorParent {
case "SineModsMarketplace:UninstallMod": {
const modId = message.data.modId;
- const mods = await this.modsManager.utils.getMods();
-
- delete mods[modId];
-
await this.modsManager.manager.removeMod(modId);
await this.modsManager.manager.rebuildMods(false);
@@ -49,10 +61,19 @@ export class SineModsMarketplaceParent extends JSWindowActorParent {
return Boolean(themes?.[themeId]);
}
+ default: {
+ console.error("[Sine:MarketplaceParent]: Unknown message received.");
+ break;
+ }
}
return null;
}
+ /**
+ * Triggers a mod changed event on the parent class.
+ *
+ * @param {string} modId - Mod id to trigger mod changed event on.
+ */
updateChildProcesses(modId) {
this.sendAsyncMessage("SineModsMarketplace:ModChanged", { modId });
}
diff --git a/src/core/browser.mjs b/src/core/browser.mjs
index 22821a47..83a07f6b 100644
--- a/src/core/browser.mjs
+++ b/src/core/browser.mjs
@@ -1,23 +1,20 @@
/**
+ * @file Initializes a browser window with necessary Sine features.
+ * @license
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-// ===========================================================
-// Initializes a browser window instance with necessary
-// variables and check for updates.
-// ===========================================================
-
-import domUtils from "../utils/dom.mjs";
+import * as domUtils from "../utils/dom.mjs";
import updates from "../services/updates.mjs";
+import cmdPalette from "../services/cmdPalette.mjs";
-import injectCmdPalette from "../services/cmdPalette.js";
await domUtils.waitForElm("body");
domUtils.injectLocale("sine-toasts");
-injectCmdPalette();
+cmdPalette.register();
const ucAPI = ChromeUtils.importESModule(
"chrome://userscripts/content/utils/uc_api.sys.mjs"
@@ -42,7 +39,7 @@ if (ucAPI.utils.fork === "zen") {
mod.preferences = "preferences.json";
}
}
- await IOUtils.writeJSON(utils.modsDataFile, { ...sineMods, ...zenMods });
+ await IOUtils.writeJSON(utils.modsDataFile, Object.assign({}, sineMods, zenMods));
const zenModsPath = gZenMods.modsRootPath;
const promises = Object.keys(zenMods).map(async (id) => {
diff --git a/src/core/manager.sys.mjs b/src/core/manager.sys.mjs
index 0ca2324e..fd369429 100644
--- a/src/core/manager.sys.mjs
+++ b/src/core/manager.sys.mjs
@@ -1,18 +1,20 @@
/**
+ * @file Manages mods, including basic Sine functionality.
+ * @license
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-// ===========================================================
-// Manages mods and themes, allowing Sine to install, update,
-// enable, disable, and configure them.
-// ===========================================================
-
import utils from "./utils.sys.mjs";
-import domUtils from "../utils/dom.mjs";
+import * as domUtils from "../utils/dom.mjs";
import ucAPI from "../utils/uc_api.sys.mjs";
+/**
+ * Main mod manager class.
+ *
+ * @class
+ */
class Manager {
preferences = ChromeUtils.importESModule("chrome://userscripts/content/core/preferences.sys.mjs");
marketplace = ChromeUtils.importESModule(
@@ -21,16 +23,32 @@ class Manager {
#stylesheetManager = ChromeUtils.importESModule(
"chrome://userscripts/content/services/stylesheets.sys.mjs"
).default;
- #unloadListeners = {};
-
+ #unloadListeners = new Map();
+
+ /**
+ * Adds an unload listener to #unloadListeners.
+ *
+ * @param {string} script - Script path to assign an unload listener to.
+ * @param {Window} window - Window to relate unload listener to.
+ * @param {() => void} callback - Callback to execute when unload listener is triggered.
+ */
addUnloadListener(script, window, callback) {
- this.#unloadListeners[script] ??= new Map();
- const scriptListeners = this.#unloadListeners[script];
+ if (!this.#unloadListeners.has(script)) {
+ this.#unloadListeners.set(script, new Map());
+ }
+ const scriptListeners = this.#unloadListeners.get(script);
scriptListeners.set(window, callback);
}
+ /**
+ * Triggers an unload listener from #unloadListeners.
+ *
+ * @param {string} chromePath - Path of script to unload.
+ * @param {Window} window - Window to unload script from.
+ * @returns {boolean} Whether script remains loaded or not.
+ */
async triggerUnloadListener(chromePath, window) {
- const listeners = this.#unloadListeners[chromePath];
+ const listeners = this.#unloadListeners.get(chromePath);
if (!listeners) return false;
// If there is no match for the window, then the script was not loaded in this DOM.
@@ -49,30 +67,42 @@ class Manager {
listeners.delete(window);
if (listeners.size === 0) {
- delete this.#unloadListeners[chromePath];
+ this.#unloadListeners.delete(chromePath);
}
// Script is no longer loaded, return false.
return false;
}
+ /**
+ * Removes all unload listeners related to a mod. Should be triggered when a mod is uninstalled or
+ * disabled.
+ *
+ * @param {string} modId - Id of mod to remove unload listeners of.
+ */
async removeUnloadListeners(modId) {
const allUnloadPromises = [];
- for (const [scriptName, listeners] of Object.entries(this.#unloadListeners)) {
+ for (const [scriptName, listeners] of this.#unloadListeners) {
if (scriptName.startsWith(`chrome://sine/content/${modId}/`)) {
for (const listener of listeners.values()) {
if (listener) {
allUnloadPromises.push(listener());
}
}
- delete this.#unloadListeners[scriptName];
+ this.#unloadListeners.delete(scriptName);
}
}
await Promise.all(allUnloadPromises);
}
+ /**
+ * Removes all unload listeners related to a window. Should be executed when a window is closed or
+ * unloaded.
+ *
+ * @param {Window} window - Window to remove unload listeners from.
+ */
removeListenersForDOM(window) {
- for (const listeners of Object.values(this.#unloadListeners)) {
+ for (const listeners of this.#unloadListeners.values()) {
if (listeners.has(window)) {
const windowListener = listeners.get(window);
if (windowListener) {
@@ -84,6 +114,12 @@ class Manager {
}
}
+ /**
+ * Appends Sine interfaces to a window object. Should be executed when a window that a mod may run
+ * in is opened.
+ *
+ * @param {Window} window - Window to append interface to.
+ */
appendInterfaceToDOM(window) {
const addUnloadListener = this.addUnloadListener.bind(this);
window.addUnloadListener = (callback, scriptPath) => {
@@ -103,7 +139,13 @@ class Manager {
window.triggerUnloadListener = this.triggerUnloadListener.bind(this);
}
- #registerChromeManifest(manifestPath, modId) {
+ /**
+ * Registers a mod's chrome manifest.
+ *
+ * @param {string} manifestPath - Chrome URI path to a manifest file.
+ * @param {string} modId - Mod id to register manifest of.
+ */
+ static #registerChromeManifest(manifestPath, modId) {
if (!manifestPath) return;
const cmanifest = Services.dirsvc.get("UChrm", Ci.nsIFile);
@@ -120,6 +162,12 @@ class Manager {
}
}
+ /**
+ * Rebuilds all mods. If both parameters are disabled, function will rebuild mod-related DOM data.
+ *
+ * @param {boolean} rebuildJS - If true, will load/reload JavaScript.
+ * @param {boolean} reloadStyles - If true, will load/reload styles.
+ */
async rebuildMods(rebuildJS = true, reloadStyles = true) {
if (Services.prefs.getBoolPref("sine.mods.disable-all", false)) {
return;
@@ -137,7 +185,7 @@ class Manager {
// Load chrome uris.
for (const mod of Object.values(mods)) {
- this.#registerChromeManifest(mod.chromeManifest, mod.id);
+ this.constructor.#registerChromeManifest(mod.chromeManifest, mod.id);
}
// Inject background modules.
@@ -145,9 +193,9 @@ class Manager {
if (scriptPath.endsWith(".sys.mjs")) {
const chromePath = `chrome://sine/content/${scriptPath}`;
- // TODO: Find a way to pass addUnloadListener to background scripts.
+ // TODO: Find a way to pass Sine interface to background scripts. Sandboxing execution?
try {
- if (scripts[scriptPath].enabled && !Object.hasOwn(this.#unloadListeners, chromePath)) {
+ if (scripts[scriptPath].enabled && !this.#unloadListeners.has(chromePath)) {
// Null is being passed as window until a reference for such is found.
this.addUnloadListener(chromePath, null, null);
ChromeUtils.importESModule(chromePath);
@@ -194,8 +242,16 @@ class Manager {
await Promise.all(promises);
}
+ /**
+ * Observes new chrome window events.
+ *
+ * @param {Window} subject - Window that is being observed.
+ * @param {string} topic - Topic specifying what the function is called for.
+ */
observe(subject, topic) {
if (topic === "chrome-document-global-created" && subject) {
+ this.#stylesheetManager.onWindow(subject);
+
subject.addEventListener("load", async (event) => {
const window = event.target.defaultView;
@@ -210,9 +266,11 @@ class Manager {
this.appendInterfaceToDOM(window);
window.newDOM = true;
- ChromeUtils.compileScript("chrome://userscripts/content/services/module_loader.mjs").then(
- (script) => script.executeInGlobal(window)
- );
+ ChromeUtils.compileScript("chrome://userscripts/content/services/module_loader.mjs")
+ .then((script) => script.executeInGlobal(window))
+ .catch((err) =>
+ console.error(`[Sine:Manager]: Failed to compile module loader.\n${err}`)
+ );
for (const scriptPath of Object.keys(scripts)) {
if (scriptPath.endsWith(".uc.js")) {
@@ -222,8 +280,6 @@ class Manager {
});
}
}
-
- this.#stylesheetManager.onWindow(window);
});
subject.addEventListener("beforeunload", (event) => {
@@ -233,15 +289,23 @@ class Manager {
}
}
+ /** Initializes window listener, calling this.observe when a new chrome window is initialized. */
initWinListener() {
Services.obs.addObserver(this, "chrome-document-global-created");
}
+ /**
+ * Uninstalls a mod.
+ *
+ * @param {string} id - Id of mod to uninstall.
+ */
async removeMod(id) {
// Unload JS listeners first.
await this.removeUnloadListeners(id);
const installedMods = await utils.getMods();
+ // TODO: Possibly optimize.
+ // oxlint-disable-next-line typescript/no-dynamic-delete
delete installedMods[id];
await IOUtils.writeJSON(utils.modsDataFile, installedMods);
@@ -250,7 +314,16 @@ class Manager {
this.rebuildMods(false);
}
- #buildModXUL(document, modId, modData, modsChanged) {
+ /**
+ * Appends a mod interface to the DOM. (specifically the settings page)
+ *
+ * @param {HTMLDocument} document - Document to append mod XUL to.
+ * @param {string} modId - Id of mod to append to DOM.
+ * @param {object} modData - Mod data to append to DOM.
+ * @param {string[] | null} modsChanged - List of changed mod ids.
+ * @returns {HTMLElement} Element that was appended.
+ */
+ static #buildModXUL(document, modId, modData, modsChanged) {
const item = domUtils.appendXUL(
document.querySelector("#sineModsList"),
`
@@ -296,9 +369,9 @@ class Manager {
const enableToggleLocale = "sine-mod-disable";
if (modData.enabled) {
enableToggle.setAttribute("pressed", "");
- enableToggle.setAttribute("data-l10n-id", `${enableToggleLocale}-enabled`);
+ enableToggle.dataset.l10nId = `${enableToggleLocale}-enabled`;
} else {
- enableToggle.setAttribute("data-l10n-id", `${enableToggleLocale}-disabled`);
+ enableToggle.dataset.l10nId = `${enableToggleLocale}-disabled`;
}
if (modData.preferences) {
@@ -317,8 +390,8 @@ class Manager {
const configureBtn = document.createElement("button");
configureBtn.className = "sineItemConfigureButton";
- configureBtn.setAttribute("data-l10n-id", "sine-settings-button");
- configureBtn.setAttribute("data-l10n-attrs", "title");
+ configureBtn.dataset.l10nId = "sine-settings-button";
+ configureBtn.dataset.l10nAttrs = "title";
const sineItemActions = item.querySelector(".sineItemActions");
sineItemActions.insertBefore(configureBtn, sineItemActions.children[0]);
@@ -328,16 +401,22 @@ class Manager {
const updateToggleLocale = "sine-mod-update-disable";
if (modData["no-updates"]) {
updateToggle.setAttribute("enabled", "");
- updateToggle.setAttribute("data-l10n-id", `${updateToggleLocale}-enabled`);
+ updateToggle.dataset.l10nId = `${updateToggleLocale}-enabled`;
} else {
- updateToggle.setAttribute("data-l10n-id", `${updateToggleLocale}-disabled`);
+ updateToggle.dataset.l10nId = `${updateToggleLocale}-disabled`;
}
return item;
}
+ /**
+ * Loads all mods into the settings page DOM.
+ *
+ * @param {Window | null} specificWindow - Specific window to load mods into.
+ * @param {string[] | null} modsChanged - List of changed/updated mod ids.
+ */
async loadMods(specificWindow = null, modsChanged = null) {
- let installedMods = await utils.getMods();
+ const installedMods = await utils.getMods();
const pages = utils.getProcesses(specificWindow, ["settings", "preferences"]);
for (const window of pages) {
@@ -345,7 +424,14 @@ class Manager {
document.querySelector("#sineModsList").innerHTML = "";
- if (!Services.prefs.getBoolPref("sine.mods.disable-all", false)) {
+ if (Services.prefs.getBoolPref("sine.mods.disable-all", false)) {
+ domUtils.appendXUL(
+ document.querySelector("#sineModsList"),
+ ``,
+ null,
+ window.MozXULElement
+ );
+ } else {
const sortedArr = Object.values(installedMods).toSorted((a, b) =>
a.name.localeCompare(b.name)
);
@@ -353,21 +439,18 @@ class Manager {
for (const key of ids) {
const modData = installedMods[key];
// Create new item.
- const item = this.#buildModXUL(document, key, modData, modsChanged);
+ const item = this.constructor.#buildModXUL(document, key, modData, modsChanged);
const modVersion = modData.version ? ` (v${modData.version})` : "";
- item.querySelectorAll(".sineItemTitle").forEach((el) => {
+ for (const el of item.querySelectorAll(".sineItemTitle")) {
el.textContent = modData.name + modVersion;
- });
+ }
const toggle = item.querySelector(".sineItemPreferenceToggle");
toggle.addEventListener("toggle", async () => {
- installedMods = await utils.getMods();
- const theme = await this.toggleTheme(installedMods, modData.id);
- toggle.setAttribute(
- "data-l10n-id",
- `sine-mod-disable-${theme.enabled ? "enabled" : "disabled"}`
- );
+ const currMods = await utils.getMods();
+ const theme = await this.toggleTheme(currMods, modData.id);
+ toggle.dataset.l10nId = `sine-mod-disable-${theme.enabled ? "enabled" : "disabled"}`;
});
if (Object.hasOwn(modData, "preferences") && modData.preferences !== "") {
@@ -382,7 +465,7 @@ class Manager {
for (const pref of modPrefs) {
const prefEl = this.preferences.parsePref(pref, this, window);
if (prefEl) {
- item.querySelector(".sineItemPreferenceDialogContent").appendChild(prefEl);
+ item.querySelector(".sineItemPreferenceDialogContent").append(prefEl);
}
}
};
@@ -412,12 +495,12 @@ class Manager {
updateButton.addEventListener("click", async () => {
const latestMods = await utils.getMods();
latestMods[key]["no-updates"] = !latestMods[key]["no-updates"];
- if (!updateButton.getAttribute("enabled")) {
- updateButton.setAttribute("enabled", true);
- updateButton.setAttribute("data-l10n-id", "sine-mod-update-disable-enabled");
- } else {
+ if (updateButton.getAttribute("enabled")) {
updateButton.removeAttribute("enabled");
- updateButton.setAttribute("data-l10n-id", "sine-mod-update-disable-disabled");
+ updateButton.dataset.l10nId = "sine-mod-update-disable-disabled";
+ } else {
+ updateButton.setAttribute("enabled", true);
+ updateButton.dataset.l10nId = "sine-mod-update-disable-enabled";
}
await IOUtils.writeJSON(utils.modsDataFile, latestMods);
});
@@ -457,17 +540,18 @@ class Manager {
window.MozXULElement
);
}
- } else {
- domUtils.appendXUL(
- document.querySelector("#sineModsList"),
- ``,
- null,
- window.MozXULElement
- );
}
}
}
+ /**
+ * Processes an update for a specific mod.
+ *
+ * @param {object} currModData - Current data of mod to process.
+ * @param {object} currModsList - Current list of mod data.
+ * @param {object} marketplaceData - Current marketplace data.
+ * @returns {object} Mod update details.
+ */
async processModUpdate(currModData, currModsList, marketplaceData) {
let newThemeData, githubAPI, originalData, homepage;
@@ -480,7 +564,7 @@ class Manager {
const minimalData = await this.createThemeJSON(
currModData.homepage,
currModsList,
- typeof originalData !== "object" ? {} : originalData,
+ typeof originalData === "object" ? originalData : {},
true
);
newThemeData = minimalData.theme;
@@ -504,7 +588,7 @@ class Manager {
const customData = await this.createThemeJSON(
currModData.homepage,
currModsList,
- typeof newThemeData !== "object" ? {} : newThemeData,
+ typeof newThemeData === "object" ? newThemeData : {},
false,
githubAPI
);
@@ -528,6 +612,13 @@ class Manager {
return { changed: true, modHasJS, id: currModData.id };
}
+ /**
+ * Checks for updates on all mods.
+ *
+ * @param {string | null} source - "auto" or null. If source is auto, will check if automatic
+ * updates are enabled.
+ * @returns {boolean} True if any mods have been updated.
+ */
async updateMods(source) {
if (source === "auto" && !utils.autoUpdate) return false;
@@ -577,14 +668,21 @@ class Manager {
});
}
- const modsHaveChanged = modsChanged.length !== 0;
- if (modsHaveChanged) {
- this.rebuildMods();
- this.loadMods(null, modsChanged);
+ if (modsChanged.length === 0) {
+ return false;
}
- return modsHaveChanged;
+ this.rebuildMods();
+ this.loadMods(null, modsChanged);
+ return true;
}
+ /**
+ * Installs a mod from a repository.
+ *
+ * @param {string} repo - GitHub repository to install from.
+ * @param {string | null} origin - Origin of mod, "store," or none.
+ * @param {boolean} reload - If true, will reload mods after installing.
+ */
async installMod(repo, origin, reload = true) {
const currModsList = await utils.getMods();
@@ -599,7 +697,7 @@ class Manager {
.fetch(`${utils.rawURL(repo)}theme.json`)
.then(
async (res) =>
- await this.createThemeJSON(repo, currModsList, typeof res !== "object" ? {} : res)
+ await this.createThemeJSON(repo, currModsList, typeof res === "object" ? res : {})
);
}
@@ -621,19 +719,27 @@ class Manager {
}
}
- parseGitHubUrl(url) {
- url = url.replace(/(\?.+)?(\/+)?$/, "");
+ /**
+ * Parses a GitHub URL into an object of data.
+ *
+ * @param {string} url - GitHub URL.
+ * @returns {object} Object of GitHub URL metadata.
+ */
+ static parseGitHubUrl(url) {
+ url = url.replace(/(\?.+)?(\/+)?$/u, "");
const regexes = [
- /^(?:https?:\/\/)?github\.com\/([^/]+)\/([^/]+)$/,
- /^(?:https?:\/\/)?github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/,
- /^(?:https?:\/\/)?raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/refs\/heads\/([^/]+)(\/.*)?$/,
- /^(?:https?:\/\/)?raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)(\/.*)?$/,
- /^([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/,
- /^([^/]+)\/([^/]+)$/,
+ /^(?:https?:\/\/)?github\.com\/([^/]+)\/([^/]+)$/u,
+ /^(?:https?:\/\/)?github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/u,
+ /^(?:https?:\/\/)?github\.com\/([^/]+)\/([^/]+)\/commit\/([^/]+)(\/.*)?$/u,
+ /^(?:https?:\/\/)?raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/refs\/heads\/([^/]+)(\/.*)?$/u,
+ /^(?:https?:\/\/)?raw\.githubusercontent\.com\/([^/]+)\/([^/]+)\/([^/]+)(\/.*)?$/u,
+ /^([^/]+)\/([^/]+)\/tree\/([^/]+)(\/.*)?$/u,
+ /^([^/]+)\/([^/]+)\/commit\/([^/]+)(\/.*)?$/u,
+ /^([^/]+)\/([^/]+)$/u,
];
- for (const regex of regexes) {
+ for (const [idx, regex] of regexes.entries()) {
const match = url.match(regex);
if (match) {
const author = match[1];
@@ -642,7 +748,11 @@ class Manager {
let branch = "main";
let folder = "";
if (match.length > 3) {
- branch = match[3];
+ if (idx === 2 || idx === 6) {
+ branch = match[3];
+ } else {
+ branch = `refs/heads/${match[3]}`;
+ }
folder = match[4] || "";
}
@@ -650,7 +760,7 @@ class Manager {
name: repo,
author,
branch,
- folder: folder.replace(/^\/+/, ""),
+ folder: folder.replace(/^\/+/u, ""),
};
}
}
@@ -658,11 +768,21 @@ class Manager {
throw new Error("[Sine]: Unknown GitHub repo format, unable to parse.");
}
- findFile(modId, fileNames, modEntries, repo, customUrl) {
+ /**
+ * Finds a singular file entrypoint from a list of possible matches.
+ *
+ * @param {string} modId - Id of mod to filter with.
+ * @param {string[]} fileNames - List of file names to search for.
+ * @param {string[]} modEntries - List of item entries.
+ * @param {object} repo - Repository metadata. (fetched from this.parseGitHubUrl)
+ * @param {string | null} customUrl - Custom file name to search for.
+ * @returns {string} Valid and matching file path to use.
+ */
+ static findFile(modId, fileNames, modEntries, repo, customUrl) {
const repoFolder = repo.folder ? `${repo.folder}/` : "";
const fileEntries = modEntries.filter(
(entry) =>
- (fileNames.filter((name) => entry.endsWith(name)).length !== 0 &&
+ (fileNames.some((name) => entry.endsWith(name)) &&
entry.startsWith(`${modId}/${repoFolder}`)) ||
entry === `${modId}/${repoFolder}${customUrl}`
);
@@ -693,17 +813,26 @@ class Manager {
return relativePath.replace(`${modId}/`, "");
}
+ /**
+ * Syncs a mod data (updates or installs), given mod metadata.
+ *
+ * @param {string} repoLink - Link to repository to fetch from.
+ * @param {object} currModsList - List of currently installed mods and their metadata.
+ * @param {object} newThemeData - New mod metadata to apply. (fetched via repoLink)
+ * @param {object | null} currModData - Previous metadata. (applicable in updates)
+ * @returns {boolean} Returns whether the installed mod has JS.
+ */
async syncModData(repoLink, currModsList, newThemeData, currModData = false) {
const themeFolder = utils.getModFolder(newThemeData.id);
- const nestedPath = `main/mods/${newThemeData.id}`;
if (repoLink === "{store}") {
- repoLink = `sineorg/store/tree/${nestedPath}`;
+ const repoData = this.constructor.parseGitHubUrl(newThemeData.homepage);
+ repoLink = `${repoData.author}/${repoData.name}/commit/${newThemeData.commit}/${repoData.folder}`;
newThemeData.origin = "store";
} else if (newThemeData.origin) {
// Prevent mods from pretending to be verified and from the store.
delete newThemeData.origin;
}
- let repo = this.parseGitHubUrl(repoLink);
+ let repo = this.constructor.parseGitHubUrl(repoLink);
const tmpFolder = PathUtils.join(utils.modsDir, `tmp-${currModData.id}`);
if (currModData) {
@@ -711,11 +840,7 @@ class Manager {
await IOUtils.remove(themeFolder, { recursive: true });
}
- let zipUrl = `https://codeload.github.com/${repo.author}/${repo.name}/zip/refs/heads/${repo.branch}`;
- if (newThemeData.origin === "store") {
- repo = this.parseGitHubUrl(newThemeData.homepage);
- zipUrl = `https://raw.githubusercontent.com/sineorg/store/${nestedPath}/mod.zip`;
- }
+ let zipUrl = `https://codeload.github.com/${repo.author}/${repo.name}/zip/${repo.branch}`;
const zipEntries = await ucAPI.unpackRemoteArchive({
url: zipUrl,
id: newThemeData.id,
@@ -748,7 +873,7 @@ class Manager {
const normalizePath = (value) =>
typeof value === "string" && value.startsWith("https://")
- ? this.parseGitHubUrl(value).folder
+ ? this.constructor.parseGitHubUrl(value).folder
: value;
customChrome = normalizePath(customChrome);
@@ -756,14 +881,14 @@ class Manager {
const customPreferences = normalizePath(preferences);
newThemeData.style = {};
- newThemeData.style.chrome = this.findFile(
+ newThemeData.style.chrome = this.constructor.findFile(
newThemeData.id,
["userChrome.css", "chrome.css"],
zipEntries,
repo,
customChrome
);
- newThemeData.style.content = this.findFile(
+ newThemeData.style.content = this.constructor.findFile(
newThemeData.id,
["userContent.css"],
zipEntries,
@@ -771,7 +896,7 @@ class Manager {
customContent
);
- newThemeData.preferences = this.findFile(
+ newThemeData.preferences = this.constructor.findFile(
newThemeData.id,
["preferences.json"],
zipEntries,
@@ -822,6 +947,13 @@ class Manager {
return false;
}
+ /**
+ * Toggles a mod to be enabled or disabled.
+ *
+ * @param {object} installedMods - Current list of installed mod metadata.
+ * @param {string} id - Id of mod to toggle.
+ * @returns {object} New mod metadata.
+ */
async toggleTheme(installedMods, id) {
const themeData = installedMods[id];
@@ -843,9 +975,15 @@ class Manager {
return themeData;
}
- translateToAPI(input) {
- const trimmedInput = input.trim().replace(/\/+$/, "");
- const regex = /(?:https?:\/\/github\.com\/)?([\w\-.]+)\/([\w\-.]+)/i;
+ /**
+ * Parses a standard GitHub link into an API link.
+ *
+ * @param {string} input - GitHub link to parse.
+ * @returns {string} API version of link.
+ */
+ static translateToAPI(input) {
+ const trimmedInput = input.trim().replace(/\/+$/u, "");
+ const regex = /(?:https?:\/\/github\.com\/)?([\w\-.]+)\/([\w\-.]+)/iu;
const match = trimmedInput.match(regex);
if (!match) {
return null;
@@ -855,6 +993,17 @@ class Manager {
return `https://api.github.com/repos/${user}/${returnRepo}`;
}
+ /**
+ * Generates a list of mod metadata based on specified parameters from a repo and defaults.
+ *
+ * @param {string} repo - Repo link which data was fetched from.
+ * @param {object} themes - List of currently installed mod data.
+ * @param {object} theme - Specified mod data. (defaults to an empty object)
+ * @param {boolean} minimal - Whether generated data should be minimal.
+ * @param {object | null} githubAPI - Optional GitHub API fetched from a previous minimal call.
+ * @returns {object} If minimal is true, an object of theme data and the GitHub API, or just theme
+ * data.
+ */
async createThemeJSON(repo, themes, theme = {}, minimal = false, githubAPI = null) {
const apiRequiringProperties = minimal ? ["updatedAt"] : ["description", "updatedAt"];
let needAPI = false;
@@ -864,7 +1013,7 @@ class Manager {
}
}
if (needAPI && !githubAPI) {
- githubAPI = ucAPI.fetch(translateToAPI(repo));
+ githubAPI = ucAPI.fetch(this.constructor.translateToAPI(repo));
}
let promise;
@@ -886,12 +1035,14 @@ class Manager {
setProperty("homepage", repo);
- const parsedRepo = this.parseGitHubUrl(repo);
+ const parsedRepo = this.constructor.parseGitHubUrl(repo);
setProperty("name", parsedRepo.folder || parsedRepo.name);
if (!Object.hasOwn(theme, "version")) {
promise = (async () => {
- const releasesData = await ucAPI.fetch(`${translateToAPI(repo)}/releases/latest`);
+ const releasesData = await ucAPI.fetch(
+ `${this.constructor.translateToAPI(repo)}/releases/latest`
+ );
setProperty(
"version",
Object.hasOwn(releasesData, "tag_name")
diff --git a/src/core/preferences.sys.mjs b/src/core/preferences.sys.mjs
index 74921326..8dd88e11 100644
--- a/src/core/preferences.sys.mjs
+++ b/src/core/preferences.sys.mjs
@@ -1,4 +1,6 @@
/**
+ * @file Defines mod preference management.
+ * @license
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
@@ -10,7 +12,7 @@
// ===========================================================
import utils from "./utils.sys.mjs";
-import domUtils from "../utils/dom.mjs";
+import * as domUtils from "../utils/dom.mjs";
import ucAPI from "../utils/uc_api.sys.mjs";
const tagNames = {
@@ -53,13 +55,13 @@ const evaluateConditions = (conditions, operator = "AND") => {
return false;
});
- return operator === "OR" ? results.some((r) => r) : results.every((r) => r);
+ return operator === "OR" ? results.some(Boolean) : results.every(Boolean);
};
const updatePrefVisibility = (pref, document) => {
const identifier = pref.id ?? pref.property;
- const targetId = identifier.replace(/\./g, "-");
- const element = document.getElementById(targetId);
+ const targetId = identifier.replaceAll(".", "-");
+ const element = document.querySelector("#" + targetId);
if (element) {
const shouldShow = evaluateConditions(pref.conditions, pref.operator || "OR");
@@ -67,14 +69,21 @@ const updatePrefVisibility = (pref, document) => {
}
};
+/**
+ * Sets up pref observers necessary for a mod preference's conditionals to function.
+ *
+ * @param {object} pref - Mod preference that contains the conditional observers.
+ * @param {Window} window - Window that preference is loaded in.
+ * @returns {object} Observer object used in listening.
+ */
export const setupPrefObserver = (pref, window) => {
const document = window.document;
const identifier = pref.id ?? pref.property;
- const targetId = identifier.replace(/\./g, "-");
+ const targetId = identifier.replaceAll(".", "-");
// Initially hide the element
- const element = document.getElementById(targetId);
+ const element = document.querySelector("#" + targetId);
if (element) {
element.style.display = "none";
}
@@ -84,14 +93,14 @@ export const setupPrefObserver = (pref, window) => {
const collectProps = (conditions) => {
const condArray = Array.isArray(conditions) ? conditions : [conditions];
- condArray.forEach((cond) => {
+ for (const cond of condArray) {
if (cond.if || cond.not) {
const condition = cond.if || cond.not;
propsToObserve.add(condition.property);
} else if (cond.conditions) {
collectProps(cond.conditions);
}
- });
+ }
};
collectProps(pref.conditions);
@@ -100,20 +109,20 @@ export const setupPrefObserver = (pref, window) => {
const observer = {
observe: (_, topic, data) => {
if (topic === "nsPref:changed" && propsToObserve.has(data)) {
- th.updatePrefVisibility(pref, document);
+ updatePrefVisibility(pref, document);
}
},
};
// Add observers for each property
- propsToObserve.forEach((prop) => {
+ for (const prop of propsToObserve) {
Services.prefs.addObserver(prop, observer);
- });
+ }
window.addEventListener("beforeunload", () => {
- propsToObserve.forEach((prop) => {
+ for (const prop of propsToObserve) {
Services.prefs.removeObserver(prop, observer);
- });
+ }
});
// Initial visibility check
@@ -141,7 +150,7 @@ const buildPrefElement = (pref, document) => {
const foundId = pref.id || pref.property;
if (foundId) {
- prefEl.id = foundId.replace(/\./g, "-");
+ prefEl.id = foundId.replaceAll(".", "-");
}
if (pref.label) {
@@ -273,11 +282,11 @@ const applyDropdown = (pref, prefEl, ctx, manager, window) => {
`