diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ca6012..ca6b176 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,30 +2,79 @@ name: CI on: push: - branches: [ main ] pull_request: - branches: [ main ] jobs: + checks: + name: Lint & type-check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.15 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install npm dependencies + run: npm install + + - name: Install Python tools + run: pip install ruff mypy + + - name: Prettier + run: npx prettier --check "src/**/*.ts" "webviews/viewer/src/**/*.{ts,svelte}" "webviews/export/**/*.{js,css,html}" + + - name: ESLint + run: npx eslint --max-warnings=0 src/ webviews/export/ + + - name: TypeScript + run: npx tsc --noEmit + + - name: svelte-check + run: npx svelte-check --tsconfig webviews/viewer/tsconfig.json --fail-on-warnings + + - name: Ruff lint + run: python3 -m ruff check python/lsp/ python/med2obj.py + + - name: Ruff format + run: python3 -m ruff format --check python/lsp/ python/med2obj.py + + - name: mypy + run: python3 -m mypy + build: + name: Package runs-on: ubuntu-latest + needs: checks steps: - uses: actions/checkout@v4 + - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 22.15 + - name: Install Python run: sudo apt-get update && sudo apt-get install -y python3 python3-pip python3-nox python3-venv + - name: Install npm dependencies run: npm install + - name: Install vsce run: npm install -g @vscode/vsce + - name: Build and package run: python3 -m nox -s package -v --no-error-on-missing-interpreters + - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: vsix-package path: "*.vsix" - retention-days: 30 \ No newline at end of file + retention-days: 30 diff --git a/.gitignore b/.gitignore index f72f8cf..a9d2865 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Node modules node_modules/ +# Webview build output +webviews/viewer/dist/ + # Build output dist/ @@ -47,6 +50,7 @@ yarn.lock vsc-extension-quickstart.md **/__pycache__/ + # Fichiers temporaires ou backup *.tmp *.swp @@ -59,14 +63,7 @@ vsc-extension-quickstart.md *.js.map -node_modules/ -dist/ - -yarn.lock *.vsix - -# Exclude extension package -vs-code-aster-*.vsix .vscode-test out/ diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..0cd5fd7 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +npx prettier --write "src/**/*.ts" "webviews/viewer/src/**/*.{ts,svelte}" "webviews/export/**/*.{js,css,html}" +git add -u +npx eslint --max-warnings=0 src/ webviews/export/ +npx svelte-check --tsconfig webviews/viewer/tsconfig.json --fail-on-warnings +python3 -m ruff check python/lsp/ python/med2obj.py +python3 -m ruff format --check python/lsp/ python/med2obj.py diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..2e1207a --- /dev/null +++ b/.prettierignore @@ -0,0 +1,5 @@ +dist/ +node_modules/ +python/ +*.min.js +*.min.css diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..3a5ed67 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "plugins": ["prettier-plugin-svelte"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ], + "singleQuote": true, + "semi": true, + "printWidth": 100, + "tabWidth": 2, + "trailingComma": "es5" +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 3cf99c3..a1a58ed 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -7,7 +7,8 @@ "label": "watch", "dependsOn": [ "npm: watch:tsc", - "npm: watch:esbuild" + "npm: watch:esbuild", + "npm: watch:webview" ], "presentation": { "reveal": "never" @@ -17,6 +18,26 @@ "isDefault": true } }, + { + "type": "npm", + "script": "watch:webview", + "group": "build", + "isBackground": true, + "label": "npm: watch:webview", + "presentation": { + "group": "watch", + "reveal": "never" + }, + "problemMatcher": { + "owner": "vite-watch", + "pattern": { "regexp": "^$" }, + "background": { + "activeOnStart": false, + "beginsPattern": "watching for file changes", + "endsPattern": "built in \\d" + } + } + }, { "type": "npm", "script": "watch:esbuild", diff --git a/.vscodeignore b/.vscodeignore index f5e8bde..c0171a1 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -16,7 +16,14 @@ vsc-extension-quickstart.md **/.vscode-test.* .venv noxfile.py -requirements.txt +requirements.txt python/data python/lsp/.venv -python/.venv \ No newline at end of file +python/.venv +webviews/viewer/src/** +webviews/viewer/vite.config.ts +webviews/viewer/svelte.config.js +webviews/viewer/tsconfig.json +webviews/viewer/tailwind.css +webviews/viewer/styles.css +webviews/viewer/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 15ca2ba..6279e45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,25 @@ All notable changes to the **VS Code Aster** extension will be documented in thi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.5.0] - 2026-03-13 + +Rewrote the mesh viewer UI with Svelte, and added new viewer features. + +### Added +- Migrated the mesh viewer frontend from vanilla JS/HTML to Svelte with TypeScript +- Mesh viewer UI now follows the VS Code user theme +- Object file names are shown in the webview tab titles +- Focusing a `.comm` file now focuses its corresponding mesh viewer webview +- Revamped help popup with tabs and more tips +- New settings popup with various settings + - Edge rendering settings + - Object visibility settings + - UI settings +- Improved various UI components in the mesh viewer +- Show/hide toggle button per object in the sidebar +- Per-object color display +- Zoom widget in the mesh viewer + ## [1.4.3] - 2026-03-03 Updated dependencies. diff --git a/CITATION.cff b/CITATION.cff index b5fcb0f..055d550 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,4 +1,4 @@ -cff-version: 1.4.3 +cff-version: 1.5.0 title: VS Code Aster message: >- If you use this software, please cite it using the diff --git a/README.md b/README.md index 4b8d9a7..2f37a93 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -

Simvia Logo

+

Simvia Logo

- Version + Version License

@@ -253,17 +253,41 @@ git clone https://github.com/simvia-tech/vs-code-aster.git npm install ``` -3. Compile extension : +### 3. Architecture overview + +The extension consists of two independently compiled parts : + +- **Extension host** (`src/`) — TypeScript compiled with esbuild, runs in Node.js inside VS Code +- **Webview** (`webviews/viewer/`) — Svelte 5 + Vite app that powers the 3D visualizer; built separately into `webviews/viewer/dist/` + +### 4. Running the extension locally + +Press `F5` (or go to `Run > Start Debugging`) to launch a new VS Code window running the extension. + +This starts three background watch tasks automatically (defined in `.vscode/tasks.json`) : + +| Task | What it does | +|---|---| +| `npm: watch:esbuild` | Recompiles the extension host on every save | +| `npm: watch:tsc` | Type-checks the extension host continuously | +| `npm: watch:webview` | Rebuilds the Svelte webview on every save | + +After making changes to the **extension host** (`src/`), reload the debug window with `Ctrl + R`. + +After making changes to the **webview** (`webviews/viewer/src/`), wait for the `watch:webview` task to finish rebuilding, then run `Developer: Reload Webviews` from the Command Palette. + +### 5. Building manually + +To build everything from scratch without starting the debug session : ```bash +# Build the webview +npm run build:webview + +# Compile and type-check the extension host npm run compile ``` -### 3. Running the extension locally - -You can press `F5` or go to `Run > Start Debugging` to launch a new VS Code window running this extension. -After making changes, you can reload the new window using `Ctrl` + `R`. - ## Telemetry **VS Code Aster** includes optional telemetry features to help improve the tool by collecting anonymous usage data. diff --git a/ROADMAP.md b/ROADMAP.md index 76d5bc1..1c55674 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,7 +4,7 @@ The extension aims to reduce friction between modeling, validation, execution, and analysis by bringing **code_aster** native workflows into the editor. -## Current Capabilities (v1.4.3) +## Current Capabilities (v1.5.0) - `.export` file generator - 3D mesh viewer diff --git a/eslint.config.mjs b/eslint.config.mjs index d5c0b53..a1cb232 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,7 +2,7 @@ import typescriptEslint from "@typescript-eslint/eslint-plugin"; import tsParser from "@typescript-eslint/parser"; export default [{ - files: ["**/*.ts"], + files: ["**/*.ts", "webviews/export/**/*.js"], }, { plugins: { "@typescript-eslint": typescriptEslint, diff --git a/resources/icons/3d.svg b/media/icons/3d.svg similarity index 100% rename from resources/icons/3d.svg rename to media/icons/3d.svg diff --git a/media/icons/3d_light.svg b/media/icons/3d_light.svg new file mode 100644 index 0000000..0712340 --- /dev/null +++ b/media/icons/3d_light.svg @@ -0,0 +1 @@ + diff --git a/resources/images/aster.png b/media/images/aster.png similarity index 100% rename from resources/images/aster.png rename to media/images/aster.png diff --git a/resources/images/icone-code-aster.png b/media/images/icone-code-aster.png similarity index 100% rename from resources/images/icone-code-aster.png rename to media/images/icone-code-aster.png diff --git a/resources/images/simvia.png b/media/images/simvia.png similarity index 100% rename from resources/images/simvia.png rename to media/images/simvia.png diff --git a/package-lock.json b/package-lock.json index d0b048e..e69fa47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "vs-code-aster", - "version": "1.4.3", + "version": "1.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vs-code-aster", - "version": "1.4.3", + "version": "1.5.0", "license": "GPL-3.0", "dependencies": { "@tailwindcss/cli": "^4.1.17", @@ -14,6 +14,8 @@ "uuid": "^13.0.0" }, "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "@tailwindcss/vite": "^4.2.1", "@types/node": "^20.19.4", "@types/vscode": "^1.101.0", "@typescript-eslint/eslint-plugin": "^8.31.1", @@ -21,8 +23,14 @@ "@vscode/test-electron": "^2.5.2", "esbuild": "^0.25.5", "eslint": "^9.25.1", + "husky": "^9.1.7", "npm-run-all": "^4.1.5", + "prettier": "^3.8.1", + "prettier-plugin-svelte": "^3.5.1", + "svelte": "^5.53.9", + "svelte-check": "^4.4.5", "typescript": "^5.8.3", + "vite": "^7.3.1", "vscode-languageclient": "^9.0.0" }, "engines": { @@ -501,15 +509,15 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", - "minimatch": "^3.1.2" + "minimatch": "^3.1.5" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -573,9 +581,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.4.tgz", - "integrity": "sha512-4h4MVF8pmBsncB60r0wSJiIeUKTSD4m7FmTFThG8RHlsg9ajqckLm9OraguFGZE4vVdpiI1Q4+hFnisopmG6gQ==", + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", "dev": true, "license": "MIT", "dependencies": { @@ -586,7 +594,7 @@ "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", - "minimatch": "^3.1.3", + "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" }, "engines": { @@ -638,9 +646,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.3.tgz", - "integrity": "sha512-1B1VkCq6FuUNlQvlBYb+1jDu/gV297TIs/OeiaSR9l1H27SVW55ONE1e1Vp16NqP683+xEGzxYtv4XCiDPaQiw==", + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", "dev": true, "license": "MIT", "engines": { @@ -1084,149 +1092,132 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/@tailwindcss/cli": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz", - "integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==", - "license": "MIT", - "dependencies": { - "@parcel/watcher": "^2.5.1", - "@tailwindcss/node": "4.2.1", - "@tailwindcss/oxide": "4.2.1", - "enhanced-resolve": "^5.19.0", - "mri": "^1.2.0", - "picocolors": "^1.1.1", - "tailwindcss": "4.2.1" - }, - "bin": { - "tailwindcss": "dist/index.mjs" - } - }, - "node_modules/@tailwindcss/node": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", - "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.19.0", - "jiti": "^2.6.1", - "lightningcss": "1.31.1", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.2.1" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", - "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-arm64": "4.2.1", - "@tailwindcss/oxide-darwin-x64": "4.2.1", - "@tailwindcss/oxide-freebsd-x64": "4.2.1", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", - "@tailwindcss/oxide-linux-x64-musl": "4.2.1", - "@tailwindcss/oxide-wasm32-wasi": "4.2.1", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", - "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "android" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", - "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", - "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" ], - "engines": { - "node": ">= 20" - } + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", - "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", - "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", "cpu": [ "arm" ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" ], - "engines": { - "node": ">= 20" - } + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", - "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", "cpu": [ "arm64" ], + "dev": true, "libc": [ "glibc" ], @@ -1234,18 +1225,16 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", - "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", "cpu": [ "arm64" ], + "dev": true, "libc": [ "musl" ], @@ -1253,18 +1242,16 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", - "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", "cpu": [ - "x64" + "loong64" ], + "dev": true, "libc": [ "glibc" ], @@ -1272,18 +1259,16 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", - "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", "cpu": [ - "x64" + "loong64" ], + "dev": true, "libc": [ "musl" ], @@ -1291,1450 +1276,1310 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 20" - } + ] }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", - "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", "cpu": [ - "wasm32" + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" ], "license": "MIT", "optional": true, - "dependencies": { - "@emnapi/core": "^1.8.1", - "@emnapi/runtime": "^1.8.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.1", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } + "os": [ + "linux" + ] }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", - "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", "cpu": [ - "arm64" + "ppc64" + ], + "dev": true, + "libc": [ + "musl" ], "license": "MIT", "optional": true, "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } + "linux" + ] }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", - "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", "cpu": [ - "x64" + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" ], "license": "MIT", "optional": true, "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" + "linux" + ] }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], "dev": true, - "license": "MIT" + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/node": { - "version": "20.19.35", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.35.tgz", - "integrity": "sha512-Uarfe6J91b9HAUXxjvSOdiO2UPOKLm07Q1oh0JHxoZ1y8HoqxDAu3gVrsrOHeiio0kSsoVBt4wFrKOm0dKxVPQ==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/vscode": { - "version": "1.109.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.109.0.tgz", - "integrity": "sha512-0Pf95rnwEIwDbmXGC08r0B4TQhAbsHQ5UyTIgVgoieDe4cOnf92usuR5dEczb6bTKEp7ziZH4TV1TRGPPCExtw==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "MIT" + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.1.tgz", - "integrity": "sha512-Jz9ZztpB37dNC+HU2HI28Bs9QXpzCz+y/twHOwhyrIRdbuVDxSytJNDl6z/aAKlaRIwC7y8wJdkBv7FxYGgi0A==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/type-utils": "8.56.1", - "@typescript-eslint/utils": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.56.1", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@typescript-eslint/parser": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.56.1.tgz", - "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } + "optional": true, + "os": [ + "openbsd" + ] }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.56.1.tgz", - "integrity": "sha512-TAdqQTzHNNvlVFfR+hu2PDJrURiwKsUvxFn1M0h95BB8ah5jejas08jUWG4dBA68jDMI988IvtfdAI53JzEHOQ==", + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.56.1", - "@typescript-eslint/types": "^8.56.1", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } + "optional": true, + "os": [ + "openharmony" + ] }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.56.1.tgz", - "integrity": "sha512-YAi4VDKcIZp0O4tz/haYKhmIDZFEUPOreKbfdAN3SzUDMcPhJ8QI99xQXqX+HoUVq8cs85eRKnD+rne2UAnj2w==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.56.1.tgz", - "integrity": "sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.56.1.tgz", - "integrity": "sha512-yB/7dxi7MgTtGhZdaHCemf7PuwrHMenHjmzgUW1aJpO+bBU43OycnM3Wn+DdvDO/8zzA9HlhaJ0AUGuvri4oGg==", + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1", - "@typescript-eslint/utils": "8.56.1", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@typescript-eslint/types": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.56.1.tgz", - "integrity": "sha512-dbMkdIUkIkchgGDIv7KLUpa0Mda4IYjo4IAMJUZ+3xNoUXxMsk9YtKpTHSChRS85o+H9ftm51gsK1dZReY9CVw==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.56.1.tgz", - "integrity": "sha512-qzUL1qgalIvKWAf9C1HpvBjif+Vm6rcT5wZd4VoMb9+Km3iS3Cv9DY6dMRMDtPnwRAFyAi7YXJpTIEXLvdfPxg==", + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz", + "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==", "dev": true, "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.56.1", - "@typescript-eslint/tsconfig-utils": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/visitor-keys": "8.56.1", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "acorn": "^8.9.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.56.1.tgz", - "integrity": "sha512-HPAVNIME3tABJ61siYlHzSWCGtOoeP2RTIaHXFMPqjrQKCGB9OgUVdiNgH7TJS2JNIQ5qQ4RsAUDuGaGme/KOA==", + "node_modules/@sveltejs/vite-plugin-svelte": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz", + "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.56.1", - "@typescript-eslint/types": "8.56.1", - "@typescript-eslint/typescript-estree": "8.56.1" + "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", + "deepmerge": "^4.3.1", + "magic-string": "^0.30.21", + "obug": "^2.1.0", + "vitefu": "^1.1.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^20.19 || ^22.12 || >=24" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.0.0" + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.56.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.56.1.tgz", - "integrity": "sha512-KiROIzYdEV85YygXw6BI/Dx4fnBlFQu6Mq4QE4MOH9fFnhohw6wX/OAvDY2/C+ut0I3RSPKenvZJIVYqJNkhEw==", + "node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.2.tgz", + "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.56.1", - "eslint-visitor-keys": "^5.0.0" + "obug": "^2.1.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^20.19 || ^22.12 || >=24" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "peerDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", + "svelte": "^5.0.0", + "vite": "^6.3.0 || ^7.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" + "node_modules/@tailwindcss/cli": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz", + "integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==", + "license": "MIT", + "dependencies": { + "@parcel/watcher": "^2.5.1", + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "enhanced-resolve": "^5.19.0", + "mri": "^1.2.0", + "picocolors": "^1.1.1", + "tailwindcss": "4.2.1" }, - "funding": { - "url": "https://opencollective.com/eslint" + "bin": { + "tailwindcss": "dist/index.mjs" } }, - "node_modules/@vscode/test-electron": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", - "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", - "dev": true, + "node_modules/@tailwindcss/node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", "license": "MIT", "dependencies": { - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "jszip": "^3.10.1", - "ora": "^8.1.0", - "semver": "^7.6.2" - }, - "engines": { - "node": ">=16" + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.31.1", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.1" } }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-x64": "4.2.1", + "@tailwindcss/oxide-freebsd-x64": "4.2.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "cpu": [ + "arm64" + ], "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 14" + "node": ">= 20" } }, - "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "cpu": [ + "arm64" + ], "license": "MIT", - "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" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" } }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">= 20" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "cpu": [ + "x64" + ], "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">= 20" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "cpu": [ + "arm" + ], "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 20" } }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 20" } }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" + "node": ">= 20" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 20" } }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "18 || 20 || >=22" + "node": ">= 20" } }, - "node_modules/brace-expansion": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", - "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], "license": "MIT", + "optional": true, "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" }, "engines": { - "node": ">= 0.4" + "node": ">=14.0.0" } }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "cpu": [ + "arm64" + ], "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 20" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "cpu": [ + "x64" + ], "license": "MIT", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6" + "node": ">= 20" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@tailwindcss/vite": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.2.1.tgz", + "integrity": "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "tailwindcss": "4.2.1" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" } }, - "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@types/node": { + "version": "20.19.37", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.37.tgz", + "integrity": "sha512-8kzdPJ3FsNsVIurqBs7oodNnCEVbni9yUEkaHbgptDACOPW04jimGagZ51E6+lXUwJjgnBw+hyko/lkFWCldqw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "undici-types": "~6.21.0" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "dev": true, "license": "MIT" }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "node_modules/@types/vscode": { + "version": "1.110.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.110.0.tgz", + "integrity": "sha512-AGuxUEpU4F4mfuQjxPPaQVyuOMhs+VT/xRok1jiHVBubHK7lBRvCuOMZG0LKUwxncrPorJ5qq/uil3IdZBd5lA==", "dev": true, "license": "MIT" }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.57.0.tgz", + "integrity": "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/type-utils": "8.57.0", + "@typescript-eslint/utils": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": ">= 8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.57.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "node_modules/@typescript-eslint/parser": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.57.0.tgz", + "integrity": "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", + "debug": "^4.4.3" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "node_modules/@typescript-eslint/project-service": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.57.0.tgz", + "integrity": "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "@typescript-eslint/tsconfig-utils": "^8.57.0", + "@typescript-eslint/types": "^8.57.0", + "debug": "^4.4.3" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/inspect-js" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.57.0.tgz", + "integrity": "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.57.0.tgz", + "integrity": "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/@typescript-eslint/type-utils": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.57.0.tgz", + "integrity": "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0", + "@typescript-eslint/utils": "8.57.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/@typescript-eslint/types": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.57.0.tgz", + "integrity": "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg==", "dev": true, "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.57.0.tgz", + "integrity": "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "@typescript-eslint/project-service": "8.57.0", + "@typescript-eslint/tsconfig-utils": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/visitor-keys": "8.57.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "node_modules/@typescript-eslint/utils": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.57.0.tgz", + "integrity": "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ==", "dev": true, - "license": "MIT" - }, - "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.57.0", + "@typescript-eslint/types": "8.57.0", + "@typescript-eslint/typescript-estree": "8.57.0" }, "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/es-abstract": { - "version": "1.24.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", - "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.57.0.tgz", + "integrity": "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" + "@typescript-eslint/types": "8.57.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">= 0.4" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/@vscode/test-electron": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.5.2.tgz", + "integrity": "sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==", "dev": true, "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "jszip": "^3.10.1", + "ora": "^8.1.0", + "semver": "^7.6.2" + }, "engines": { - "node": ">= 0.4" + "node": ">=16" } }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">= 0.4" + "node": ">=0.4.0" } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 14" } }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" + "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" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/eslint": { - "version": "9.39.3", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.3.tgz", - "integrity": "sha512-VmQ+sifHUbI/IcSopBCF/HO3YiHQx/AVd3UVyYL6weuwW+HvON9VYn5l6Zl1WZzPWXPNZrSQpxwkkZ/VuvJZzg==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "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.3", - "@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" - }, - "bin": { - "eslint": "bin/eslint.js" + "color-convert": "^2.0.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=8" }, "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 0.4" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 4" + "node": "18 || 20 || >=22" } }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/brace-expansion": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz", + "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "balanced-match": "^4.0.2" }, "engines": { - "node": "*" + "node": "18 || 20 || >=22" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=6" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" + "dependencies": { + "readdirp": "^4.0.1" }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "engines": { + "node": ">= 14.16.0" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": ">=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "color-name": "~1.1.4" }, "engines": { - "node": ">=16" + "node": ">=7.0.0" } }, - "node_modules/flatted": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", - "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.2.7" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", + "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -2743,73 +2588,146 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz", + "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "gopd": "^1.2.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, - "license": "ISC", + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" }, "engines": { "node": ">=10.13.0" } }, - "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "is-arrayish": "^0.2.1" } }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", "dev": true, "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -2818,69 +2736,65 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -2889,1346 +2803,2690 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@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.14.0", + "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.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">= 14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 14" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">= 4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.19" + "node": ">= 4" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" + "node": "*" } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrap": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz", + "integrity": "sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "@typescript-eslint/types": "^8.2.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.1.tgz", + "integrity": "sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", + "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/husky": { + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "bin.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", + "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.6" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", "dev": true, "license": "MIT", "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.2" + "p-locate": "^5.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", + "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "chalk": "^5.3.0", + "is-unicode-supported": "^1.3.0" }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/log-symbols/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", "dev": true, "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/is-date-object": { + "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10.0" } }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" + "brace-expansion": "^5.0.2" }, "engines": { - "node": ">= 0.4" + "node": "18 || 20 || >=22" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "engines": { - "node": ">= 0.4" + "bin": { + "nanoid": "bin/nanoid.cjs" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" }, - "engines": { - "node": ">= 0.4" + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 4" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/npm-run-all/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "color-convert": "^1.9.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/npm-run-all/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/npm-run-all/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/npm-run-all/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4" } }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", + "node_modules/npm-run-all/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "node_modules/npm-run-all/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "node_modules/npm-run-all/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=4.8" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/npm-run-all/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.8.0" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/npm-run-all/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" + "engines": { + "node": ">=4" } }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "node_modules/npm-run-all/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "argparse": "^2.0.1" + "brace-expansion": "^1.1.7" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "*" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "node_modules/npm-run-all/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "node_modules/npm-run-all/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/npm-run-all/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "node_modules/npm-run-all/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", "dev": true, "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "node_modules/npm-run-all/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { - "immediate": "~3.0.5" + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/lightningcss": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", - "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", - "license": "MPL-2.0", + "node_modules/npm-run-all/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "isexe": "^2.0.0" }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.31.1", - "lightningcss-darwin-arm64": "1.31.1", - "lightningcss-darwin-x64": "1.31.1", - "lightningcss-freebsd-x64": "1.31.1", - "lightningcss-linux-arm-gnueabihf": "1.31.1", - "lightningcss-linux-arm64-gnu": "1.31.1", - "lightningcss-linux-arm64-musl": "1.31.1", - "lightningcss-linux-x64-gnu": "1.31.1", - "lightningcss-linux-x64-musl": "1.31.1", - "lightningcss-win32-arm64-msvc": "1.31.1", - "lightningcss-win32-x64-msvc": "1.31.1" + "bin": { + "which": "bin/which" } }, - "node_modules/lightningcss-android-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", - "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", - "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "node": ">= 0.4" } }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", - "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", - "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" ], + "license": "MIT" + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", - "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", - "cpu": [ - "arm" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "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" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", - "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", - "cpu": [ - "arm64" - ], - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/ora": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", + "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^5.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=18" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", - "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", - "cpu": [ - "arm64" - ], - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/ora/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 12.0.0" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", - "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", - "cpu": [ - "x64" - ], - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", - "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", - "cpu": [ - "x64" - ], - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", - "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", - "cpu": [ - "arm64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { - "node": ">= 12.0.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.31.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", - "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", - "cpu": [ - "x64" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" + "engines": { + "node": ">=6" } }, - "node_modules/load-json-file": { + "node_modules/parse-json": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { "node": ">=4" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, - "node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" + "pify": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "dev": true, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "bin": { + "pidtree": "bin/pidtree.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10" } }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "engines": { + "node": ">=4" } }, - "node_modules/math-intrinsics": { + "node_modules/possible-typed-array-names": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, "engines": { - "node": ">= 0.10.0" + "node": "^10 || ^12 || >=14" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.8.0" } }, - "node_modules/minimatch": { - "version": "10.2.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", - "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "node_modules/prettier": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", + "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.2" + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "node_modules/prettier-plugin-svelte": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.5.1.tgz", + "integrity": "sha512-65+fr5+cgIKWKiqM1Doum4uX6bY8iFCdztvvp2RcF+AJoieaw9kJOFMNcJo/bkmKYsxFaM9OsVZK/gWauG/5mg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "peerDependencies": { + "prettier": "^3.0.0", + "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, "license": "MIT" }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT" - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/npm-run-all": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", - "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "chalk": "^2.4.1", - "cross-spawn": "^6.0.5", - "memorystream": "^0.3.1", - "minimatch": "^3.0.4", - "pidtree": "^0.3.0", - "read-pkg": "^3.0.0", - "shell-quote": "^1.6.1", - "string.prototype.padend": "^3.0.0" - }, - "bin": { - "npm-run-all": "bin/npm-run-all/index.js", - "run-p": "bin/run-p/index.js", - "run-s": "bin/run-s/index.js" - }, "engines": { - "node": ">= 4" + "node": ">=6" } }, - "node_modules/npm-run-all/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" }, "engines": { "node": ">=4" } }, - "node_modules/npm-run-all/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/npm-run-all/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/npm-run-all/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, "engines": { - "node": ">=4" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "node_modules/npm-run-all/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/npm-run-all/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">=4.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/npm-run-all/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "*" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/npm-run-all/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-all/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", + "dependencies": { + "@types/estree": "1.0.8" + }, "bin": { - "semver": "bin/semver" + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/npm-run-all/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^1.0.0" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/npm-run-all/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/npm-run-all/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } + "license": "MIT" }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, "engines": { "node": ">= 0.4" }, @@ -4236,119 +5494,104 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, - "license": "MIT", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" } }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 0.4" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", "dev": true, "license": "MIT", "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" + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" } }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=8" } }, - "node_modules/ora/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=8" } }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, "engines": { "node": ">= 0.4" }, @@ -4356,236 +5599,228 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/parent-module": { + "node_modules/side-channel-map": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { - "node": ">=4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=8" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/pidtree": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", - "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } + "license": "CC0-1.0" }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "node_modules/stdin-discarder": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", + "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/possible-typed-array-names": { + "node_modules/stop-iteration-iterator": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, "engines": { "node": ">= 0.4" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "node_modules/string.prototype.padend": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", + "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", + "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4594,19 +5829,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4615,19 +5848,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4636,77 +5866,64 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, "engines": { - "node": ">=18" + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-push-apply": { + "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, "engines": { "node": ">= 0.4" }, @@ -4714,129 +5931,148 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "node_modules/svelte": { + "version": "5.53.11", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.11.tgz", + "integrity": "sha512-GYmqRjRhJYLQBonfdfGAt28gkfWEShrtXKGXcFGneXi502aBE+I1dJcs/YQriByvP6xqXRz/OdBGC6tfvUQHyQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", + "acorn": "^8.12.1", + "aria-query": "5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "devalue": "^5.6.3", + "esm-env": "^1.2.1", + "esrap": "^2.2.2", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "node_modules/svelte-check": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.5.tgz", + "integrity": "sha512-1bSwIRCvvmSHrlK52fOlZmVtUZgil43jNL/2H18pRpa+eQjzGt6e3zayxhp1S7GajPFKNM/2PMCG+DZFHlG9fw==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "chokidar": "^4.0.1", + "fdir": "^6.2.0", + "picocolors": "^1.0.0", + "sade": "^1.7.4" + }, "bin": { - "semver": "bin/semver.js" + "svelte-check": "bin/svelte-check" }, "engines": { - "node": ">=10" + "node": ">= 18.0.0" + }, + "peerDependencies": { + "svelte": "^4.0.0 || ^5.0.0-next.0", + "typescript": ">=5.0.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, + "node_modules/tailwindcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": ">= 0.4" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, + "node_modules/ts-api-utils": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", + "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true, - "license": "MIT" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/shell-quote": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", - "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, "engines": { "node": ">= 0.4" }, @@ -4844,18 +6080,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -4864,15 +6102,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -4881,37 +6123,31 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14.17" } }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -4920,481 +6156,631 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" } }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "license": "Apache-2.0", "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", "dev": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/spdx-license-ids": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", - "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], "dev": true, - "license": "CC0-1.0" + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" } }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/string.prototype.padend": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz", - "integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==", + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=18" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/tailwindcss": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", - "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "cpu": [ + "riscv64" + ], + "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "node": ">=18" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "node": ">=18" } }, - "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "node": ">=18" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 0.8.0" + "node": ">=18" } }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">= 0.4" + "node": ">=18" } }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, + "optional": true, + "os": [ + "openharmony" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=14.17" + "node": ">=18" } }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=18" } }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "node_modules/vite/node_modules/esbuild": { + "version": "0.27.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz", + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", - "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], + "hasInstallScript": true, "license": "MIT", "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" + } + }, + "node_modules/vitefu": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.2.tgz", + "integrity": "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, "node_modules/vscode-jsonrpc": { @@ -5604,6 +6990,13 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", + "dev": true, + "license": "MIT" } } } diff --git a/package.json b/package.json index dae7cf8..c9b05a0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vs-code-aster", "displayName": "VS Code Aster", - "version": "1.4.3", + "version": "1.5.0", "description": "VS Code extension for code_aster", "publisher": "simvia", "license": "GPL-3.0", @@ -28,7 +28,7 @@ "engines": { "vscode": "^1.101.0" }, - "icon": "resources/images/icone-code-aster.png", + "icon": "media/images/icone-code-aster.png", "categories": [ "Other" ], @@ -78,8 +78,8 @@ ".com9" ], "icon": { - "light": "./resources/images/icone-code-aster.png", - "dark": "./resources/images/icone-code-aster.png" + "light": "./media/images/icone-code-aster.png", + "dark": "./media/images/icone-code-aster.png" }, "configuration": "./language-configuration.json" } @@ -148,6 +148,46 @@ "default": "python3", "markdownDescription": "Specifies the python executable used to run the language server." }, + "vs-code-aster.viewer.hiddenObjectOpacity": { + "order": 10, + "type": "number", + "default": 0, + "minimum": 0, + "maximum": 0.5, + "markdownDescription": "Opacity of objects hidden via the eye button in the mesh viewer (0 = fully invisible, 0.5 = 50% visible as a ghost)." + }, + "vs-code-aster.viewer.edgeMode": { + "order": 11, + "type": "string", + "default": "threshold", + "enum": [ + "gradual", + "threshold", + "show", + "hide" + ], + "enumDescriptions": [ + "Edges fade in as you zoom in, scaled by mesh density. When zoomed out, large meshes may appear very flat as outer edges are mostly hidden. Performance is impacted.", + "Edges appear abruptly at a zoom level based on mesh density. When zoomed out, large meshes may appear slightly flat as outer edges are hidden. Performance is not impacted.", + "Edges are always visible. Large meshes will appear almost entirely black when zoomed out. Performance is impacted.", + "Edges are always hidden. All shapes will look slightly flat regardless of zoom level or mesh size." + ], + "markdownDescription": "Controls how mesh edges are displayed in the viewer." + }, + "vs-code-aster.viewer.groupTransparency": { + "order": 15, + "type": "number", + "default": 0.2, + "minimum": 0, + "maximum": 0.5, + "markdownDescription": "Opacity of the parent mesh when a sub-group is highlighted (0 = invisible, 0.5 = semi-visible)." + }, + "vs-code-aster.viewer.showOrientationWidget": { + "order": 16, + "type": "boolean", + "default": true, + "markdownDescription": "Show the orientation axes widget in the bottom-right corner of the viewer." + }, "vs-code-aster.enableTelemetry": { "order": 100, "type": "boolean", @@ -158,16 +198,21 @@ } }, "scripts": { - "vscode:prepublish": "npm run package", + "vscode:prepublish": "npm run build:webview && npm run package", "compile": "npm run check-types && npm run lint && node esbuild.js", "watch": "npm-run-all -p watch:*", "watch:esbuild": "node esbuild.js --watch", "watch:tsc": "tsc --noEmit --watch --project tsconfig.json", + "watch:webview": "vite build --config webviews/viewer/vite.config.ts --watch", + "build:webview": "vite build --config webviews/viewer/vite.config.ts", "package": "npm run check-types && npm run lint && node esbuild.js --production", "check-types": "tsc --noEmit", - "lint": "eslint src" + "lint": "eslint src", + "prepare": "husky" }, "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "@tailwindcss/vite": "^4.2.1", "@types/node": "^20.19.4", "@types/vscode": "^1.101.0", "@typescript-eslint/eslint-plugin": "^8.31.1", @@ -175,8 +220,14 @@ "@vscode/test-electron": "^2.5.2", "esbuild": "^0.25.5", "eslint": "^9.25.1", + "husky": "^9.1.7", "npm-run-all": "^4.1.5", + "prettier": "^3.8.1", + "prettier-plugin-svelte": "^3.5.1", + "svelte": "^5.53.9", + "svelte-check": "^4.4.5", "typescript": "^5.8.3", + "vite": "^7.3.1", "vscode-languageclient": "^9.0.0" }, "dependencies": { diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0825573 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,18 @@ +[tool.ruff] +line-length = 100 +target-version = "py311" + +[tool.ruff.lint] +select = ["E", "F", "I", "W", "UP"] +ignore = ["E501"] + +[tool.mypy] +python_version = "3.11" +ignore_missing_imports = true +warn_unused_ignores = true +warn_return_any = false +files = ["python/lsp"] + +[[tool.mypy.overrides]] +module = ["asterstudy.*", "code_aster.*"] +ignore_errors = true diff --git a/python/lsp/__init__.py b/python/lsp/__init__.py index 2c6df74..ea13a77 100644 --- a/python/lsp/__init__.py +++ b/python/lsp/__init__.py @@ -1,7 +1,7 @@ -import sys import pathlib as pl -asterstudy_path = pl.Path(__file__).parent.parent.absolute() +import sys + +asterstudy_path = pl.Path(__file__).parent.parent.absolute() sys.path.append(str(asterstudy_path)) code_aster_path = asterstudy_path / "asterstudy" / "code_aster_version" sys.path.append(str(code_aster_path)) - diff --git a/python/lsp/command_core.py b/python/lsp/command_core.py index b2919b1..258a542 100644 --- a/python/lsp/command_core.py +++ b/python/lsp/command_core.py @@ -1,7 +1,12 @@ +import sys + try: from asterstudy.datamodel.catalogs import CATA except ImportError as exc: - raise Exception(f"Could not import CATA from asterstudy.datamodel.catalogs. Ensure the path is correct. {sys.path} ; {exc}") + raise Exception( + f"Could not import CATA from asterstudy.datamodel.catalogs. Ensure the path is correct. {sys.path} ; {exc}" + ) + class CommandCore: """ @@ -10,6 +15,7 @@ class CommandCore: - Document registries (CommandRegistry per doc) - Langage server utilities """ + _instance = None def __new__(cls): @@ -18,7 +24,7 @@ def __new__(cls): cls._instance.CATA = CATA cls._instance.document_registries = {} return cls._instance - + # ====== Langage server ====== def store_ls(self, ls): @@ -26,32 +32,32 @@ def store_ls(self, ls): self.ls = ls def log(self, debug): - self.ls.send_notification('logParser', {'text': debug}) + self.ls.send_notification("logParser", {"text": debug}) def get_ls(self): return self.ls - + def get_doc_from_uri(self, doc_uri): return self.ls.workspace.get_document(doc_uri) - + # ====== CATA ====== def get_CATA(self): """Get the CATA object""" return self.CATA - + def get_CATA_commands(self): return self.CATA.get_commands() def get_docstring(self, command_name): - return self.CATA.get_command_definition(command_name, context = None) - + return self.CATA.get_command_definition(command_name, context=None) + def get_command_def(self, command_name): cmd_obj = self.CATA.get_command_obj(command_name) if cmd_obj: cmd_def = self.CATA.parse_command(cmd_obj) return cmd_def - + # ====== Document registries ====== def get_registry(self, doc_uri): @@ -66,5 +72,3 @@ def remove_registry(self, doc_uri): """Remove a registry for a closed/removed document""" if doc_uri in self.document_registries: del self.document_registries[doc_uri] - - diff --git a/python/lsp/command_registry.py b/python/lsp/command_registry.py index 03099fc..17611f4 100644 --- a/python/lsp/command_registry.py +++ b/python/lsp/command_registry.py @@ -4,26 +4,26 @@ """ import re -from typing import Dict, List, Optional, Tuple from dataclasses import dataclass, field @dataclass class CommandInfo: """Information about a detected command""" + name: str # Ex: "AFFE_CHAR_MECA" - var_name: Optional[str] # Ex: "CHARD" or None + var_name: str | None # Ex: "CHARD" or None start_line: int # 1-based numbering - end_line: Optional[int] # None if incomplete - end_char: Optional[int] # Position of closing parenthesis on end line + end_line: int | None # None if incomplete + end_char: int | None # Position of closing parenthesis on end line zone_end: int # End of the zone (next command or EOF) is_complete: bool - parsed_params: Dict[str, str] = field(default_factory=dict) - + parsed_params: dict[str, str] = field(default_factory=dict) + def get_key(self) -> str: """Returns the unique key of the command""" return f"{self.name}:{self.start_line}" - + def contains_line(self, line: int) -> bool: """Checks if a line belongs to this command's zone""" return self.start_line <= line <= self.zone_end @@ -33,87 +33,92 @@ class CommandRegistry: """ Command registry with incremental updates (Unique for each .comm file) """ - + def __init__(self): - self.commands: Dict[str, CommandInfo] = {} + self.commands: dict[str, CommandInfo] = {} # Sorted ranges for binary search: (start, end, cmd_key) - self.ranges: List[Tuple[int, int, Optional[str]]] = [] - - def initialize(self, ls, lines: List[str]): + self.ranges: list[tuple[int, int, str | None]] = [] + + def initialize(self, ls, lines: list[str]): """ Full registry initialization when opening the document - + Args: lines: All document lines """ self.ls = ls self.commands = {} - + # 1. Detect all commands with the existing parser raw_commands = self._parse_all_commands(lines) - + # 2. Create CommandInfo with zones for cmd_data in raw_commands: cmd_info = CommandInfo( - name=cmd_data['name'], - var_name=cmd_data['var_name'], - start_line=cmd_data['start_line'], - end_line=cmd_data['end_line'], - zone_end=cmd_data['zone_end'], - end_char=cmd_data['end_char'], - is_complete=cmd_data['is_complete'] + name=cmd_data["name"], + var_name=cmd_data["var_name"], + start_line=cmd_data["start_line"], + end_line=cmd_data["end_line"], + zone_end=cmd_data["zone_end"], + end_char=cmd_data["end_char"], + is_complete=cmd_data["is_complete"], ) - + # 3. Parse level 1 parameters cmd_info.parsed_params = self._parse_params_level1( lines, cmd_info.start_line, cmd_info.zone_end ) - + self.commands[cmd_info.get_key()] = cmd_info - + # 4. Build the range index self._rebuild_ranges() - - def on_document_change(self, lines: List[str], change_start_line: int, text_change: str) -> None: + + def on_document_change( + self, lines: list[str], change_start_line: int, text_change: str + ) -> None: """ Incremental update on a change - + Args: lines: New complete document lines change_start_line: Line where change starts (1-based) text_change: Inserted text or empty """ - + # 2. Find the affected command affected_cmd_key = self._find_command_at_line(change_start_line) - + if affected_cmd_key is None: - self.ls.send_notification('logParser', {'text': f"Change outside a command"}) + self.ls.send_notification("logParser", {"text": "Change outside a command"}) return - + # Check if we are inside the command (needs updating end_char) - self.ls.send_notification('logParser', {'text': f"Command: {affected_cmd_key}, change: {text_change}"}) + self.ls.send_notification( + "logParser", {"text": f"Command: {affected_cmd_key}, change: {text_change}"} + ) self._reparse_command(lines, affected_cmd_key) - - - def get_command_at_line(self, line: int) -> Optional[CommandInfo]: + + def get_command_at_line(self, line: int) -> CommandInfo | None: """ Returns the command that contains the given line - + Args: line: Line number (1-based) - + Returns: CommandInfo or None """ cmd_key = self._find_command_at_line(line) + if cmd_key is None: + return None return self.commands.get(cmd_key) - - def get_all_commands(self) -> Dict[str, str]: + + def get_all_commands(self) -> dict[str, str]: """ Returns a simple JSON format for compatibility - + Returns: Dict {cmdName:line: "start-end" or "start"} """ @@ -124,19 +129,23 @@ def get_all_commands(self) -> Dict[str, str]: else: result[cmd_key] = str(cmd_info.start_line) return result - + def log_command(self, cmd_info): if cmd_info.is_complete: lines = [f"For the complete command: {cmd_info.name}"] - lines.append(f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}") + lines.append( + f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}" + ) lines.append(str(cmd_info.parsed_params)) return "\n".join(lines) else: lines = [f"For the incomplete command: {cmd_info.name}"] - lines.append(f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}") + lines.append( + f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}" + ) lines.append(str(cmd_info.parsed_params)) return "\n".join(lines) - + def log_all_commands(self): """ Returns all expanded commands @@ -145,330 +154,331 @@ def log_all_commands(self): for cmd_key, cmd_info in self.commands.items(): if cmd_info.is_complete: lines.append(f"For the complete command: {cmd_info.name}") - lines.append(f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}") + lines.append( + f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}" + ) lines.append(str(cmd_info.parsed_params)) lines.append("") else: lines.append(f"For the incomplete command: {cmd_info.name}") - lines.append(f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}") + lines.append( + f"start_line: {cmd_info.start_line}, end_line: {cmd_info.end_line}, zone_end: {cmd_info.zone_end}" + ) lines.append(str(cmd_info.parsed_params)) lines.append("") return "\n".join(lines) - + def text_is_outside_command(self, position, cmd_info) -> bool: """ Indicates if the position is outside the command, only when line == cmd_info.end_line - 1 (0-based). - + True => right of closing parenthesis => outside command False => left or inside the command => inside """ # Closing parenthesis is before position.character -> we are out if hasattr(cmd_info, "end_char") and cmd_info.end_char is not None: return position.character > cmd_info.end_char - + return True - + def clean_value(self, value: str) -> str: - value = value.strip().rstrip(',') - if (value.startswith('"') and value.endswith('"')) or (value.startswith("'") and value.endswith("'")): + value = value.strip().rstrip(",") + if (value.startswith('"') and value.endswith('"')) or ( + value.startswith("'") and value.endswith("'") + ): value = value[1:-1] return value - + # ============ Private methods ============ - def _parse_all_commands(self, lines: List[str]) -> List[Dict]: + def _parse_all_commands(self, lines: list[str]) -> list[dict]: """Parse all commands in the document""" commands = [] - pattern = re.compile( - r'^\s*(?:(\w+)\s*=\s*)?(?!_F\b)([A-Z_][A-Z0-9_]*)\s*\(', - re.MULTILINE - ) - + re.compile(r"^\s*(?:(\w+)\s*=\s*)?(?!_F\b)([A-Z_][A-Z0-9_]*)\s*\(", re.MULTILINE) + i = 0 while i < len(lines): line = lines[i] - + # Skip comments if self._is_comment_line(line): i += 1 continue - + match = self._find_command_start(line) if match: start_line = i + 1 # 1-based - + # Find command end - result = self._find_command_end(lines, i, match['open_paren_pos']) - + result = self._find_command_end(lines, i, match["open_paren_pos"]) + # Calculate zone_end (adjusted later) - zone_end = result['end_line'] if result['complete'] else len(lines) - - commands.append({ - 'name': match['command'], - 'var_name': match['variable'], - 'start_line': start_line, - 'end_line': result['end_line'] if result['complete'] else None, - 'end_char': result.get('end_char'), - 'zone_end': zone_end, - 'is_complete': result['complete'] - }) - - if result['complete']: - i = result['end_line'] + zone_end = result["end_line"] if result["complete"] else len(lines) + + commands.append( + { + "name": match["command"], + "var_name": match["variable"], + "start_line": start_line, + "end_line": result["end_line"] if result["complete"] else None, + "end_char": result.get("end_char"), + "zone_end": zone_end, + "is_complete": result["complete"], + } + ) + + if result["complete"]: + i = result["end_line"] else: i += 1 else: i += 1 - + # Adjust zone_end for idx, cmd in enumerate(commands): - if cmd['is_complete'] : + if cmd["is_complete"]: continue if idx < len(commands) - 1: # Zone ends before next command - cmd['zone_end'] = commands[idx + 1]['start_line'] - 1 + cmd["zone_end"] = commands[idx + 1]["start_line"] - 1 else: # Last command: zone until the end - cmd['zone_end'] = len(lines) - + cmd["zone_end"] = len(lines) + return commands - - def _parse_params_level1(self, lines: List[str], start_line: int, - zone_end: int) -> Dict[str, str]: + + def _parse_params_level1( + self, lines: list[str], start_line: int, zone_end: int + ) -> dict[str, str]: """ Parse level 1 parameters (without entering _F) - + Args: lines: All lines start_line: Start line (1-based) zone_end: Zone end line (1-based) - + Returns: Dict {param_name: value} """ - params = {} - + params: dict[str, str] = {} + # Extract zone content - zone_lines = lines[start_line - 1:zone_end] - content = '\n'.join(zone_lines) - + zone_lines = lines[start_line - 1 : zone_end] + content = "\n".join(zone_lines) + # Find first opening parenthesis - match = re.search(r'\(', content) + match = re.search(r"\(", content) if not match: return params - + # Parse from parenthesis - content = content[match.end():] - + content = content[match.end() :] + # Regex for param=value at level 1 # Stop at comma or closing parenthesis i = 0 paren_depth = 0 current_param = None value_start = None - + while i < len(content): char = content[i] - + # Skip strings if char in ('"', "'"): quote = char i += 1 while i < len(content) and content[i] != quote: - if content[i] == '\\': + if content[i] == "\\": i += 2 else: i += 1 i += 1 continue - + # Parenthesis management - if char == '(': + if char == "(": paren_depth += 1 - elif char == ')': + elif char == ")": paren_depth -= 1 if paren_depth < 0: # End of command - save current param before exiting if current_param and value_start is not None: - value = content[value_start:i].strip().rstrip(',') + value = content[value_start:i].strip().rstrip(",") value = self.clean_value(content[value_start:i]) params[current_param] = value break - + # Detect param= if paren_depth == 0: - param_match = re.match(r'\s*(\w+)\s*=\s*', content[i:]) + param_match = re.match(r"\s*(\w+)\s*=\s*", content[i:]) if param_match: if current_param and value_start is not None: # Save previous param - value = content[value_start:i].strip().rstrip(',') + value = content[value_start:i].strip().rstrip(",") value = self.clean_value(content[value_start:i]) params[current_param] = value - + current_param = param_match.group(1) i += param_match.end() value_start = i continue - + # Detect end of value (comma at level 0) - if char == ',' and current_param and value_start is not None: + if char == "," and current_param and value_start is not None: value = content[value_start:i].strip() value = self.clean_value(content[value_start:i]) params[current_param] = value current_param = None value_start = None - + i += 1 - + # Note: Last param is NOT saved here because either: # - It was saved during break (paren_depth < 0) # - Or the command is incomplete and we do not want partial value - - # Simplify _F(...) values + + # Simplify _F(...) values for key, value in params.items(): - if value.strip().startswith('_F('): + if value.strip().startswith("_F("): params[key] = "_F(...)" - elif value.strip().startswith('(') and '_F(' in value: + elif value.strip().startswith("(") and "_F(" in value: params[key] = "(_F(...), ...)" - + return params - - def _reparse_command(self, lines: List[str], cmd_key: str): + def _reparse_command(self, lines: list[str], cmd_key: str): """Re-parse a specific command after modification""" cmd_info = self.commands[cmd_key] - + cmd_info.parsed_params = self._parse_params_level1( lines, cmd_info.start_line, cmd_info.zone_end ) - # TODO: update last character + # TODO: update last character - - def _find_command_at_line(self, line: int) -> Optional[str]: + def _find_command_at_line(self, line: int) -> str | None: """Binary search to find the command at a line""" left, right = 0, len(self.ranges) - 1 - + while left <= right: mid = (left + right) // 2 start, end, cmd_key = self.ranges[mid] - + if start <= line <= end: return cmd_key elif line < start: right = mid - 1 else: left = mid + 1 - + return None - + def _rebuild_ranges(self): """Rebuild the range index for binary search""" self.ranges = [] - + sorted_cmds = sorted(self.commands.values(), key=lambda c: c.start_line) - + current_line = 1 for cmd_info in sorted_cmds: # Add empty zone before this command if needed if current_line < cmd_info.start_line: self.ranges.append((current_line, cmd_info.start_line - 1, None)) - + # Add the command self.ranges.append((cmd_info.start_line, cmd_info.zone_end, cmd_info.get_key())) current_line = cmd_info.zone_end + 1 - + # Add final empty zone if needed - if self.ranges and self.ranges[-1][1] < float('inf'): + if self.ranges and self.ranges[-1][1] < float("inf"): # We cannot know the exact end, leave open pass - + # ============ Parsing utilities ============ def _is_comment_line(self, line: str) -> bool: stripped = line.lstrip() - return stripped.startswith('#') or stripped == '' - - def _find_command_start(self, line: str) -> Optional[Dict]: + return stripped.startswith("#") or stripped == "" + + def _find_command_start(self, line: str) -> dict | None: line_clean = self._remove_inline_comment(line) - pattern = re.compile( - r'^\s*(?:(\w+)\s*=\s*)?(?!_F\b)([A-Z_][A-Z0-9_]*)\s*\(' - ) + pattern = re.compile(r"^\s*(?:(\w+)\s*=\s*)?(?!_F\b)([A-Z_][A-Z0-9_]*)\s*\(") match = pattern.search(line_clean) if match: return { - 'variable': match.group(1), - 'command': match.group(2), - 'open_paren_pos': match.end() - 1 + "variable": match.group(1), + "command": match.group(2), + "open_paren_pos": match.end() - 1, } return None - + def _find_open_paren_pos(self, line: str) -> int: """Find the position of the opening parenthesis""" - return line.find('(') - + return line.find("(") + def _remove_inline_comment(self, line: str) -> str: in_string = False string_char = None - + for i, char in enumerate(line): if char in ('"', "'"): if not in_string: in_string = True string_char = char - elif char == string_char and (i == 0 or line[i-1] != '\\'): + elif char == string_char and (i == 0 or line[i - 1] != "\\"): in_string = False string_char = None - - if char == '#' and not in_string: + + if char == "#" and not in_string: return line[:i] - + return line - - - def _find_command_end(self, lines: List[str], start_idx: int, - start_char_pos: int) -> Dict: + def _find_command_end(self, lines: list[str], start_idx: int, start_char_pos: int) -> dict: """Find the end of a command (parser version)""" paren_count = 1 i = start_idx char_pos = start_char_pos + 1 - + while i < len(lines) and paren_count > 0: line = lines[i] line_clean = self._remove_inline_comment(line) - + # Check for new command if i > start_idx: new_cmd = self._find_command_start(line) if new_cmd is not None: - return {'end_line': i, 'complete': False} - + return {"end_line": i, "complete": False} + in_string = False string_char = None - + while char_pos < len(line_clean): char = line_clean[char_pos] - + if char in ('"', "'"): if not in_string: in_string = True string_char = char - elif char == string_char and (char_pos == 0 or line_clean[char_pos-1] != '\\'): + elif char == string_char and ( + char_pos == 0 or line_clean[char_pos - 1] != "\\" + ): in_string = False string_char = None - + if not in_string: - if char == '(': + if char == "(": paren_count += 1 - elif char == ')': + elif char == ")": paren_count -= 1 if paren_count == 0: - return {'end_line': i + 1, 'end_char': char_pos, 'complete': True} + return {"end_line": i + 1, "end_char": char_pos, "complete": True} char_pos += 1 - + i += 1 char_pos = 0 - - return {'end_line': len(lines), 'complete': False} + + return {"end_line": len(lines), "complete": False} diff --git a/python/lsp/handlers.py b/python/lsp/handlers.py index 646f32a..4da461c 100644 --- a/python/lsp/handlers.py +++ b/python/lsp/handlers.py @@ -1,39 +1,37 @@ # python/lsp/full_parsing.py from lsprotocol.types import ( - InitializeParams, - CompletionParams, CompletionList, - HoverParams, - Hover, + CompletionParams, DidChangeTextDocumentParams, + DidChangeWatchedFilesParams, DidOpenTextDocumentParams, + Hover, + HoverParams, + InitializeParams, SignatureHelp, SignatureHelpParams, - DidChangeWatchedFilesParams ) - from pygls.server import LanguageServer from lsp.managers_container import ManagerContainer + managers = ManagerContainer() + def register_handlers(server: LanguageServer): @server.feature("initialize") - def on_initialize(ls: LanguageServer, params: InitializeParams) : + def on_initialize(ls: LanguageServer, params: InitializeParams): return { "capabilities": { - "textDocumentSync": 1, - "completionProvider": { - "resolveProvider": False, - "triggerCharacters": [" ", "."] - }, + "textDocumentSync": 1, + "completionProvider": {"resolveProvider": False, "triggerCharacters": [" ", "."]}, "hoverProvider": True, - "definitionProvider": True + "definitionProvider": True, } } - + @server.feature("textDocument/didOpen") def on_document_open(ls: LanguageServer, params: DidOpenTextDocumentParams): """Initialisation du registre à l'ouverture du document""" @@ -64,14 +62,14 @@ def signature_help(ls: LanguageServer, params: SignatureHelpParams) -> Signature position = params.position return managers.signature.help(doc_uri, position) - + @server.feature("textDocument/hover") def hover(ls: LanguageServer, params: HoverParams) -> Hover: doc_uri = params.text_document.uri position = params.position return managers.hover.display(doc_uri, position) - + @server.feature("workspace/didChangeWatchedFiles") def ignore_watched_files(ls: LanguageServer, params: DidChangeWatchedFilesParams): """Handler vide pour ignorer les notifications de fichiers surveillés.""" @@ -79,14 +77,14 @@ def ignore_watched_files(ls: LanguageServer, params: DidChangeWatchedFilesParams @server.feature("codeaster/analyzeCommandFamilies") def analyze_command_families(ls, params): - if hasattr(params, 'get'): - doc_uri = params.get('uri', 'unknown') + if hasattr(params, "get"): + doc_uri = params.get("uri", "unknown") else: - doc_uri = getattr(params, 'uri', 'unknown') + doc_uri = getattr(params, "uri", "unknown") return managers.status_bar.analyze_command_families(doc_uri) - + @server.feature("codeaster/getCompleteFamilies") def getCompleteFamilies(ls, params): - - return managers.status_bar.get_complete_families() \ No newline at end of file + + return managers.status_bar.get_complete_families() diff --git a/python/lsp/managers/__init__.py b/python/lsp/managers/__init__.py index b795d20..e63a97b 100644 --- a/python/lsp/managers/__init__.py +++ b/python/lsp/managers/__init__.py @@ -1,14 +1,14 @@ # managers/__init__.py from .completion_manager import CompletionManager -from .signature_manager import SignatureManager from .hover_manager import HoverManager -from .update_manager import UpdateManager +from .signature_manager import SignatureManager from .status_bar_manager import StatusBarManager +from .update_manager import UpdateManager __all__ = [ "CompletionManager", "SignatureManager", "HoverManager", "UpdateManager", - "StatusBarManager" + "StatusBarManager", ] diff --git a/python/lsp/managers/completion_manager.py b/python/lsp/managers/completion_manager.py index 9fa19d2..053d691 100644 --- a/python/lsp/managers/completion_manager.py +++ b/python/lsp/managers/completion_manager.py @@ -1,9 +1,9 @@ +from command_core import CommandCore from lsprotocol.types import ( - CompletionList, CompletionItem, CompletionItemKind, + CompletionList, ) -from command_core import CommandCore class CompletionManager: @@ -37,18 +37,17 @@ def _suggest_commands(self) -> CompletionList: items = [] commands = self.core.get_CATA_commands() - for cmd in commands: + for cmd in commands: items.append( CompletionItem( label=cmd["name"], kind=CompletionItemKind.Function, - documentation=cmd.get("doc", "") + documentation=cmd.get("doc", ""), ) ) return CompletionList(is_incomplete=False, items=items) - def _suggest_parameters(self, cmd_info) -> CompletionList: """ Suggest parameters of a code_aster command depending on the context. @@ -65,7 +64,6 @@ def _suggest_parameters(self, cmd_info) -> CompletionList: items = [] written = set(cmd_info.parsed_params.keys()) for param in visible_params: - if param["name"] in written: continue @@ -77,7 +75,7 @@ def _suggest_parameters(self, cmd_info) -> CompletionList: CompletionItem( label=arg["name"], kind=CompletionItemKind.Property, - insert_text=arg["name"] + "=" + insert_text=arg["name"] + "=", ) ) # Normal parameter (can be a single param or a dico (_F)) @@ -89,13 +87,12 @@ def _suggest_parameters(self, cmd_info) -> CompletionList: CompletionItem( label=param["name"], kind=CompletionItemKind.Property, - insert_text=insert_text + insert_text=insert_text, ) ) return CompletionList(is_incomplete=False, items=items) - def _expand_condition_bloc(self, params, context): """ Expand conditional blocks depending on the current context. @@ -107,6 +104,6 @@ def _expand_condition_bloc(self, params, context): if arg["bloc"].isEnabled(context): for param in arg["children"]: visible_params.append(param) - else : + else: visible_params.append(arg) return visible_params diff --git a/python/lsp/managers/hover_manager.py b/python/lsp/managers/hover_manager.py index 8b43616..02668bd 100644 --- a/python/lsp/managers/hover_manager.py +++ b/python/lsp/managers/hover_manager.py @@ -2,10 +2,10 @@ HoverManager: provides hover information for code_aster commands Relies on CommandCore to get the document registry and CATA metadata """ + import re -from typing import Optional -from command_core import CommandCore +from command_core import CommandCore from lsprotocol.types import ( Hover, MarkupContent, @@ -13,7 +13,6 @@ ) - class HoverManager: """ Manager for providing hover info in a code_aster document. @@ -22,7 +21,7 @@ class HoverManager: def __init__(self): self.core = CommandCore() - def display(self, doc_uri, position) -> Optional[Hover]: + def display(self, doc_uri, position) -> Hover | None: """ Return a Hover object for the given document URI and position. """ @@ -33,16 +32,12 @@ def display(self, doc_uri, position) -> Optional[Hover]: if word: docstring = self.core.get_docstring(word) if docstring: - return Hover(contents=MarkupContent( - kind=MarkupKind.PlainText, - value=docstring - )) - + return Hover(contents=MarkupContent(kind=MarkupKind.PlainText, value=docstring)) + return None + def extract_word_at_position(self, line: str, char_pos: int) -> str: - matches = list(re.finditer(r'\b\w+\b', line)) + matches = list(re.finditer(r"\b\w+\b", line)) for match in matches: if match.start() <= char_pos <= match.end(): return match.group() return "" - - diff --git a/python/lsp/managers/signature_manager.py b/python/lsp/managers/signature_manager.py index 47655f7..52001a6 100644 --- a/python/lsp/managers/signature_manager.py +++ b/python/lsp/managers/signature_manager.py @@ -1,8 +1,8 @@ import re -from lsprotocol.types import ( - SignatureHelp, SignatureInformation -) + from command_core import CommandCore +from lsprotocol.types import SignatureHelp, SignatureInformation + class SignatureManager: """ @@ -10,7 +10,7 @@ class SignatureManager: """ def __init__(self): - self.core = CommandCore() + self.core = CommandCore() def help(self, doc_uri, position): """ @@ -18,11 +18,13 @@ def help(self, doc_uri, position): """ doc = self.core.get_doc_from_uri(doc_uri) if position.line >= len(doc.lines) or position.line < 0: - self.core.log(f"[signature_help] Position line {position.line} out of range (doc has {len(doc.lines)} lines)") + self.core.log( + f"[signature_help] Position line {position.line} out of range (doc has {len(doc.lines)} lines)" + ) return SignatureHelp(signatures=[], active_signature=0, active_parameter=0) - - line_text = doc.lines[position.line][:position.character] - + + line_text = doc.lines[position.line][: position.character] + default_signature = SignatureHelp(signatures=[], active_signature=0, active_parameter=0) # Match a command before the opening parenthesis @@ -51,12 +53,13 @@ def help(self, doc_uri, position): cmd_name = cmd_info.name cmd_def = self.core.get_command_def(cmd_name) if cmd_def: - signature = SignatureInformation(label=self.params_label(cmd_def["params"], cmd_info.parsed_params)) + signature = SignatureInformation( + label=self.params_label(cmd_def["params"], cmd_info.parsed_params) + ) self.core.log(f"Comma inside command: {cmd_name}") return SignatureHelp(signatures=[signature], active_signature=0, active_parameter=0) return default_signature - def params_label(self, command_params, current_context): """ Recursively generate a string label for the parameters of a command, @@ -72,7 +75,9 @@ def params_label(self, command_params, current_context): if param["bloc"].isEnabled(current_context): label.append(f"{self.params_label(param['children'], current_context)}") else: - label.append(f"{param['name']}: ({self.params_label(param['children'], current_context)})") + label.append( + f"{param['name']}: ({self.params_label(param['children'], current_context)})" + ) else: label.append(f"{param['name']}: {param['type']}") return ", ".join(label) diff --git a/python/lsp/managers/status_bar_manager.py b/python/lsp/managers/status_bar_manager.py index 62f1f63..5f6c641 100644 --- a/python/lsp/managers/status_bar_manager.py +++ b/python/lsp/managers/status_bar_manager.py @@ -1,9 +1,10 @@ # status_bar.py -from pathlib import Path import re -from typing import Dict, List +from pathlib import Path + from command_core import CommandCore + class StatusBarManager: """ Class that encapsulates the logic for: @@ -12,11 +13,11 @@ class StatusBarManager: """ FAMILY_MAP = { - 'Mesh': 'mesh', - 'Material': 'material', - 'BC and Load': 'bcAndLoads', - 'Analysis': 'analysis', - 'Output': 'output' + "Mesh": "mesh", + "Material": "material", + "BC and Load": "bcAndLoads", + "Analysis": "analysis", + "Output": "output", } def __init__(self): @@ -29,7 +30,7 @@ def __init__(self): self.cata = CommandCore().get_CATA() self.family_map = self.FAMILY_MAP - def analyze_command_families(self, uri: str) -> Dict[str, List[str]]: + def analyze_command_families(self, uri: str) -> dict[str, list[str]]: """ Parse a .comm file and return the commands found in each family. @@ -47,19 +48,19 @@ def analyze_command_families(self, uri: str) -> Dict[str, List[str]]: if not path.exists(): return {} - with open(path, "r", encoding="utf-8") as f: + with open(path, encoding="utf-8") as f: lines = f.readlines() content = "\n".join(lines) return self._parse_comm_file(content) - def get_complete_families(self) -> Dict[str, List[str]]: + def get_complete_families(self) -> dict[str, list[str]]: """ Return the complete list of known commands for each family. Returns: Dict[str, List[str]]: Complete commands grouped by family """ - families_result = {v: [] for v in self.family_map.values()} + families_result: dict[str, list[str]] = {v: [] for v in self.family_map.values()} for display_name, key in self.family_map.items(): try: @@ -72,7 +73,7 @@ def get_complete_families(self) -> Dict[str, List[str]]: return families_result - def _parse_comm_file(self, content: str) -> Dict[str, List[str]]: + def _parse_comm_file(self, content: str) -> dict[str, list[str]]: """ Parse the content of a .comm file and extract commands by family. @@ -82,24 +83,26 @@ def _parse_comm_file(self, content: str) -> Dict[str, List[str]]: Returns: Dict[str, List[str]]: Commands grouped by family """ - lines = content.split('\n') - code_without_comments = [re.sub(r'#.*$', '', l).strip() for l in lines if l.strip()] - full_text = ' '.join(code_without_comments) + lines = content.split("\n") + code_without_comments = [ + re.sub(r"#.*$", "", line).strip() for line in lines if line.strip() + ] + full_text = " ".join(code_without_comments) - command_pattern = r'(?:^|\s)(?:[\w]+\s*=\s*)?(?!_F\b)([A-Z][A-Z0-9_]*)\s*\(' + command_pattern = r"(?:^|\s)(?:[\w]+\s*=\s*)?(?!_F\b)([A-Z][A-Z0-9_]*)\s*\(" matches = re.finditer(command_pattern, full_text, re.VERBOSE) found_commands = set() for m in matches: cmd_name = m.group(1) - if cmd_name not in ['DEBUT', 'FIN', 'POURSUITE']: + if cmd_name not in ["DEBUT", "FIN", "POURSUITE"]: found_commands.add(cmd_name) - if re.search(r'\bDEBUT\s*\(', full_text): - found_commands.add('DEBUT') - if re.search(r'\bFIN\s*\(', full_text): - found_commands.add('FIN') + if re.search(r"\bDEBUT\s*\(", full_text): + found_commands.add("DEBUT") + if re.search(r"\bFIN\s*\(", full_text): + found_commands.add("FIN") - families_result = {v: [] for v in self.family_map.values()} + families_result: dict[str, list[str]] = {v: [] for v in self.family_map.values()} for cmd_name in found_commands: try: family_raw = self.cata.get_command_category(cmd_name) diff --git a/python/lsp/managers/update_manager.py b/python/lsp/managers/update_manager.py index 7b5c6a8..68ba199 100644 --- a/python/lsp/managers/update_manager.py +++ b/python/lsp/managers/update_manager.py @@ -1,6 +1,7 @@ from command_core import CommandCore from command_registry import CommandRegistry + class UpdateManager: """ Manager for handling document open and change events for .comm files. @@ -36,13 +37,13 @@ def update_registry(self, doc, doc_uri, changes): self.core.set_registry(doc_uri, registry) for change in changes: - if hasattr(change, 'range') and change.range: + if hasattr(change, "range") and change.range: start_line = change.range.start.line + 1 end_line = change.range.end.line + 1 text = change.text # Handle multi-line deletions or additions - if end_line - start_line > 0 or text.count('\n') > 0 or text == '(': + if end_line - start_line > 0 or text.count("\n") > 0 or text == "(": self.core.log("on reload entierement") registry.initialize(ls, doc.lines) continue diff --git a/python/lsp/managers_container.py b/python/lsp/managers_container.py index 25e98f9..5584df7 100644 --- a/python/lsp/managers_container.py +++ b/python/lsp/managers_container.py @@ -1,13 +1,21 @@ -from managers import StatusBarManager, HoverManager, UpdateManager, SignatureManager, CompletionManager +from managers import ( + CompletionManager, + HoverManager, + SignatureManager, + StatusBarManager, + UpdateManager, +) + class ManagerContainer: """ Central container for all feature classes. Initialize all managers """ + def __init__(self): self.status_bar = StatusBarManager() self.hover = HoverManager() self.update = UpdateManager() self.signature = SignatureManager() - self.completion = CompletionManager() \ No newline at end of file + self.completion = CompletionManager() diff --git a/python/lsp/server.py b/python/lsp/server.py index fa8e9e1..925359f 100644 --- a/python/lsp/server.py +++ b/python/lsp/server.py @@ -1,26 +1,27 @@ -import pathlib as pl +# ruff: noqa: I001 — import order is intentional: lsp.handlers must precede command_core to trigger sys.path setup in lsp/__init__.py +import pathlib as pl import sys -### bundled libraries -bundled_path = pl.Path(__file__).parent.parent.absolute() / "bundled" / "libs" +### bundled libraries +bundled_path = pl.Path(__file__).parent.parent.absolute() / "bundled" / "libs" ## preprend the path to include bundled libraries #### Becareful, we prepend the path to ensure that bundled libraries are found first in place of system libraries sys.path.insert(0, str(bundled_path)) +from pygls.server import LanguageServer # noqa: E402 +from lsp.handlers import register_handlers # noqa: E402 - -from pygls.server import LanguageServer -from lsp.handlers import register_handlers - -from command_core import CommandCore +from command_core import CommandCore # noqa: E402 ls = LanguageServer(name="aster-lsp", version="0.1.0") + def main(): CommandCore().store_ls(ls) register_handlers(ls) ls.start_io() + if __name__ == "__main__": main() diff --git a/python/med2obj.py b/python/med2obj.py index 37e57f9..264d459 100644 --- a/python/med2obj.py +++ b/python/med2obj.py @@ -5,20 +5,17 @@ import argparse -import medcoupling as mc import pathlib as pl +import medcoupling as mc + def parse_args(): parser = argparse.ArgumentParser( description="Convert a .med mesh file to a .obj file with groups." ) - parser.add_argument( - "-i", "--input", type=str, required=True, help="Input .med file path." - ) - parser.add_argument( - "-o", "--output", type=str, required=True, help="Output .obj file path." - ) + parser.add_argument("-i", "--input", type=str, required=True, help="Input .med file path.") + parser.add_argument("-o", "--output", type=str, required=True, help="Output .obj file path.") return parser.parse_args() @@ -54,7 +51,7 @@ def write_obj( for elem in skin_mesh: conn = elem.getAllConn() # OBJ is 1-indexed end_connectivity = END_CONNECTIVITY[len(conn) - 1] + 1 - f.write(f'f {" ".join([str(x+1) for x in conn[1:end_connectivity]])}\n') + f.write(f"f {' '.join([str(x + 1) for x in conn[1:end_connectivity]])}\n") for group_name in skin_groups: submesh = med_file.getGroup(skin_level, group_name) @@ -62,7 +59,7 @@ def write_obj( for elem in submesh: conn = elem.getAllConn() end_connectivity = END_CONNECTIVITY[len(conn) - 1] + 1 - f.write(f'f {" ".join([str(x+1) for x in conn[1:end_connectivity]])}\n') + f.write(f"f {' '.join([str(x + 1) for x in conn[1:end_connectivity]])}\n") for group_name in node_groups: node_ids = med_file.getGroupArr(node_level, group_name).toNumPyArray() diff --git a/resources/export_form/export.css b/resources/export_form/export.css deleted file mode 100644 index 99f7e8d..0000000 --- a/resources/export_form/export.css +++ /dev/null @@ -1,157 +0,0 @@ -body { - margin: 32px auto; - max-width: 600px; - font-family: "Segoe UI", "Roboto", Arial, sans-serif; - color: #222; - background: linear-gradient(135deg, #f6fafd 0%, #e9f0f7 100%); - box-shadow: 0 4px 24px rgba(0,0,0,0.06); - border-radius: 12px; - padding: 32px 40px 40px 40px; -} - -h2, h3 { - color: #174a6e; - margin-bottom: 0.5em; - letter-spacing: 0.01em; -} - -h3 { - font-size: 1.1em; - font-weight: 600; - margin-top: 1.5em; -} - -div.field { - margin-top: 1em; - margin-bottom: 1em; - clear: both; - padding: 0.7em 0.5em; - display: flex; - align-items: center; - background: rgba(255,255,255,0.8); - border-radius: 6px; - box-shadow: 0 1px 2px rgba(0,0,0,0.02); - transition: background 0.2s; -} - -div.label { - width: 10em; - margin-right: 1em; - font-weight: 600; - color: #246; - letter-spacing: 0.01em; -} - -div.field select, -div.field input { - flex: 1; - min-width: 0; - padding: 0.5em 0.8em; - border: 1px solid #bcd2e6; - border-radius: 4px; - font-size: 1em; - background-color: #fafdff; - transition: border 0.2s, box-shadow 0.2s; - box-shadow: 0 1px 2px rgba(0,0,0,0.03); -} - -div.field input { - width: 100%; -} - -div.file-row > * { - margin-right: 12px; -} - -div.file-row > *:last-child { - margin-right: 0; -} - -div.field select:focus, -div.field input:focus { - border-color: #007acc; - box-shadow: 0 0 0 2px #b3e1ff; - outline: none; - background: #f2faff; -} - -div.submit { - margin-top: 2.5em; - clear: both; - text-align: right; -} - -div.submit button { - margin-left: 0.5em; - padding: 0.6em 1.4em; - font-size: 1.08em; - border: none; - border-radius: 5px; - cursor: pointer; - background: linear-gradient(90deg, #007acc 70%, #005f99 100%); - color: white; - font-weight: 600; - letter-spacing: 0.02em; - box-shadow: 0 2px 8px rgba(0,122,204,0.07); - transition: background 0.2s, transform 0.1s; -} - -div.submit button:hover, -div.submit button:focus { - background: linear-gradient(90deg, #005f99 60%, #007acc 100%); - transform: translateY(-1px) scale(1.04); -} - -div.suggestion-box { - position: absolute; - left: 0; - min-width: 100%; - background: #fff; - border: 1px solid #bcd2e6; - border-radius: 4px; - box-shadow: 0 2px 8px rgba(0,0,0,0.09); - z-index: 10; -} - -div.highlighted-suggestion { - background-color: #e0f0ff; - font-weight: bold; - border-left: 3px solid #007acc; -} - -div.field input.input-warning { - border: 1.5px solid #d45858 !important; - background-color: #faecec !important; -} - -div.logo-container { - position: absolute; - top: 34px; - right: 36px; - display: flex; - gap: 18px; - align-items: center; - z-index: 10; - max-width: 220px; - max-height: 60px; - overflow: hidden; -} - -img.logo-img { - max-height: 54px; - max-width: 90px; - height: auto; - width: auto; - object-fit: contain; - display: block; - filter: drop-shadow(0 2px 8px rgba(0,0,0,0.07)); - transition: filter 0.2s; -} - -img.logo-img:hover { - filter: drop-shadow(0 4px 12px #007acc33); -} - -#submitCreate { - font-weight: bold; -} diff --git a/resources/export_form/export.html b/resources/export_form/export.html deleted file mode 100644 index 751fec9..0000000 --- a/resources/export_form/export.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - Export File Creation - - - - - - - - - -
- Logo 1 - Logo 2 -
- -

Export File Creation

- -
-
File name:
- -
- -
-
Time Limit:
- -
-
- -
-
Memory Limit:
- -
-
- -
-
NCPUs:
- -
-
- -
-
MPI NBCPU:
- -
-
- -
-
MPI NBNOEUD:
- -
-
- - - -

For each file, fill in the format, name, and unite value.

- -

- Input Files - - -

- -
- -

- -

- Output Files - - -

- -
- -

- -
- - -
- - - - - - diff --git a/resources/icons/clear.svg b/resources/icons/clear.svg deleted file mode 100644 index 9d38780..0000000 --- a/resources/icons/clear.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/face.svg b/resources/icons/face.svg deleted file mode 100644 index 7aa8e1e..0000000 --- a/resources/icons/face.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/filter.svg b/resources/icons/filter.svg deleted file mode 100644 index 3daaa2b..0000000 --- a/resources/icons/filter.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/node.svg b/resources/icons/node.svg deleted file mode 100644 index c147a75..0000000 --- a/resources/icons/node.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/object.svg b/resources/icons/object.svg deleted file mode 100644 index 24bee7e..0000000 --- a/resources/icons/object.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/icons/question_mark.svg b/resources/icons/question_mark.svg deleted file mode 100644 index 02a8a6a..0000000 --- a/resources/icons/question_mark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/resources/visu_vtk/index.html b/resources/visu_vtk/index.html deleted file mode 100644 index 4e057b5..0000000 --- a/resources/visu_vtk/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - MeshViewer - - - - -
- -
- - -
-
- - -
-
- - -
-
- - -
- - -
- - - -
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/resources/visu_vtk/index.js b/resources/visu_vtk/index.js deleted file mode 100644 index 254703a..0000000 --- a/resources/visu_vtk/index.js +++ /dev/null @@ -1,24 +0,0 @@ -// Entry point for the VS Code Webview -const vscode = acquireVsCodeApi(); // VS Code API for messaging with the extension -const scene = document.getElementById("scene"); // HTML scene for rendering -Controller.Instance.init(scene, vscode); // Initialize the main Controller with scene and VS Code API - -// Listen for messages from the extension -window.addEventListener("message", async (e) => { - const { type, body } = e.data; - - switch (type) { - // Initialize the visualization with loaded OBJ files - case "init": - Controller.Instance.loadFiles(body.fileContexts, body.objFilenames); - break; - - // Toggle visibility for a specific group and update the UI label - case "displayGroup": - VisibilityManager.Instance.setVisibility(body.group, body.visible); - break; - } -}); - -// Notify the extension that the webview is ready -vscode.postMessage({ type: "ready" }); diff --git a/resources/visu_vtk/js/Controller.js b/resources/visu_vtk/js/Controller.js deleted file mode 100644 index f729690..0000000 --- a/resources/visu_vtk/js/Controller.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Controller for managing rendering operations and group visibility in the visualization module. - */ -class Controller { - static get Instance() { - if (!this._i) { - this._i = new Controller(); - } - return this._i; - } - - /** - * Initializes the render controller with the given scene and VS Code API entry. - * @param {HTMLElement} scene - The HTML scene for 3D rendering. - * @param {any} vsCodeApiEntry - The VS Code API entry point. - */ - init(scene, vsCodeApiEntry) { - this._scene = scene; - this._vsCodeApi = vsCodeApiEntry; - VtkApp.Instance.init(scene); - } - - getScene() { - return this._scene; - } - - getVSCodeAPI() { - return this._vsCodeApi; - } - - /** - * Loads a file and updates the group list in the VS Code webview. - * @param {string[]} fileContexts - The contexts of the files to load. - * @param {string[]} fileNames - The names of the files to load. - */ - loadFiles(fileContexts, fileNames) { - const lfr = new CreateGroups(fileContexts, fileNames); - lfr.do(); - this.initManagers(); - this.getVSCodeAPI().postMessage({ - type: "groups", - groupList: this.getGroupNames(), - }); - } - - saveGroups(groups, groupHierarchy) { - this._groups = groups; - this._groupHierarchy = groupHierarchy; - Controller.Instance.getVSCodeAPI().postMessage({ - type: "debugPanel", - text: `Actors and hierarchy saved`, - }); - } - - initManagers() { - UIManager.Instance.init(this._groupHierarchy); - VisibilityManager.Instance.init(this._groups, this._groupHierarchy); - CameraManager.Instance.init(this._groups); - } - - getGroupNames() { - if (!this._groups) { - return []; - } - return Object.keys(this._groups).filter((key) => !key.includes("all_")); - } -} diff --git a/resources/visu_vtk/js/commands/VisibilityManager.js b/resources/visu_vtk/js/commands/VisibilityManager.js deleted file mode 100644 index 5f5b834..0000000 --- a/resources/visu_vtk/js/commands/VisibilityManager.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * Manages visibility of groups in the visualization module. - */ -class VisibilityManager { - /** - * Manage a singleton instance - */ - static get Instance() { - if (!this._i) { - this._i = new VisibilityManager(); - } - return this._i; - } - - /** - * Initializes the manager with groups and their hierarchy. - * @param {Map } groups A map of group names to group objects. - * @param {Map } objects A map of objects with their corresponding face and node groups. - */ - init(groups, objects) { - this.groups = groups; - this.visibleGroupsByObject = {}; - - for (const object in objects) { - this.visibleGroupsByObject[object] = 0; - } - } - - /** - * Sets visibility for a given group and updates associated object transparency. - * @param {string} groupName Name of the group to modify. - * @param {boolean} visible Optional visibility state; toggles if omitted. - * @returns {Object} Current visibility info: {visible, color, isFaceGroup} - */ - setVisibility(groupName, visible) { - // Helper function to send messages to the backend - const post = (text) => { - Controller.Instance.getVSCodeAPI().postMessage({ - type: "debugPanel", - text, - }); - }; - - // Handle errors - const group = this.groups[groupName]; - if (!group) { - post(`setVisibility: group "${groupName}" has no group defined`); - return; - } - const object = group.fileGroup; - if (!object) { - post(`setVisibility: group "${groupName}" has no parent object`); - return; - } - const actor = group.actor; - if (!actor) { - post(`setVisibility: no actor found for group "${groupName}"`); - return; - } - - // Get data about the group - const color = group.getColor(); - const isFaceGroup = group.isFaceGroup; - - // Store the previous visibility state before changing it - const wasVisible = actor.getVisibility(); - - if (typeof visible === "boolean") { - // If 'visible' is set, set the new visibility accordingly - actor.setVisibility(visible); - } else { - // Else, toggle visibility - actor.setVisibility(!actor.getVisibility()); - } - - // Make the whole object transparent (except from the selected groups) if at least one group is selected - // Or make it opaque if no groups are selected - const isVisible = actor.getVisibility(); - - // Only update the counter if visibility actually changed - if (wasVisible !== isVisible) { - const visibleGroupsCount = this.visibleGroupsByObject[object]; - if ( - (visibleGroupsCount === 0 && isVisible) || - (visibleGroupsCount === 1 && !isVisible) - ) { - this.setTransparence(isVisible, object); - } - this.visibleGroupsByObject[object] += isVisible ? 1 : -1; - } - - // Change group button highlight status - if (isVisible) { - UIManager.Instance.highlightButton(groupName, color); - } else { - UIManager.Instance.highlightButton(groupName); - } - - // Re-render the VTK window - VtkApp.Instance.getRenderWindow().render(); - - return { visible: isVisible, color, isFaceGroup }; // Unused, is this really necessary ? - } - - /** - * Sets the opacity of an object. - * @param {boolean} transparent Whether the object should be partially transparent or opaque. - * @param {string} object Name of the object. - */ - setTransparence(transparent, object) { - if (!this.groups) { - return; - } - const meshOpacity = transparent ? 0.2 : 1; - const group = this.groups[object]; - group.setOpacity(meshOpacity); - } - - /** - * Resets visibility and transparency for all groups. - */ - clear() { - /** - * Parse all groups and set their visibility to false (meaning they are not highlighted) - */ - for (const [groupName, group] of Object.entries(this.groups)) { - if (!group.actor) { - continue; - } - if (group.fileGroup === null) { - continue; - } - group.setVisibility(false); - - // Change group button highlight status - UIManager.Instance.highlightButton(groupName); - } - - // Make all objects opaque - for (const object in this.visibleGroupsByObject) { - this.setTransparence(false, object); - this.visibleGroupsByObject[object] = 0; - } - - // Re-render - VtkApp.Instance.getRenderWindow().render(); - } -} diff --git a/resources/visu_vtk/js/core/VtkApp.js b/resources/visu_vtk/js/core/VtkApp.js deleted file mode 100644 index b9a97db..0000000 --- a/resources/visu_vtk/js/core/VtkApp.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Singleton managing the VTK rendering context. - * Handles the creation of renderer and render window for the visualization panel. - */ -class VtkApp { - - static get Instance() { - if (!this._i) { - this._i = new VtkApp(); - } - return this._i; - } - - /** - * Initializes the full-screen renderer in the given HTML scene - * @param {HTMLElement} scene - The HTML element to attach the renderer - */ - init(scene) { - if (!window.vtk) {return;} - - this.fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance({ - rootContainer: scene, - background: [0.4, 0.6, 1.0], - }); - - this.renderer = this.fullScreenRenderer.getRenderer(); - this.renderWindow = this.fullScreenRenderer.getRenderWindow(); - - Controller.Instance.getVSCodeAPI().postMessage({ - type: 'debugPanel', - text: 'vtkAppInitialized' - }); - } - - /** @returns {vtkRenderer} The VTK renderer */ - getRenderer() { - return this.renderer; - } - - /** @returns {vtkRenderWindow} The VTK render window */ - getRenderWindow() { - return this.renderWindow; - } -} diff --git a/resources/visu_vtk/js/data/CreateGroups.js b/resources/visu_vtk/js/data/CreateGroups.js deleted file mode 100644 index 3fa5556..0000000 --- a/resources/visu_vtk/js/data/CreateGroups.js +++ /dev/null @@ -1,96 +0,0 @@ -class CreateGroups { - /** - * Creates a CreateGroups. - * @param {string[]} fileContext The contexts of the files to load. - * @param {string[]} fileName The names of the files to load. - */ - constructor(fileContexts, fileNames) { - this.fileContexts = fileContexts; - this.fileNames = fileNames; - this.groups = {}; - } - - /** - * Loads the files, creates Actors instances - * @method - */ - do() { - - const result = ObjLoader.loadFiles(this.fileContexts, this.fileNames); - const post = (text) => { - Controller.Instance.getVSCodeAPI().postMessage({ - type: 'debugPanel', - text, - }); - }; - - if (!result) { - return; - } - - const { - vertices, - cells, - cellIndexToGroup, - nodes, - nodeIndexToGroup, - faceGroups, - nodeGroups, - groupHierarchy - } = result; - - const FaceActorCreato = new FaceActorCreator(vertices, cells, cellIndexToGroup); - const NodeActorCreato = new NodeActorCreator(vertices, nodes, nodeIndexToGroup); - - for (const fileGroup in groupHierarchy) { - const groupId = faceGroups.indexOf(fileGroup); - - const actor = FaceActorCreato.create(fileGroup, groupId); - - const groupInstance = new Group(actor, fileGroup, true); - - this.groups[fileGroup] = groupInstance; - - const size = this.computeSize(actor); - - for (const faceGroup of groupHierarchy[fileGroup].faces) { - const groupId = faceGroups.indexOf(faceGroup); - - const actor = FaceActorCreato.create(faceGroup, groupId); - - const subGroup = new Group(actor, faceGroup, true, fileGroup, size); - this.groups[`${fileGroup}::${faceGroup}`] = subGroup; - } - - for (const nodeGroup of groupHierarchy[fileGroup].nodes) { - const groupId = nodeGroups.indexOf(nodeGroup); - - const actor = NodeActorCreato.create(groupId); - - const subGroup = new Group(actor, nodeGroup, false, fileGroup, size); - this.groups[`${fileGroup}::${nodeGroup}`] = subGroup; - } - } - - //Reset the camera after Actors creation - VtkApp.Instance.getRenderer().resetCamera(); - VtkApp.Instance.getRenderWindow().render(); - post(`actors : ${Object.keys(this.groups).length}`); - - //Send groups to the controller - Controller.Instance.saveGroups(this.groups, groupHierarchy); - } - - computeSize(actor) { - const bounds = actor.getBounds(); - - const dx = bounds[1] - bounds[0]; - const dy = bounds[3] - bounds[2]; - const dz = bounds[5] - bounds[4]; - - const size = Math.sqrt(dx*dx + dy*dy + dz*dz); - - return Math.max(size, 1e-3); - } - -} \ No newline at end of file diff --git a/resources/visu_vtk/js/data/Group.js b/resources/visu_vtk/js/data/Group.js deleted file mode 100644 index 9aa424c..0000000 --- a/resources/visu_vtk/js/data/Group.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Represents a group in the visualization module. - * Can be a fileGroup or a sub-group of faces/nodes. - */ -class Group { - /** - * @param {vtkActor} actor - The VTK actor associated with the group - * @param {string} name - Name of the group (fileGroup or sub-group) - * @param {boolean} isFaceGroup - True for face group, false for nodal - * @param {string|null} fileGroup - Parent fileGroup name (null if this is a fileGroup) - * @param {number|null} parentSize - Size of the parent fileGroup (null if this is a fileGroup) - */ - constructor(actor, name, isFaceGroup, fileGroup = null, parentSize = null) { - this.actor = actor; - this.name = name; - this.isFaceGroup = isFaceGroup; - this.fileGroup = fileGroup; - this.size = parentSize; - } - - /** - * Sets the visual point size of the actor based on distance. - * @param {number} distance - Distance used to compute scaling - */ - setSize(distance) { - const decay = this.size / 5; - const scale = Math.max(30 * (1 / Math.sqrt(1 + distance / decay)), 0); - this.actor.getProperty().setPointSize(scale); - } - - getColor() { - return this.actor.getProperty().getColor(); - } - - setVisibility(visible) { - this.actor.setVisibility(visible); - } - - setOpacity(opacity) { - this.actor.getProperty().setOpacity(opacity); - } -} diff --git a/resources/visu_vtk/js/data/ObjLoader.js b/resources/visu_vtk/js/data/ObjLoader.js deleted file mode 100644 index 624fffe..0000000 --- a/resources/visu_vtk/js/data/ObjLoader.js +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Loads OBJ-like file contents and constructs geometry data structures. - * Handles vertices, faces, nodes, face groups, node groups, and group hierarchy. - */ -class ObjLoader { - - /** - * Parses file contents and returns structured geometry info. - * @param {string[]} fileContexts - Array of file contents (one string per file) - * @param {string[]} fileNames - Corresponding names of the files - * @returns {Object} - Geometry data including vertices, cells, nodes, and group mappings - */ - static loadFiles(fileContexts, fileNames) { - - const vertices = [], - cells = [], - cellIndexToGroup = [], - nodes = [], - nodeIndexToGroup = [], - faceGroups = [], - nodeGroups = [], - groupHierarchy = {}; - - let nbVertices = 0; - let groupId = -1; - let nodeGroupId = -1; - - for (let i = 0; i < fileContexts.length; i++) { - try { - groupId++; - const skinName = "all_" + fileNames[i]; - - groupHierarchy[skinName] = { faces: [], nodes: [] }; - faceGroups.push(skinName); - nbVertices = vertices.length; - - // Split lines and normalize line endings - const lines = fileContexts[i].split('\n').map(l => l.replace('\r', '')); - - let vertexCount = 0; - let faceCount = 0; - - for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) { - const line = lines[lineIdx]; - const ss = line.split(' ').filter(p => p.length !== 0); - if (ss.length === 0) { continue; } - - switch (ss[0]) { - case 'v': // Vertex definition - vertices.push({ - x: Number.parseFloat(ss[1]), - y: Number.parseFloat(ss[2]), - z: Number.parseFloat(ss[3]) - }); - vertexCount++; - break; - - case 'f': // Face definition - const faceIndices = ss.slice(1).map(p => Number.parseInt(p) - 1 + nbVertices); - cells.push(faceIndices); - cellIndexToGroup.push(groupId); - faceCount++; - break; - - case 'g': // New face group - groupId++; - const faceGroupName = ss[1] || `group${groupId}`; - faceGroups.push(faceGroupName); - groupHierarchy[skinName].faces.push(faceGroupName); - break; - - case 'ng': // New node group - nodeGroupId++; - const nodeGroupName = ss[1] || `nodeGroup${nodeGroupId}`; - nodeGroups.push(nodeGroupName); - groupHierarchy[skinName].nodes.push(nodeGroupName); - break; - - case 'p': // Node assignment - const nodeIndex = parseInt(ss[1]); - nodes.push(nodeIndex - 1 + nbVertices); - nodeIndexToGroup.push(nodeGroupId); - break; - } - } - - } catch (fileError) { - Controller.Instance.getVSCodeAPI().postMessage({ - type: 'debugPanel', - text: `ERROR: ${fileError.message}` - }); - throw fileError; - } - } - - Controller.Instance.getVSCodeAPI().postMessage({ - type: 'debugPanel', - text: `TOTAL: ${vertices.length} vertices, ${cells.length} cells, ${nodes.length} nodes` - }); - - return { - vertices, - cells, - cellIndexToGroup, - nodes, - nodeIndexToGroup, - faceGroups, - nodeGroups, - groupHierarchy - }; - } -} diff --git a/resources/visu_vtk/js/data/create/FaceActorCreator.js b/resources/visu_vtk/js/data/create/FaceActorCreator.js deleted file mode 100644 index 762d8fd..0000000 --- a/resources/visu_vtk/js/data/create/FaceActorCreator.js +++ /dev/null @@ -1,94 +0,0 @@ -class FaceActorCreator { - /** - * Create a FaceActorCreator. - * @param {Vector[]} vertices - List of vertex coordinates - * @param {number[][]} cells - Connectivity list - * @param {number[]} cellIndexToGroup - Cell-to-group index mapping - */ - constructor(vertices, cells, cellIndexToGroup) { - this.vertices = vertices; - this.cells = cells; - this.cellIndexToGroup = cellIndexToGroup; - } - - /** - * Creates and configures an actor for a face group. - * @param {string} groupName - * @param {number} groupId - * @returns {vtkActor} - */ - create(groupName, groupId) { - const polyData = this.prepare(groupId); - - const actor = vtk.Rendering.Core.vtkActor.newInstance(); - const mapper = vtk.Rendering.Core.vtkMapper.newInstance(); - - mapper.setInputData(polyData); - actor.setMapper(mapper); - - this.setProperty(actor, groupName); - VtkApp.Instance.getRenderer().addActor(actor); - - return actor; - } - - - /** - * Prepares vtkPolyData for a given groupId using instance data. - * @param {number} groupId - * @returns {vtkPolyData} - */ - prepare(groupId) { - const pd = vtk.Common.DataModel.vtkPolyData.newInstance(); - - const pts = vtk.Common.Core.vtkPoints.newInstance(); - const coords = new Float32Array(this.vertices.length * 3); - this.vertices.forEach((v, i) => { - coords[3 * i] = v.x; - coords[3 * i + 1] = v.y; - coords[3 * i + 2] = v.z; - }); - pts.setData(coords, 3); - pd.setPoints(pts); - - const cellIndices = this.cellIndexToGroup - .map((g, idx) => (g === groupId ? idx : -1)) - .filter(idx => idx !== -1); - - if (cellIndices.length > 0) { - const cellArray = vtk.Common.Core.vtkCellArray.newInstance({ - values: Uint32Array.from(cellIndices.flatMap(i => { - const c = this.cells[i]; - return [c.length, ...c]; - })) - }); - pd.setPolys(cellArray); - } - - return pd; - } - - /** - * Configures rendering properties (color, opacity, visibility) - * @param {vtkActor} actor - * @param {string} groupName - */ - setProperty(actor, groupName) { - const prop = actor.getProperty(); - - if (groupName.includes("all_")) { - prop.setColor(GlobalSettings.Instance.surfaceOutsideColor); - } else { - prop.setColor(GlobalSettings.Instance.getColorForGroup()); - prop.setOpacity(0.8); - actor.setVisibility(false); - } - - prop.setEdgeVisibility(true); - prop.setLineWidth(0.3); - prop.setInterpolationToPhong(); - prop.setSpecular(0.3); - prop.setSpecularPower(15); - } - -} diff --git a/resources/visu_vtk/js/data/create/NodeActorCreator.js b/resources/visu_vtk/js/data/create/NodeActorCreator.js deleted file mode 100644 index 380f257..0000000 --- a/resources/visu_vtk/js/data/create/NodeActorCreator.js +++ /dev/null @@ -1,89 +0,0 @@ -class NodeActorCreator { - /** - * @param {Vector[]} vertices - List of vertex coordinates - * @param {number[][]} nodes - - * @param {number[]} nodeIndexToGroup - Node-to-group index mapping - */ - constructor(vertices, nodes, nodeIndexToGroup) { - this.vertices = vertices; - this.nodes = nodes; - this.nodeIndexToGroup = nodeIndexToGroup; - } - - /** - * Creates and configures an actor for a face group. - * @param {number} groupId - * @returns {vtkActor} - */ - create(groupId) { - - const polyData = this.prepare(groupId); - - const mapper = vtk.Rendering.Core.vtkMapper.newInstance(); - mapper.setInputData(polyData); - - const actor = vtk.Rendering.Core.vtkActor.newInstance(); - actor.setMapper(mapper); - - this.setProperty(actor); - VtkApp.Instance.getRenderer().addActor(actor); - - return actor; - } - - /** - * Prepares vtkPolyData for a given groupId using instance data. - * @param {number} groupId - * @returns {vtkPolyData} - */ -prepare(groupId) { - const pd = vtk.Common.DataModel.vtkPolyData.newInstance(); - - const nodeIndices = this.nodeIndexToGroup - .map((g, idx) => (g === groupId ? idx : -1)) - .filter(idx => idx !== -1); - - if (nodeIndices.length > 0) { - const pts = vtk.Common.Core.vtkPoints.newInstance(); - const data = []; - - for (const idx of nodeIndices) { - const v = this.vertices[this.nodes[idx]]; - if (v) { - data.push(v.x, v.y, v.z); - } - } - - pts.setData(Float32Array.from(data), 3); - pd.setPoints(pts); - - const numPoints = data.length / 3; - const verts = vtk.Common.Core.vtkCellArray.newInstance(); - const vertData = []; - - for (let i = 0; i < numPoints; i++) { - vertData.push(1, i); - } - - verts.setData(Uint32Array.from(vertData)); - pd.setVerts(verts); - - } - - return pd; -} - - /** - * Initialize rendering properties (color, opacity, visibility) - * @param {vtkActor} actor - * @param {string} groupName - */ - setProperty(actor) { - const prop = actor.getProperty(); - prop.setRepresentation(0); - prop.setOpacity(1); - actor.setVisibility(false); - prop.setColor(GlobalSettings.Instance.getColorForGroup()); - } - -} diff --git a/resources/visu_vtk/js/interaction/AxesCreator.js b/resources/visu_vtk/js/interaction/AxesCreator.js deleted file mode 100644 index f11c6be..0000000 --- a/resources/visu_vtk/js/interaction/AxesCreator.js +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Creates custom XYZ axes actors with colored cylinders and spheres for visualization. - * Provides utility to generate axes for VTK rendering. - */ -class CustomAxesCreator { - constructor() { - this.axisLength = 1.0; - this.axisRadius = 0.02; - this.sphereRadius = 0.08; - - this.colors = { - x: [1, 0, 0], - y: [0.251, 0.529, 0.376], - z: [0, 0, 1] - }; - } - - /** - * Creates a single actor containing X, Y, Z axes with spheres at the ends. - * @returns {vtkActor} - VTK actor containing all axes - */ - static createCustomAxesActor() { - const instance = new CustomAxesCreator(); - - const axisRadius = instance.axisRadius; - const sphereRadius = 0.1; - const sphereTheta = 12; - const spherePhi = 12; - - const addColor = (polyData, color) => { - const scalars = vtk.Common.Core.vtkDataArray.newInstance({ - numberOfComponents: 3, - values: new Uint8Array(polyData.getPoints().getNumberOfPoints() * 3), - name: 'color' - }); - - const colors = scalars.getData(); - const rgb = color.map(c => Math.round(c * 255)); - for (let i = 0; i < colors.length; i += 3) { - colors[i] = rgb[0]; - colors[i + 1] = rgb[1]; - colors[i + 2] = rgb[2]; - } - - polyData.getPointData().setScalars(scalars); - }; - - const xAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); - xAxisSource.setInputData(vtk.Filters.Sources.vtkCylinderSource.newInstance({ - radius: axisRadius, - resolution: 20, - direction: [1, 0, 0], - center: [0.5, 0, 0] - }).getOutputData()); - - xAxisSource.addInputData(vtk.Filters.Sources.vtkSphereSource.newInstance({ - radius: sphereRadius, - center: [1, 0, 0], - thetaResolution: sphereTheta, - phiResolution: spherePhi - }).getOutputData()); - - const xAxis = xAxisSource.getOutputData(); - addColor(xAxis, instance.colors.x); - - const yAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); - yAxisSource.setInputData(vtk.Filters.Sources.vtkCylinderSource.newInstance({ - radius: axisRadius, - resolution: 20, - direction: [0, 1, 0], - center: [0, 0.5, 0] - }).getOutputData()); - - yAxisSource.addInputData(vtk.Filters.Sources.vtkSphereSource.newInstance({ - radius: sphereRadius, - center: [0, 1, 0], - thetaResolution: sphereTheta, - phiResolution: spherePhi - }).getOutputData()); - - const yAxis = yAxisSource.getOutputData(); - addColor(yAxis, instance.colors.y); - - const zAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); - zAxisSource.setInputData(vtk.Filters.Sources.vtkCylinderSource.newInstance({ - radius: axisRadius, - resolution: 20, - direction: [0, 0, 1], - center: [0, 0, 0.5] - }).getOutputData()); - - zAxisSource.addInputData(vtk.Filters.Sources.vtkSphereSource.newInstance({ - radius: sphereRadius, - center: [0, 0, 1], - thetaResolution: sphereTheta, - phiResolution: spherePhi - }).getOutputData()); - - const zAxis = zAxisSource.getOutputData(); - addColor(zAxis, instance.colors.z); - - // Combine all axes - const axesSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); - axesSource.setInputData(xAxis); - axesSource.addInputData(yAxis); - axesSource.addInputData(zAxis); - - const axesMapper = vtk.Rendering.Core.vtkMapper.newInstance(); - axesMapper.setInputData(axesSource.getOutputData()); - - const axesActor = vtk.Rendering.Core.vtkActor.newInstance(); - axesActor.setMapper(axesMapper); - axesActor.getProperty().setLighting(false); - - return axesActor; - } - - createAxisWithSphere(axis) { - const start = [0, 0, 0]; - const end = [0, 0, 0]; - end[['x', 'y', 'z'].indexOf(axis)] = this.axisLength; - - const cylinderSource = vtk.Filters.Sources.vtkCylinderSource.newInstance({ - height: this.axisLength, - radius: this.axisRadius, - resolution: 16 - }); - const cylinderMapper = vtk.Rendering.Core.vtkMapper.newInstance(); - cylinderMapper.setInputConnection(cylinderSource.getOutputPort()); - const cylinderActor = vtk.Rendering.Core.vtkActor.newInstance(); - cylinderActor.setMapper(cylinderMapper); - cylinderActor.getProperty().setColor(...this.colors[axis]); - this.positionCylinder(cylinderActor, start, end); - - const sphereSource = vtk.Filters.Sources.vtkSphereSource.newInstance({ - radius: this.sphereRadius, - thetaResolution: 16, - phiResolution: 16 - }); - const sphereMapper = vtk.Rendering.Core.vtkMapper.newInstance(); - sphereMapper.setInputConnection(sphereSource.getOutputPort()); - const sphereActor = vtk.Rendering.Core.vtkActor.newInstance(); - sphereActor.setMapper(sphereMapper); - sphereActor.setPosition(...end); - sphereActor.getProperty().setColor(...this.colors[axis]); - - return { cylinder: cylinderActor, sphere: sphereActor }; - } - - positionCylinder(actor, start, end) { - const center = [ - (start[0] + end[0]) / 2, - (start[1] + end[1]) / 2, - (start[2] + end[2]) / 2 - ]; - - const direction = [ - end[0] - start[0], - end[1] - start[1], - end[2] - start[2] - ]; - - const length = Math.sqrt(direction[0] ** 2 + direction[1] ** 2 + direction[2] ** 2); - const normalized = direction.map(d => d / length); - - const yAxis = [0, 1, 0]; - const rotationAxis = [ - yAxis[1] * normalized[2] - yAxis[2] * normalized[1], - yAxis[2] * normalized[0] - yAxis[0] * normalized[2], - yAxis[0] * normalized[1] - yAxis[1] * normalized[0] - ]; - - const dotProduct = yAxis[0] * normalized[0] + yAxis[1] * normalized[1] + yAxis[2] * normalized[2]; - const angle = Math.acos(dotProduct) * (180 / Math.PI); - - actor.setPosition(...center); - - const axisLength = Math.sqrt(rotationAxis[0] ** 2 + rotationAxis[1] ** 2 + rotationAxis[2] ** 2); - if (axisLength > 0.0001) { - actor.rotateWXYZ(angle, ...rotationAxis.map(a => a / axisLength)); - } - } -} diff --git a/resources/visu_vtk/js/interaction/CameraManager.js b/resources/visu_vtk/js/interaction/CameraManager.js deleted file mode 100644 index db03ea9..0000000 --- a/resources/visu_vtk/js/interaction/CameraManager.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Manages the camera and node scaling in the VTK visualization. - */ -class CameraManager { - - static get Instance() { - if (!this._i) { - this._i = new CameraManager(); - } - return this._i; - } - - /** - * Initializes camera manager with node groups, sets up axis marker and size updates. - * @param {Object} groups - Map of groupName -> Group instances - */ - init(groups) { - this.nodesGroups = {}; - - const renderer = VtkApp.Instance.getRenderer(); - this.camera = renderer.getActiveCamera(); - this.lastDistance = this.camera.getDistance(); - - // Store only node groups - for (const [groupName, group] of Object.entries(groups)) { - if (!group.isFaceGroup) { - this.nodesGroups[groupName] = group; - group.setSize(this.lastDistance); - } - } - - this.axisMarker = this.createAxisMarker(); - this.activateSizeUpdate(); - } - - /** - * Automatically updates node group sizes when the camera distance changes - */ - activateSizeUpdate() { - this.camera.onModified(() => { - const currentDistance = this.camera.getDistance(); - if (Math.abs(currentDistance - this.lastDistance) > 1e-2) { - for (const nodeGroup of Object.values(this.nodesGroups)) { - nodeGroup.setSize(currentDistance); - } - this.lastDistance = currentDistance; - } - }); - } - - /** - * Positions the camera along a given axis relative to its focal point. - * @param {string} axis - 'x', 'y', or 'z' - */ - setCameraAxis(axis) { - if (!this.camera) { return; } - - const focalPoint = this.camera.getFocalPoint(); - const distance = this.camera.getDistance(); - - let newPosition = [0, 0, 0]; - let viewUp = [0, 0, 1]; - - switch(axis.toLowerCase()) { - case 'x': - newPosition = [focalPoint[0] + distance, focalPoint[1], focalPoint[2]]; - break; - case 'y': - newPosition = [focalPoint[0], focalPoint[1] + distance, focalPoint[2]]; - break; - case 'z': - newPosition = [focalPoint[0], focalPoint[1], focalPoint[2] + distance]; - viewUp = [0, 1, 0]; - break; - default: - return; - } - - this.camera.setPosition(...newPosition); - this.camera.setViewUp(viewUp); - VtkApp.Instance.getRenderer().resetCameraClippingRange(); - VtkApp.Instance.getRenderWindow().render(); - } - - /** - * Creates an orientation marker widget with XYZ axes in the bottom-right corner. - * @returns {vtkOrientationMarkerWidget} - */ - createAxisMarker() { - const axes = CustomAxesCreator.createCustomAxesActor(); - - const widget = vtk.Interaction.Widgets.vtkOrientationMarkerWidget.newInstance({ - actor: axes, - interactor: VtkApp.Instance.getRenderWindow().getInteractor(), - }); - widget.setEnabled(true); - widget.setViewportCorner(vtk.Interaction.Widgets.vtkOrientationMarkerWidget.Corners.BOTTOM_RIGHT); - widget.setViewportSize(0.15); - - this.orientationWidget = widget; - this.axesActor = axes; - } -} diff --git a/resources/visu_vtk/js/settings/GlobalSettings.js b/resources/visu_vtk/js/settings/GlobalSettings.js deleted file mode 100644 index 2a2e89e..0000000 --- a/resources/visu_vtk/js/settings/GlobalSettings.js +++ /dev/null @@ -1,66 +0,0 @@ -class GlobalSettings { - static get Instance() { - if (!this._instance) { - this._instance = new GlobalSettings(); - } - return this._instance; - } - - constructor() { - this.grpIndex = 0; - } - - // scene - backgroundColor = [0.6627, 0.7960, 0.910]; // #a9cbe8 - ambientLightColor = [0.2, 0.2, 0.2]; // #333333 - lightColor = [0.6667, 0.6667, 0.6667]; // #aaaaaa - // app - surfaceInsideColor = [1, 1, 0]; // #ffff00 - - surfaceOutsideColor = [0.537, 0.529, 0.529]; // #898787 - localSelectedColor = [1, 1, 1]; // #ffffff - surfaceTransparentColor = [0.553, 0.749, 0.42]; // #8dbf6b - surfaceRenderOrder = 0; - - wireframeColor = [0, 0, 0]; // #000000 - wireframeOpacity = 0.35; - wireframeAlpha = 1; - wireframeRenderOrder = 10; - wireframeSelectedColor = [1, 1, 1]; // #ffffff - wireframeSelectedRenderOrder = 11; - - drawLineColor = [1, 0, 0]; // #ff0000 - drawLineHelperRenderOrder = 12; - selectHelperColor = [1, 1, 1]; // #ffffff - selectionPointColor = [1, 0, 0]; // #ff0000 - - // couleurs des groupes - meshGroupColors = [ - [0.902, 0.098, 0.294], // #e6194b - [0.235, 0.706, 0.294], // #3cb44b - [1, 0.882, 0.098], // #ffe119 - [0.941, 0.196, 0.902], // #f032e6 - [0.961, 0.510, 0.192], // #f58231 - [0.569, 0.118, 0.706], // #911eb4 - [0.275, 0.941, 0.941], // #46f0f0 - [0.737, 0.965, 0.047], // #bcf60c - [0.980, 0.745, 0.745], // #fabebe - [0, 0.502, 0.502], // #008080 - [0.902, 0.745, 1], // #e6beff - [0.604, 0.388, 0.141], // #9a6324 - [0.263, 0.388, 0.847], // #4363d8 - [1, 0.980, 0.784], // #fffac8 - [0.502, 0, 0], // #800000 - [0.667, 1, 0.764], // #aaffc3 - [0.502, 0.502, 0], // #808000 - [1, 0.847, 0.694], // #ffd8b1 - [0, 0, 0.463], // #000075 - [0.502, 0.502, 0.502], // #808080 - ]; - - getColorForGroup() { - let idx = this.grpIndex % this.meshGroupColors.length; - this.grpIndex++; - return this.meshGroupColors[idx]; - } -} diff --git a/resources/visu_vtk/js/ui/UIManager.js b/resources/visu_vtk/js/ui/UIManager.js deleted file mode 100644 index 11d7a64..0000000 --- a/resources/visu_vtk/js/ui/UIManager.js +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Manages the creation and interaction of UI elements in the visualization panel. - */ -class UIManager { - /** - * Manage a singleton instance - */ - static get Instance() { - if (!this._i) { - this._i = new UIManager(); - } - return this._i; - } - - /** - * Initializes the manager by adding onclick events, buttons and setting up the popup. - * @param {Map { - VisibilityManager.Instance.clear(); - }); - - // Group buttons popup - const selectGroupsBtn = document.getElementById("selectGroupsBtn"); - selectGroupsBtn.addEventListener("click", () => { - this.openGroupButtonsPopup(); - }); - const saveBtn = document.getElementById("saveBtn"); - saveBtn.addEventListener("click", this.saveGroupButtonsPopup); - const cancelBtn = document.getElementById("cancelBtn"); - cancelBtn.addEventListener("click", this.cancelGroupButtonsPopup); - - // Camera axis buttons, to allow quick camera control - const xBtn = document.getElementById("xBtn"); - const yBtn = document.getElementById("yBtn"); - const zBtn = document.getElementById("zBtn"); - xBtn.addEventListener("click", () => { - CameraManager.Instance.setCameraAxis("x"); - }); - yBtn.addEventListener("click", () => { - CameraManager.Instance.setCameraAxis("y"); - }); - zBtn.addEventListener("click", () => { - CameraManager.Instance.setCameraAxis("z"); - }); - - // Help popup - const helpBtn = document.getElementById("helpBtn"); - helpBtn.addEventListener("click", () => { - this.openHelpPopup(); - }); - const closeHelpBtn = document.getElementById("closeHelpBtn"); - closeHelpBtn.addEventListener("click", () => { - this.closeHelpPopup(); - }); - } - - /** - * Add the list of group buttons to the sidebar. - * @param {Map } objects A map of objects with their corresponding face and node groups. - */ - addGroupButtons(objects) { - // Hack to retrieve necessary icons - const objectIconUrl = document.getElementById("object").src; - const faceIconUrl = document.getElementById("face").src; - const nodeIconUrl = document.getElementById("node").src; - - // Get group buttons div - const groupButtonsDiv = document.getElementById("groupButtons"); - - // Add buttons for each object and its groups - for (const object in objects) { - const { faces, nodes } = objects[object]; - const objectName = object.replace("all_", "").replace(".obj", ""); - - // Create object label - const objectLabel = document.createElement("span"); - objectLabel.id = `obj_${objectName}`; - objectLabel.classList.add( - "relative", - "h-4.5", - "w-full", - "flex", - "justify-center", - "items-center", - "mb-2", - "not-nth-of-type-[1]:mt-1", - "text-xs", - "text-black/70", - "font-bold" - ); - - const icon = ``; - const text = `${objectName}`; - objectLabel.innerHTML = icon + text; - - groupButtonsDiv.appendChild(objectLabel); - - // Create group buttons for the current object - const groups = faces.concat(nodes); - groups.forEach((groupName) => { - const btn = document.createElement("button"); - btn.id = `btn_${object}::${groupName}`; - btn.classList.add( - "relative", - "flex", - "items-center", - "justify-center", - "hover:bg-white/50", - "rounded-sm", - "bg-white/30", - "text-black/70", - "text-xs", - "px-2", - "pt-0.75", - "pb-1.25", - "w-full", - "cursor-pointer" - ); - - const icon = ``; - const text = `${groupName}`; - btn.innerHTML = icon + text; - - btn.addEventListener("click", () => { - VisibilityManager.Instance.setVisibility(`${object}::${groupName}`); - }); - - groupButtonsDiv.appendChild(btn); - }); - } - } - - /** - * Set a group button's status between highlighted or not. - * A highlighted button will be colorful with bold text, while a non highlighted button will be grey. - * @param {HTMLButtonElement} groupName The group button that will be highlighted or not. - * @param {number[]} color An RGB color array corresponding to the group. The highlight will be removed if not set. - */ - highlightButton(groupName, color) { - const btn = document.getElementById(`btn_${groupName}`); - - if (color) { - // If the button was not highlighted, highlight it - btn.classList.add("font-semibold", "hover:brightness-90"); - btn.classList.remove("bg-white/30"); - btn.style.backgroundColor = `rgb(${color[0] * 255}, ${color[1] * 255}, ${ - color[2] * 255 - }, 0.8)`; - } else { - // Else unapply the highlight - btn.classList.remove("font-semibold", "hover:brightness-90"); - btn.classList.add("bg-white/30"); - btn.style.backgroundColor = ""; - } - } - - /** - * Add the list of group buttons to the sidebar. - * @param {Map } objects A map of objects with their corresponding face and node groups. - */ - initGroupButtonsPopup(objects) { - // Get group list inside the popup - const groupList = document.getElementById("groupList"); - // Add buttons for each object and its groups - for (const object in objects) { - const { faces, nodes } = objects[object]; - const objectName = object.replace("all_", "").replace(".obj", ""); - - // Create object div - const objectDiv = document.createElement("div"); - objectDiv.classList.add("flex", "flex-col", "space-y-1", "mb-4"); - objectDiv.dataset.object = object; - - // Create object label - const objectLabel = `${objectName}`; - objectDiv.innerHTML += objectLabel; - - // Create group checkboxes for the current object - const groups = faces.concat(nodes); - groups.forEach((groupName) => { - const label = ``; - objectDiv.innerHTML += label; - }); - groupList.append(objectDiv); - } - } - - /** - * Open the group buttons popup - */ - openGroupButtonsPopup() { - const popup = document.getElementById("popup"); - const groupButtonsPopup = document.getElementById("groupButtonsPopup"); - popup.classList.remove("hidden!"); - groupButtonsPopup.classList.remove("hidden!"); - } - - /** - * Save group visibility in the sidebar. All checked groups will be visible, while unchecked groups will be hidden. - * If all the groups from an object are hidden, the object is also hidden from the sidebar. - * Hidden groups are still visible on the 3D view, they are just hidden from the sidebar. - */ - saveGroupButtonsPopup() { - const groupList = document.getElementById("groupList"); - - // Parse all objects - for (let i = 0; i < groupList.children.length; ++i) { - const objectDiv = groupList.children.item(i); - - // Retrieve current object name and key - const objectNameSpan = objectDiv.querySelector("span.font-semibold"); - const objectName = objectNameSpan.textContent.trim(); - const objectKey = objectDiv.dataset.object; - let allGroupsHidden = true; - - // Parse all labels for the current object - const labels = objectDiv.querySelectorAll("label"); - labels.forEach((label) => { - const input = label.querySelector("input"); - const span = label.querySelector("span"); - - // Retrieve group name - const groupName = span.textContent.trim(); - - // Hide or show group in the sidebar - const btn = document.getElementById(`btn_${objectKey}::${groupName}`); - if (input.checked) { - btn.classList.remove("hidden!"); - allGroupsHidden = false; - } else { - btn.classList.add("hidden!"); - } - }); - - // Retrieve object label from the sidebar - const objectLabel = document.getElementById(`obj_${objectName}`); - if (allGroupsHidden) { - objectLabel.classList.add("hidden!"); - } else { - objectLabel.classList.remove("hidden!"); - } - } - - // Close popup - const popup = document.getElementById("popup"); - const groupButtonsPopup = document.getElementById("groupButtonsPopup"); - popup.classList.add("hidden!"); - groupButtonsPopup.classList.add("hidden!"); - } - - /** - * Cancel the popup actions. - * Checked status will be reset to what they were before opening, and no additional buttons will be shown or hidden. - */ - cancelGroupButtonsPopup() { - const groupList = document.getElementById("groupList"); - - // Reset checked status for each group to what they were before opening the popup - for (let i = 0; i < groupList.children.length; ++i) { - const objectDiv = groupList.children.item(i); - const labels = objectDiv.querySelectorAll("label"); - - const objectKey = objectDiv.dataset.object; - labels.forEach((label) => { - const input = label.querySelector("input"); - const span = label.querySelector("span"); - - // Retrieve group name - const groupName = span.textContent.trim(); - - // Set the checkbox state based on the button's visibility, since it did not change - const btn = document.getElementById(`btn_${objectKey}::${groupName}`); - input.checked = !btn.classList.contains("hidden!"); - }); - } - - // Close popup - const popup = document.getElementById("popup"); - const groupButtonsPopup = document.getElementById("groupButtonsPopup"); - popup.classList.add("hidden!"); - groupButtonsPopup.classList.add("hidden!"); - } - - /** - * Open the help popup - */ - openHelpPopup() { - const popup = document.getElementById("popup"); - const helpPopup = document.getElementById("helpPopup"); - popup.classList.remove("hidden!"); - helpPopup.classList.remove("hidden!"); - } - - /** - * Close the help popup - */ - closeHelpPopup() { - const popup = document.getElementById("popup"); - const helpPopup = document.getElementById("helpPopup"); - popup.classList.add("hidden!"); - helpPopup.classList.add("hidden!"); - } -} diff --git a/resources/visu_vtk/styles.css b/resources/visu_vtk/styles.css deleted file mode 100644 index b01555f..0000000 --- a/resources/visu_vtk/styles.css +++ /dev/null @@ -1,5 +0,0 @@ -@import "tailwindcss"; - -kbd { - @apply text-blue-500 bg-white/30 px-1 py-px rounded-sm; -} diff --git a/resources/visu_vtk/tailwind.css b/resources/visu_vtk/tailwind.css deleted file mode 100644 index 2cc1253..0000000 --- a/resources/visu_vtk/tailwind.css +++ /dev/null @@ -1,1147 +0,0 @@ -/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */ -@layer properties; -@layer theme, base, components, utilities; -@layer theme { - :root, :host { - --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", - "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; - --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", - "Courier New", monospace; - --color-red-600: oklch(57.7% 0.245 27.325); - --color-green-600: oklch(62.7% 0.194 149.214); - --color-blue-500: oklch(62.3% 0.214 259.815); - --color-blue-600: oklch(54.6% 0.245 262.881); - --color-slate-500: oklch(55.4% 0.046 257.417); - --color-slate-700: oklch(37.2% 0.044 257.287); - --color-black: #000; - --color-white: #fff; - --spacing: 0.25rem; - --text-xs: 0.75rem; - --text-xs--line-height: calc(1 / 0.75); - --text-sm: 0.875rem; - --text-sm--line-height: calc(1.25 / 0.875); - --text-base: 1rem; - --text-base--line-height: calc(1.5 / 1); - --font-weight-semibold: 600; - --font-weight-bold: 700; - --radius-sm: 0.25rem; - --blur-xs: 4px; - --blur-lg: 16px; - --default-font-family: var(--font-sans); - --default-mono-font-family: var(--font-mono); - } -} -@layer base { - *, ::after, ::before, ::backdrop, ::file-selector-button { - box-sizing: border-box; - margin: 0; - padding: 0; - border: 0 solid; - } - html, :host { - line-height: 1.5; - -webkit-text-size-adjust: 100%; - tab-size: 4; - font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); - font-feature-settings: var(--default-font-feature-settings, normal); - font-variation-settings: var(--default-font-variation-settings, normal); - -webkit-tap-highlight-color: transparent; - } - hr { - height: 0; - color: inherit; - border-top-width: 1px; - } - abbr:where([title]) { - -webkit-text-decoration: underline dotted; - text-decoration: underline dotted; - } - h1, h2, h3, h4, h5, h6 { - font-size: inherit; - font-weight: inherit; - } - a { - color: inherit; - -webkit-text-decoration: inherit; - text-decoration: inherit; - } - b, strong { - font-weight: bolder; - } - code, kbd, samp, pre { - font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); - font-feature-settings: var(--default-mono-font-feature-settings, normal); - font-variation-settings: var(--default-mono-font-variation-settings, normal); - font-size: 1em; - } - small { - font-size: 80%; - } - sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - sub { - bottom: -0.25em; - } - sup { - top: -0.5em; - } - table { - text-indent: 0; - border-color: inherit; - border-collapse: collapse; - } - :-moz-focusring { - outline: auto; - } - progress { - vertical-align: baseline; - } - summary { - display: list-item; - } - ol, ul, menu { - list-style: none; - } - img, svg, video, canvas, audio, iframe, embed, object { - display: block; - vertical-align: middle; - } - img, video { - max-width: 100%; - height: auto; - } - button, input, select, optgroup, textarea, ::file-selector-button { - font: inherit; - font-feature-settings: inherit; - font-variation-settings: inherit; - letter-spacing: inherit; - color: inherit; - border-radius: 0; - background-color: transparent; - opacity: 1; - } - :where(select:is([multiple], [size])) optgroup { - font-weight: bolder; - } - :where(select:is([multiple], [size])) optgroup option { - padding-inline-start: 20px; - } - ::file-selector-button { - margin-inline-end: 4px; - } - ::placeholder { - opacity: 1; - } - @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { - ::placeholder { - color: currentcolor; - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, currentcolor 50%, transparent); - } - } - } - textarea { - resize: vertical; - } - ::-webkit-search-decoration { - -webkit-appearance: none; - } - ::-webkit-date-and-time-value { - min-height: 1lh; - text-align: inherit; - } - ::-webkit-datetime-edit { - display: inline-flex; - } - ::-webkit-datetime-edit-fields-wrapper { - padding: 0; - } - ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { - padding-block: 0; - } - ::-webkit-calendar-picker-indicator { - line-height: 1; - } - :-moz-ui-invalid { - box-shadow: none; - } - button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { - appearance: button; - } - ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { - height: auto; - } - [hidden]:where(:not([hidden="until-found"])) { - display: none !important; - } -} -@layer utilities { - .collapse { - visibility: collapse; - } - .visible { - visibility: visible; - } - .absolute { - position: absolute; - } - .fixed { - position: fixed; - } - .relative { - position: relative; - } - .static { - position: static; - } - .top-1 { - top: calc(var(--spacing) * 1); - } - .top-1\/2 { - top: calc(1/2 * 100%); - } - .top-2 { - top: calc(var(--spacing) * 2); - } - .top-\[0\.5px\] { - top: 0.5px; - } - .right-2 { - right: calc(var(--spacing) * 2); - } - .right-full { - right: 100%; - } - .left-1 { - left: calc(var(--spacing) * 1); - } - .left-1\.5 { - left: calc(var(--spacing) * 1.5); - } - .left-1\.25 { - left: calc(var(--spacing) * 1.25); - } - .left-1\/2 { - left: calc(1/2 * 100%); - } - .left-full { - left: 100%; - } - .isolate { - isolation: isolate; - } - .z-10 { - z-index: 10; - } - .container { - width: 100%; - @media (width >= 40rem) { - max-width: 40rem; - } - @media (width >= 48rem) { - max-width: 48rem; - } - @media (width >= 64rem) { - max-width: 64rem; - } - @media (width >= 80rem) { - max-width: 80rem; - } - @media (width >= 96rem) { - max-width: 96rem; - } - } - .container\! { - width: 100% !important; - @media (width >= 40rem) { - max-width: 40rem !important; - } - @media (width >= 48rem) { - max-width: 48rem !important; - } - @media (width >= 64rem) { - max-width: 64rem !important; - } - @media (width >= 80rem) { - max-width: 80rem !important; - } - @media (width >= 96rem) { - max-width: 96rem !important; - } - } - .mx-auto { - margin-inline: auto; - } - .my-2 { - margin-block: calc(var(--spacing) * 2); - } - .mt-0 { - margin-top: calc(var(--spacing) * 0); - } - .mt-0\.5 { - margin-top: calc(var(--spacing) * 0.5); - } - .mt-4 { - margin-top: calc(var(--spacing) * 4); - } - .mb-2 { - margin-bottom: calc(var(--spacing) * 2); - } - .mb-4 { - margin-bottom: calc(var(--spacing) * 4); - } - .block { - display: block; - } - .contents { - display: contents; - } - .flex { - display: flex; - } - .grid { - display: grid; - } - .hidden { - display: none; - } - .hidden\! { - display: none !important; - } - .inline { - display: inline; - } - .table { - display: table; - } - .size-1 { - width: calc(var(--spacing) * 1); - height: calc(var(--spacing) * 1); - } - .size-3 { - width: calc(var(--spacing) * 3); - height: calc(var(--spacing) * 3); - } - .size-4 { - width: calc(var(--spacing) * 4); - height: calc(var(--spacing) * 4); - } - .size-4\.5 { - width: calc(var(--spacing) * 4.5); - height: calc(var(--spacing) * 4.5); - } - .size-5 { - width: calc(var(--spacing) * 5); - height: calc(var(--spacing) * 5); - } - .size-5\.5 { - width: calc(var(--spacing) * 5.5); - height: calc(var(--spacing) * 5.5); - } - .size-6 { - width: calc(var(--spacing) * 6); - height: calc(var(--spacing) * 6); - } - .size-6\.5 { - width: calc(var(--spacing) * 6.5); - height: calc(var(--spacing) * 6.5); - } - .h-4 { - height: calc(var(--spacing) * 4); - } - .h-4\.5 { - height: calc(var(--spacing) * 4.5); - } - .h-full { - height: 100%; - } - .h-px { - height: 1px; - } - .h-screen { - height: 100vh; - } - .max-h-2 { - max-height: calc(var(--spacing) * 2); - } - .max-h-2\/3 { - max-height: calc(2/3 * 100%); - } - .w-2 { - width: calc(var(--spacing) * 2); - } - .w-2\/3 { - width: calc(2/3 * 100%); - } - .w-3 { - width: calc(var(--spacing) * 3); - } - .w-3\/4 { - width: calc(3/4 * 100%); - } - .w-full { - width: 100%; - } - .w-screen { - width: 100vw; - } - .flex-grow { - flex-grow: 1; - } - .grow { - flex-grow: 1; - } - .border-collapse { - border-collapse: collapse; - } - .-translate-x-1 { - --tw-translate-x: calc(var(--spacing) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } - .-translate-x-1\/2 { - --tw-translate-x: calc(calc(1/2 * 100%) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } - .-translate-y-1 { - --tw-translate-y: calc(var(--spacing) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } - .-translate-y-1\/2 { - --tw-translate-y: calc(calc(1/2 * 100%) * -1); - translate: var(--tw-translate-x) var(--tw-translate-y); - } - .transform { - transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,); - } - .cursor-pointer { - cursor: pointer; - } - .resize { - resize: both; - } - .list-inside { - list-style-position: inside; - } - .list-disc { - list-style-type: disc; - } - .flex-col { - flex-direction: column; - } - .flex-wrap { - flex-wrap: wrap; - } - .items-center { - align-items: center; - } - .justify-center { - justify-content: center; - } - .space-y-1 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); - } - } - .space-y-4 { - :where(& > :not(:last-child)) { - --tw-space-y-reverse: 0; - margin-block-start: calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse)); - margin-block-end: calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse))); - } - } - .space-x-1 { - :where(& > :not(:last-child)) { - --tw-space-x-reverse: 0; - margin-inline-start: calc(calc(var(--spacing) * 1) * var(--tw-space-x-reverse)); - margin-inline-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-x-reverse))); - } - } - .space-x-1\.5 { - :where(& > :not(:last-child)) { - --tw-space-x-reverse: 0; - margin-inline-start: calc(calc(var(--spacing) * 1.5) * var(--tw-space-x-reverse)); - margin-inline-end: calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-x-reverse))); - } - } - .space-x-3 { - :where(& > :not(:last-child)) { - --tw-space-x-reverse: 0; - margin-inline-start: calc(calc(var(--spacing) * 3) * var(--tw-space-x-reverse)); - margin-inline-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-x-reverse))); - } - } - .space-x-6 { - :where(& > :not(:last-child)) { - --tw-space-x-reverse: 0; - margin-inline-start: calc(calc(var(--spacing) * 6) * var(--tw-space-x-reverse)); - margin-inline-end: calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-x-reverse))); - } - } - .divide-y { - :where(& > :not(:last-child)) { - --tw-divide-y-reverse: 0; - border-bottom-style: var(--tw-border-style); - border-top-style: var(--tw-border-style); - border-top-width: calc(1px * var(--tw-divide-y-reverse)); - border-bottom-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); - } - } - .divide-black { - :where(& > :not(:last-child)) { - border-color: var(--color-black); - } - } - .divide-black\/5 { - :where(& > :not(:last-child)) { - border-color: color-mix(in srgb, #000 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-black) 5%, transparent); - } - } - } - .self-end { - align-self: flex-end; - } - .overflow-y-auto { - overflow-y: auto; - } - .rounded { - border-radius: 0.25rem; - } - .rounded-full { - border-radius: calc(infinity * 1px); - } - .rounded-sm { - border-radius: var(--radius-sm); - } - .rounded-r-sm { - border-top-right-radius: var(--radius-sm); - border-bottom-right-radius: var(--radius-sm); - } - .border { - border-style: var(--tw-border-style); - border-width: 1px; - } - .border-2 { - border-style: var(--tw-border-style); - border-width: 2px; - } - .border-l { - border-left-style: var(--tw-border-style); - border-left-width: 1px; - } - .border-black { - border-color: var(--color-black); - } - .border-black\/5 { - border-color: color-mix(in srgb, #000 5%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-black) 5%, transparent); - } - } - .border-blue-600 { - border-color: var(--color-blue-600); - } - .border-green-600 { - border-color: var(--color-green-600); - } - .border-red-600 { - border-color: var(--color-red-600); - } - .border-slate-500 { - border-color: var(--color-slate-500); - } - .border-slate-500\/50 { - border-color: color-mix(in srgb, oklch(55.4% 0.046 257.417) 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - border-color: color-mix(in oklab, var(--color-slate-500) 50%, transparent); - } - } - .bg-black { - background-color: var(--color-black); - } - .bg-black\/10 { - background-color: color-mix(in srgb, #000 10%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 10%, transparent); - } - } - .bg-black\/20 { - background-color: color-mix(in srgb, #000 20%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-black) 20%, transparent); - } - } - .bg-blue-500 { - background-color: var(--color-blue-500); - } - .bg-white { - background-color: var(--color-white); - } - .bg-white\/30 { - background-color: color-mix(in srgb, #fff 30%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 30%, transparent); - } - } - .bg-white\/70 { - background-color: color-mix(in srgb, #fff 70%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 70%, transparent); - } - } - .p-1 { - padding: calc(var(--spacing) * 1); - } - .p-1\.5 { - padding: calc(var(--spacing) * 1.5); - } - .p-2 { - padding: calc(var(--spacing) * 2); - } - .p-8 { - padding: calc(var(--spacing) * 8); - } - .px-2 { - padding-inline: calc(var(--spacing) * 2); - } - .px-3 { - padding-inline: calc(var(--spacing) * 3); - } - .py-1 { - padding-block: calc(var(--spacing) * 1); - } - .pt-0 { - padding-top: calc(var(--spacing) * 0); - } - .pt-0\.75 { - padding-top: calc(var(--spacing) * 0.75); - } - .pr-1 { - padding-right: calc(var(--spacing) * 1); - } - .pr-1\.5 { - padding-right: calc(var(--spacing) * 1.5); - } - .pr-2 { - padding-right: calc(var(--spacing) * 2); - } - .pb-1 { - padding-bottom: calc(var(--spacing) * 1); - } - .pb-1\.25 { - padding-bottom: calc(var(--spacing) * 1.25); - } - .pl-1 { - padding-left: calc(var(--spacing) * 1); - } - .pl-1\.5 { - padding-left: calc(var(--spacing) * 1.5); - } - .pl-5 { - padding-left: calc(var(--spacing) * 5); - } - .align-middle { - vertical-align: middle; - } - .align-top { - vertical-align: top; - } - .text-base { - font-size: var(--text-base); - line-height: var(--tw-leading, var(--text-base--line-height)); - } - .text-sm { - font-size: var(--text-sm); - line-height: var(--tw-leading, var(--text-sm--line-height)); - } - .text-xs { - font-size: var(--text-xs); - line-height: var(--tw-leading, var(--text-xs--line-height)); - } - .text-\[0\.65rem\] { - font-size: 0.65rem; - } - .font-bold { - --tw-font-weight: var(--font-weight-bold); - font-weight: var(--font-weight-bold); - } - .font-semibold { - --tw-font-weight: var(--font-weight-semibold); - font-weight: var(--font-weight-semibold); - } - .whitespace-nowrap { - white-space: nowrap; - } - .text-black { - color: var(--color-black); - } - .text-black\/50 { - color: color-mix(in srgb, #000 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, var(--color-black) 50%, transparent); - } - } - .text-black\/70 { - color: color-mix(in srgb, #000 70%, transparent); - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, var(--color-black) 70%, transparent); - } - } - .text-blue-500 { - color: var(--color-blue-500); - } - .text-blue-500\! { - color: var(--color-blue-500) !important; - } - .text-blue-600 { - color: var(--color-blue-600); - } - .text-green-600 { - color: var(--color-green-600); - } - .text-green-600\! { - color: var(--color-green-600) !important; - } - .text-red-600 { - color: var(--color-red-600); - } - .text-red-600\! { - color: var(--color-red-600) !important; - } - .text-slate-700 { - color: var(--color-slate-700); - } - .text-white { - color: var(--color-white); - } - .lowercase { - text-transform: lowercase; - } - .uppercase { - text-transform: uppercase; - } - .underline { - text-decoration-line: underline; - } - .shadow { - --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } - .shadow-lg { - --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1)); - box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); - } - .outline { - outline-style: var(--tw-outline-style); - outline-width: 1px; - } - .blur { - --tw-blur: blur(8px); - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - .invert { - --tw-invert: invert(100%); - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - .filter { - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - .backdrop-blur-lg { - --tw-backdrop-blur: blur(var(--blur-lg)); - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - } - .backdrop-blur-xs { - --tw-backdrop-blur: blur(var(--blur-xs)); - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - } - .backdrop-filter { - -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); - } - .select-none { - -webkit-user-select: none; - user-select: none; - } - .not-nth-of-type-\[1\]\:mt-1 { - &:not(*:nth-of-type(1)) { - margin-top: calc(var(--spacing) * 1); - } - } - .group-hover\:inline { - &:is(:where(.group):hover *) { - @media (hover: hover) { - display: inline; - } - } - } - .hover\:bg-blue-600 { - &:hover { - @media (hover: hover) { - background-color: var(--color-blue-600); - } - } - } - .hover\:bg-green-600 { - &:hover { - @media (hover: hover) { - background-color: var(--color-green-600); - } - } - } - .hover\:bg-red-600 { - &:hover { - @media (hover: hover) { - background-color: var(--color-red-600); - } - } - } - .hover\:bg-white\/20 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, #fff 20%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 20%, transparent); - } - } - } - } - .hover\:bg-white\/40 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, #fff 40%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 40%, transparent); - } - } - } - } - .hover\:bg-white\/50 { - &:hover { - @media (hover: hover) { - background-color: color-mix(in srgb, #fff 50%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 50%, transparent); - } - } - } - } - .hover\:text-white\/70 { - &:hover { - @media (hover: hover) { - color: color-mix(in srgb, #fff 70%, transparent); - @supports (color: color-mix(in lab, red, red)) { - color: color-mix(in oklab, var(--color-white) 70%, transparent); - } - } - } - } - .hover\:brightness-90 { - &:hover { - @media (hover: hover) { - --tw-brightness: brightness(90%); - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - } - } - .hover\:brightness-95 { - &:hover { - @media (hover: hover) { - --tw-brightness: brightness(95%); - filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); - } - } - } -} -kbd { - border-radius: var(--radius-sm); - background-color: color-mix(in srgb, #fff 30%, transparent); - @supports (color: color-mix(in lab, red, red)) { - background-color: color-mix(in oklab, var(--color-white) 30%, transparent); - } - padding-inline: calc(var(--spacing) * 1); - padding-block: 1px; - color: var(--color-blue-500); -} -@property --tw-translate-x { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-translate-y { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-translate-z { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-rotate-x { - syntax: "*"; - inherits: false; -} -@property --tw-rotate-y { - syntax: "*"; - inherits: false; -} -@property --tw-rotate-z { - syntax: "*"; - inherits: false; -} -@property --tw-skew-x { - syntax: "*"; - inherits: false; -} -@property --tw-skew-y { - syntax: "*"; - inherits: false; -} -@property --tw-space-y-reverse { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-space-x-reverse { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-divide-y-reverse { - syntax: "*"; - inherits: false; - initial-value: 0; -} -@property --tw-border-style { - syntax: "*"; - inherits: false; - initial-value: solid; -} -@property --tw-font-weight { - syntax: "*"; - inherits: false; -} -@property --tw-shadow { - syntax: "*"; - inherits: false; - initial-value: 0 0 #0000; -} -@property --tw-shadow-color { - syntax: "*"; - inherits: false; -} -@property --tw-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100%; -} -@property --tw-inset-shadow { - syntax: "*"; - inherits: false; - initial-value: 0 0 #0000; -} -@property --tw-inset-shadow-color { - syntax: "*"; - inherits: false; -} -@property --tw-inset-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100%; -} -@property --tw-ring-color { - syntax: "*"; - inherits: false; -} -@property --tw-ring-shadow { - syntax: "*"; - inherits: false; - initial-value: 0 0 #0000; -} -@property --tw-inset-ring-color { - syntax: "*"; - inherits: false; -} -@property --tw-inset-ring-shadow { - syntax: "*"; - inherits: false; - initial-value: 0 0 #0000; -} -@property --tw-ring-inset { - syntax: "*"; - inherits: false; -} -@property --tw-ring-offset-width { - syntax: ""; - inherits: false; - initial-value: 0px; -} -@property --tw-ring-offset-color { - syntax: "*"; - inherits: false; - initial-value: #fff; -} -@property --tw-ring-offset-shadow { - syntax: "*"; - inherits: false; - initial-value: 0 0 #0000; -} -@property --tw-outline-style { - syntax: "*"; - inherits: false; - initial-value: solid; -} -@property --tw-blur { - syntax: "*"; - inherits: false; -} -@property --tw-brightness { - syntax: "*"; - inherits: false; -} -@property --tw-contrast { - syntax: "*"; - inherits: false; -} -@property --tw-grayscale { - syntax: "*"; - inherits: false; -} -@property --tw-hue-rotate { - syntax: "*"; - inherits: false; -} -@property --tw-invert { - syntax: "*"; - inherits: false; -} -@property --tw-opacity { - syntax: "*"; - inherits: false; -} -@property --tw-saturate { - syntax: "*"; - inherits: false; -} -@property --tw-sepia { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow-color { - syntax: "*"; - inherits: false; -} -@property --tw-drop-shadow-alpha { - syntax: ""; - inherits: false; - initial-value: 100%; -} -@property --tw-drop-shadow-size { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-blur { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-brightness { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-contrast { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-grayscale { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-hue-rotate { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-invert { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-opacity { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-saturate { - syntax: "*"; - inherits: false; -} -@property --tw-backdrop-sepia { - syntax: "*"; - inherits: false; -} -@layer properties { - @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { - *, ::before, ::after, ::backdrop { - --tw-translate-x: 0; - --tw-translate-y: 0; - --tw-translate-z: 0; - --tw-rotate-x: initial; - --tw-rotate-y: initial; - --tw-rotate-z: initial; - --tw-skew-x: initial; - --tw-skew-y: initial; - --tw-space-y-reverse: 0; - --tw-space-x-reverse: 0; - --tw-divide-y-reverse: 0; - --tw-border-style: solid; - --tw-font-weight: initial; - --tw-shadow: 0 0 #0000; - --tw-shadow-color: initial; - --tw-shadow-alpha: 100%; - --tw-inset-shadow: 0 0 #0000; - --tw-inset-shadow-color: initial; - --tw-inset-shadow-alpha: 100%; - --tw-ring-color: initial; - --tw-ring-shadow: 0 0 #0000; - --tw-inset-ring-color: initial; - --tw-inset-ring-shadow: 0 0 #0000; - --tw-ring-inset: initial; - --tw-ring-offset-width: 0px; - --tw-ring-offset-color: #fff; - --tw-ring-offset-shadow: 0 0 #0000; - --tw-outline-style: solid; - --tw-blur: initial; - --tw-brightness: initial; - --tw-contrast: initial; - --tw-grayscale: initial; - --tw-hue-rotate: initial; - --tw-invert: initial; - --tw-opacity: initial; - --tw-saturate: initial; - --tw-sepia: initial; - --tw-drop-shadow: initial; - --tw-drop-shadow-color: initial; - --tw-drop-shadow-alpha: 100%; - --tw-drop-shadow-size: initial; - --tw-backdrop-blur: initial; - --tw-backdrop-brightness: initial; - --tw-backdrop-contrast: initial; - --tw-backdrop-grayscale: initial; - --tw-backdrop-hue-rotate: initial; - --tw-backdrop-invert: initial; - --tw-backdrop-opacity: initial; - --tw-backdrop-saturate: initial; - --tw-backdrop-sepia: initial; - } - } -} diff --git a/src/ExportEditor.ts b/src/ExportEditor.ts index 640e75b..e7f8bc7 100644 --- a/src/ExportEditor.ts +++ b/src/ExportEditor.ts @@ -1,7 +1,7 @@ -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; -import { sendTelemetry, TelemetryType } from "./telemetry"; +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; +import { sendTelemetry, TelemetryType } from './telemetry'; interface ExportDescriptor { filename: string; @@ -46,8 +46,8 @@ export class ExportEditor implements vscode.Disposable { public static async initExportEditor() { let exportDescriptor: ExportDescriptor = { - filename: "", - content: "", + filename: '', + content: '', }; let destinationFolder = undefined; @@ -57,18 +57,18 @@ export class ExportEditor implements vscode.Disposable { const filePath = editor.document.uri.fsPath; let fileName = path.basename(filePath); let fileDir = path.dirname(filePath); - if (fileName.toLowerCase().includes(".export")) { + if (fileName.toLowerCase().includes('.export')) { exportDescriptor.filename = fileName; - exportDescriptor.content = fs.readFileSync(filePath, "utf8"); + exportDescriptor.content = fs.readFileSync(filePath, 'utf8'); destinationFolder = fileDir; } } - const testDir = path.resolve(__dirname, ".."); + const testDir = path.resolve(__dirname, '..'); const d = new ExportEditor( - "export-editor-webview", + 'export-editor-webview', testDir, - "resources/export_form/export.html", + 'webviews/export/export.html', exportDescriptor, destinationFolder, undefined @@ -78,7 +78,7 @@ export class ExportEditor implements vscode.Disposable { if (result) { vscode.window.showInformationMessage( - "File has been created in " + path.basename(d.destinationFolder) + "/" + 'File has been created in ' + path.basename(d.destinationFolder) + '/' ); } @@ -117,21 +117,15 @@ export class ExportEditor implements vscode.Disposable { if (destinationFolder) { this.destinationFolder = destinationFolder; } else { - this.destinationFolder = - vscode.workspace.workspaceFolders?.[0].uri.fsPath || __dirname; + this.destinationFolder = vscode.workspace.workspaceFolders?.[0].uri.fsPath || __dirname; } const htmlFile = path.join(resourceRootDir, htmlFileName); - let html = fs.readFileSync(htmlFile, { encoding: "utf8" }); + let html = fs.readFileSync(htmlFile, { encoding: 'utf8' }); - const title = this.extractHtmlTitle(html, "Export Editor"); + const title = this.extractHtmlTitle(html, 'Export Editor'); - this.panel = vscode.window.createWebviewPanel( - viewType, - title, - viewColumn, - options - ); + this.panel = vscode.window.createWebviewPanel(viewType, title, viewColumn, options); html = this.fixResourceReferences(html, resourceRootDir); html = this.fixCspSourceReferences(html); @@ -147,47 +141,47 @@ export class ExportEditor implements vscode.Disposable { const outputFiles = Object.values(formData.outputFiles); if ( - parameters.some((value) => value !== "") || + parameters.some((value) => value !== '') || inputFiles.length > 0 || outputFiles.length > 0 ) { this.panel.webview.postMessage({ - command: "exportFileAlreadyDefined", + command: 'exportFileAlreadyDefined', formData, }); } } - const files = this.getMatchingFiles("", ""); - this.panel.webview.postMessage({ command: "verifyFileNames", files }); + const files = this.getMatchingFiles('', ''); + this.panel.webview.postMessage({ command: 'verifyFileNames', files }); this.panel.webview.onDidReceiveMessage((message) => { - if (message.command === "cancel") { + if (message.command === 'cancel') { this.panel.dispose(); - } else if (message.command === "wrongCreation") { + } else if (message.command === 'wrongCreation') { vscode.window.showInformationMessage(`${message.value}`); - } else if (message.command === "result") { + } else if (message.command === 'result') { this.result = message.value as TResult; - const lines = message.value.split("\n"); + const lines = message.value.split('\n'); const filename = lines[0]; - const content = lines.slice(1).join("\n"); + const content = lines.slice(1).join('\n'); const fullPath = path.join(this.destinationFolder, filename); - fs.writeFileSync(fullPath, content, "utf8"); + fs.writeFileSync(fullPath, content, 'utf8'); // Report telemetry that an export file was created/saved void sendTelemetry(TelemetryType.EXPORT_SAVED); this.panel.dispose(); - } else if (message.command === "autocomplete") { + } else if (message.command === 'autocomplete') { const suggestions = this.getMatchingFiles(message.value, message.type); if (suggestions.length !== 0) { this.panel.webview.postMessage({ - command: "autocompleteResult", + command: 'autocompleteResult', suggestions, }); } else { this.panel.webview.postMessage({ - command: "autocompleteFailed", + command: 'autocompleteFailed', suggestions, }); } @@ -200,9 +194,7 @@ export class ExportEditor implements vscode.Disposable { return []; } const allFiles = fs.readdirSync(this.destinationFolder); - return allFiles.filter((name) => - name.toLowerCase().includes(partial.toLowerCase()) - ); + return allFiles.filter((name) => name.toLowerCase().includes(partial.toLowerCase())); } /** * Parse the content of an export file into structured form data. @@ -211,46 +203,46 @@ export class ExportEditor implements vscode.Disposable { */ private parseExportFile(exportDescriptor: ExportDescriptor): FormData { let formData: FormData = { - name: "", + name: '', parameters: { - time_limit: "", - memory_limit: "", - ncpus: "", - mpi_nbcpu: "", - mpi_nbnoeud: "", + time_limit: '', + memory_limit: '', + ncpus: '', + mpi_nbcpu: '', + mpi_nbnoeud: '', }, inputFiles: [], outputFiles: [], }; formData.name = exportDescriptor.filename; - const lines = exportDescriptor.content.split("\n"); + const lines = exportDescriptor.content.split('\n'); for (const line of lines) { - const cleanLine = line.split("#")[0].trim(); + const cleanLine = line.split('#')[0].trim(); if (!cleanLine) { continue; } const tokens = cleanLine.split(/\s+/); - if (tokens[0] === "P" && tokens.length === 3) { + if (tokens[0] === 'P' && tokens.length === 3) { const [_, key, value] = tokens; if (key in formData.parameters) { formData.parameters[key as keyof Parameters] = value; } } - if (tokens[0] === "F" && tokens.length === 5) { + if (tokens[0] === 'F' && tokens.length === 5) { const [_, type, name, ioFlag, unit] = tokens; const fileObj: FileDescriptor = { type: type, name: name, unit: unit, }; - if (ioFlag === "D") { + if (ioFlag === 'D') { formData.inputFiles.push(fileObj); - } else if (ioFlag === "R") { + } else if (ioFlag === 'R') { formData.outputFiles.push(fileObj); } } @@ -309,9 +301,7 @@ export class ExportEditor implements vscode.Disposable { * @param cancellation Optional cancellation token that can be used to * cancel waiting on a result. Cancelling the token also closes the dialog. */ - public async getResult( - cancellation?: vscode.CancellationToken - ): Promise { + public async getResult(cancellation?: vscode.CancellationToken): Promise { const disposePromise = new Promise((resolve, reject) => { this.panel.onDidDispose(resolve); }); diff --git a/src/LspServer.ts b/src/LspServer.ts index 52f68e8..0a47a43 100644 --- a/src/LspServer.ts +++ b/src/LspServer.ts @@ -1,13 +1,13 @@ -import * as vscode from "vscode"; -import * as path from "path"; +import * as vscode from 'vscode'; +import * as path from 'path'; import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, -} from "vscode-languageclient/node"; -import { StatusBar } from "./StatusBar"; -import { SUPPORTED_COMM_EXTENSIONS } from "./VisuManager"; +} from 'vscode-languageclient/node'; +import { StatusBar } from './StatusBar'; +import { SUPPORTED_COMM_EXTENSIONS } from './VisuManager'; /** * Singleton class to manage the Python LSP client for Code-Aster. * Handles client creation, start, restart, notifications, and editor listeners. @@ -27,7 +27,7 @@ export class LspServer { public get client(): LanguageClient { if (!this._client) { - throw new Error("LSP client has not been initialized yet."); + throw new Error('LSP client has not been initialized yet.'); } return this._client; } @@ -43,25 +43,21 @@ export class LspServer { this._client .start() .then(() => { - vscode.window.showInformationMessage("LSP Python Code-Aster ready!"); + vscode.window.showInformationMessage('LSP Python Code-Aster ready!'); this.attachEditorListeners(); }) .catch((err: any) => { - vscode.window.showErrorMessage( - "Error starting LSP Python: " + err.message, - ); + vscode.window.showErrorMessage('Error starting LSP Python: ' + err.message); }); - this._client.onDidChangeState((e) => - console.log("LSP client state changed:", e), - ); + this._client.onDidChangeState((e) => console.log('LSP client state changed:', e)); - this._client.onNotification("logParser", (params: { text: string }) => { + this._client.onNotification('logParser', (params: { text: string }) => { console.log(`${params.text}`); }); //TO DO : reload the bar - this._client.onNotification("reloadStatusBar", (params) => { + this._client.onNotification('reloadStatusBar', (params) => { StatusBar.instance.onEditorChange(vscode.window.activeTextEditor); }); } @@ -69,21 +65,14 @@ export class LspServer { /** * Creates the LanguageClient for Python LSP */ - private async createClient( - context: vscode.ExtensionContext, - ): Promise { - const serverModule = context.asAbsolutePath( - path.join("python", "lsp", "server.py"), - ); + private async createClient(context: vscode.ExtensionContext): Promise { + const serverModule = context.asAbsolutePath(path.join('python', 'lsp', 'server.py')); - const config = vscode.workspace.getConfiguration("vs-code-aster"); - const pythonExecutablePath = config.get( - "pythonExecutablePath", - "python3", - ); + const config = vscode.workspace.getConfiguration('vs-code-aster'); + const pythonExecutablePath = config.get('pythonExecutablePath', 'python3'); const commFileExtensions = config.get( - "commFileExtensions", - SUPPORTED_COMM_EXTENSIONS, + 'commFileExtensions', + SUPPORTED_COMM_EXTENSIONS ); // Build file system watcher patterns @@ -96,25 +85,23 @@ export class LspServer { options: { env: { ...process.env, - PYTHONPATH: context.asAbsolutePath("python"), + PYTHONPATH: context.asAbsolutePath('python'), }, }, }; const clientOptions: LanguageClientOptions = { - documentSelector: [{ scheme: "file", language: "comm" }], + documentSelector: [{ scheme: 'file', language: 'comm' }], synchronize: { - fileEvents: vscode.workspace.createFileSystemWatcher( - `{${watchPatterns.join(",")}}`, - ), + fileEvents: vscode.workspace.createFileSystemWatcher(`{${watchPatterns.join(',')}}`), }, }; return new LanguageClient( - "pythonLanguageServer", - "Python Language Server", + 'pythonLanguageServer', + 'Python Language Server', serverOptions, - clientOptions, + clientOptions ); } @@ -135,11 +122,8 @@ export class LspServer { //activate signature and completion triggers const lastChange = changes[changes.length - 1]; - if ( - ["(", ","].includes(lastChange.text) && - editor.document.languageId === "comm" - ) { - vscode.commands.executeCommand("editor.action.triggerParameterHints"); + if (['(', ','].includes(lastChange.text) && editor.document.languageId === 'comm') { + vscode.commands.executeCommand('editor.action.triggerParameterHints'); } }); } @@ -154,15 +138,9 @@ export class LspServer { this._client ?.start() - .then(() => - vscode.window.showInformationMessage( - "LSP Python Code-Aster restarted!", - ), - ) + .then(() => vscode.window.showInformationMessage('LSP Python Code-Aster restarted!')) .catch((err: any) => - vscode.window.showErrorMessage( - "Error restarting LSP Python: " + err.message, - ), + vscode.window.showErrorMessage('Error restarting LSP Python: ' + err.message) ); } diff --git a/src/RunAster.ts b/src/RunAster.ts index 210bd04..01cae87 100644 --- a/src/RunAster.ts +++ b/src/RunAster.ts @@ -6,77 +6,84 @@ import { promisify } from 'util'; const execAsync = promisify(exec); export class RunAster { - - /** - * Runs code_aster on the selected .export file in the workspace. - */ - public static async runCodeAster() { - const editor = vscode.window.activeTextEditor; - if (!editor) { - vscode.window.showErrorMessage(`No active file found`); - return; - } + /** + * Runs code_aster on the selected .export file in the workspace. + */ + public static async runCodeAster() { + const editor = vscode.window.activeTextEditor; + if (!editor) { + vscode.window.showErrorMessage(`No active file found`); + return; + } - const filePath = editor.document.uri.fsPath; - const fileName = path.basename(filePath); - const fileDir = path.dirname(filePath); + const filePath = editor.document.uri.fsPath; + const fileName = path.basename(filePath); + const fileDir = path.dirname(filePath); - if (!fileName.toLowerCase().includes('.export')) { - vscode.window.showErrorMessage(`The active file is not an .export file`); - return; - } - - const config = vscode.workspace.getConfiguration('vs-code-aster'); - const alias = config.get('aliasForRun', 'cave run'); + if (!fileName.toLowerCase().includes('.export')) { + vscode.window.showErrorMessage(`The active file is not an .export file`); + return; + } - // TO DO : find a way to check alias that is compatible everywhere - // const aliasIsValid = await RunAster.checkAlias(alias); - // if (!aliasIsValid) { - // return; - // } + const config = vscode.workspace.getConfiguration('vs-code-aster'); + const alias = config.get('aliasForRun', 'cave run'); - const simulationTerminal = vscode.window.createTerminal({ name: "code-aster runner", cwd: fileDir }); - - const cmd = `${alias} ${fileName}`; - simulationTerminal.show(); - simulationTerminal.sendText(cmd); - } + // TO DO : find a way to check alias that is compatible everywhere + // const aliasIsValid = await RunAster.checkAlias(alias); + // if (!aliasIsValid) { + // return; + // } - /** - * Verify the user's alias and return true if it exists on the system - * */ - private static async checkAlias(alias: string): Promise { - const firstWord = alias.split(' ')[0]; + const simulationTerminal = vscode.window.createTerminal({ + name: 'code-aster runner', + cwd: fileDir, + }); - try { - const { stdout } = await execAsync(`which ${firstWord}`); - if (stdout) { - return true; - } - } catch { - } + const cmd = `${alias} ${fileName}`; + simulationTerminal.show(); + simulationTerminal.sendText(cmd); + } - if (firstWord === 'cave') { - const selection = await vscode.window.showWarningMessage( - `"Cave" (default tool) not found. You can download it or set a personal alias.`, - "Download Cave", - "Edit Alias" - ); - if (selection === "Download Cave") { - vscode.env.openExternal(vscode.Uri.parse("https://github.com/simvia-tech/cave")); - } else if (selection === "Edit Alias") { - vscode.commands.executeCommand('workbench.action.openSettings', 'vs-code-aster.aliasForRun'); - } - } else { - const selection = await vscode.window.showWarningMessage( - `The command "${firstWord}" from your alias "${alias}" does not exist on your system.`, - "Edit Alias" - ); - if (selection === "Edit Alias") { - vscode.commands.executeCommand('workbench.action.openSettings', 'vs-code-aster.aliasForRun'); - } - } + /** + * Verify the user's alias and return true if it exists on the system + * */ + private static async checkAlias(alias: string): Promise { + const firstWord = alias.split(' ')[0]; - return false; + try { + const { stdout } = await execAsync(`which ${firstWord}`); + if (stdout) { + return true; + } + } catch {} + + if (firstWord === 'cave') { + const selection = await vscode.window.showWarningMessage( + `"Cave" (default tool) not found. You can download it or set a personal alias.`, + 'Download Cave', + 'Edit Alias' + ); + if (selection === 'Download Cave') { + vscode.env.openExternal(vscode.Uri.parse('https://github.com/simvia-tech/cave')); + } else if (selection === 'Edit Alias') { + vscode.commands.executeCommand( + 'workbench.action.openSettings', + 'vs-code-aster.aliasForRun' + ); + } + } else { + const selection = await vscode.window.showWarningMessage( + `The command "${firstWord}" from your alias "${alias}" does not exist on your system.`, + 'Edit Alias' + ); + if (selection === 'Edit Alias') { + vscode.commands.executeCommand( + 'workbench.action.openSettings', + 'vs-code-aster.aliasForRun' + ); + } } + + return false; + } } diff --git a/src/StatusBar.ts b/src/StatusBar.ts index c9bfa42..d555efe 100644 --- a/src/StatusBar.ts +++ b/src/StatusBar.ts @@ -2,167 +2,177 @@ import * as vscode from 'vscode'; import { LspServer } from './LspServer'; interface CommandFamiliesAnalysis { - mesh: string[]; - material: string[]; - bcAndLoads: string[]; - analysis: string[]; - output: string[]; + mesh: string[]; + material: string[]; + bcAndLoads: string[]; + analysis: string[]; + output: string[]; } type FamilyKey = keyof CommandFamiliesAnalysis; export const COMMAND_FAMILIES: { key: FamilyKey; label: string }[] = [ - { key: 'mesh', label: 'Mesh' }, - { key: 'material', label: 'Material' }, - { key: 'bcAndLoads', label: 'Boundary Conditions & Loads' }, - { key: 'analysis', label: 'Analysis' }, - { key: 'output', label: 'Output' } + { key: 'mesh', label: 'Mesh' }, + { key: 'material', label: 'Material' }, + { key: 'bcAndLoads', label: 'Boundary Conditions & Loads' }, + { key: 'analysis', label: 'Analysis' }, + { key: 'output', label: 'Output' }, ]; export class StatusBar { - private static _instance: StatusBar | null = null; - private statusBarItem: vscode.StatusBarItem; - private currentAnalysis: CommandFamiliesAnalysis | null = null; - private disposables: vscode.Disposable[] = []; - private completeFamilies: CommandFamiliesAnalysis = { - mesh: [], - material: [], - bcAndLoads: [], - analysis: [], - output: [] - }; - - private constructor() { - this.statusBarItem = vscode.window.createStatusBarItem( - vscode.StatusBarAlignment.Left - ); - this.statusBarItem.command = 'codeaster.showCommandFamiliesDetails'; - this.statusBarItem.tooltip = 'Click to see details'; + private static _instance: StatusBar | null = null; + private statusBarItem: vscode.StatusBarItem; + private currentAnalysis: CommandFamiliesAnalysis | null = null; + private disposables: vscode.Disposable[] = []; + private completeFamilies: CommandFamiliesAnalysis = { + mesh: [], + material: [], + bcAndLoads: [], + analysis: [], + output: [], + }; + + private constructor() { + this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + this.statusBarItem.command = 'codeaster.showCommandFamiliesDetails'; + this.statusBarItem.tooltip = 'Click to see details'; + } + + public static get instance(): StatusBar { + if (!StatusBar._instance) { + StatusBar._instance = new StatusBar(); } - - public static get instance(): StatusBar { - if (!StatusBar._instance) { - StatusBar._instance = new StatusBar(); - } - return StatusBar._instance; - } - - /** Activate status bar and register listeners */ - public async activate(context: vscode.ExtensionContext) { - await this.getCompleteFamilies(); - - const showDetailsCommand = vscode.commands.registerCommand( - 'codeaster.showCommandFamiliesDetails', - () => this.showDetails() - ); - context.subscriptions.push(showDetailsCommand); - - const editorChangeListener = vscode.window.onDidChangeActiveTextEditor( - editor => this.onEditorChange(editor) - ); - this.disposables.push(editorChangeListener); - - this.onEditorChange(vscode.window.activeTextEditor); - - context.subscriptions.push(this.statusBarItem, ...this.disposables); + return StatusBar._instance; + } + + /** Activate status bar and register listeners */ + public async activate(context: vscode.ExtensionContext) { + await this.getCompleteFamilies(); + + const showDetailsCommand = vscode.commands.registerCommand( + 'codeaster.showCommandFamiliesDetails', + () => this.showDetails() + ); + context.subscriptions.push(showDetailsCommand); + + const editorChangeListener = vscode.window.onDidChangeActiveTextEditor((editor) => + this.onEditorChange(editor) + ); + this.disposables.push(editorChangeListener); + + this.onEditorChange(vscode.window.activeTextEditor); + + context.subscriptions.push(this.statusBarItem, ...this.disposables); + } + + /** Update status bar visibility and trigger analysis on editor change */ + public async onEditorChange(editor: vscode.TextEditor | undefined) { + if (!editor) { + this.statusBarItem.hide(); + return; } - /** Update status bar visibility and trigger analysis on editor change */ - public async onEditorChange(editor: vscode.TextEditor | undefined) { - if (!editor) { - this.statusBarItem.hide(); - return; - } - - const document = editor.document; - if (document.languageId !== 'comm') { - this.statusBarItem.hide(); - return; - } - - this.statusBarItem.show(); - await this.analyzeDocument(document); + const document = editor.document; + if (document.languageId !== 'comm') { + this.statusBarItem.hide(); + return; } - /** Fetch all command families from the LSP server */ - private async getCompleteFamilies() { - try { - const client = LspServer.instance.client; - if (!client) {return;} - - const completeFamilies = await client.sendRequest( - 'codeaster/getCompleteFamilies', {} - ); - - this.completeFamilies = completeFamilies; - } catch (error) { - console.error('Error fetching command families:', error); - } + this.statusBarItem.show(); + await this.analyzeDocument(document); + } + + /** Fetch all command families from the LSP server */ + private async getCompleteFamilies() { + try { + const client = LspServer.instance.client; + if (!client) { + return; + } + + const completeFamilies = await client.sendRequest( + 'codeaster/getCompleteFamilies', + {} + ); + + this.completeFamilies = completeFamilies; + } catch (error) { + console.error('Error fetching command families:', error); } - - /** Analyze the current document and update status bar */ - private async analyzeDocument(document: vscode.TextDocument) { - try { - const client = LspServer.instance.client; - if (!client) { - this.statusBarItem.hide(); - return; - } - - const analysis = await client.sendRequest( - 'codeaster/analyzeCommandFamilies', - { uri: document.uri.toString() } - ); - - this.currentAnalysis = analysis; - this.updateStatusBarText(analysis); - - } catch (error) { - console.error('Error analyzing command families:', error); - this.statusBarItem.hide(); - } + } + + /** Analyze the current document and update status bar */ + private async analyzeDocument(document: vscode.TextDocument) { + try { + const client = LspServer.instance.client; + if (!client) { + this.statusBarItem.hide(); + return; + } + + const analysis = await client.sendRequest( + 'codeaster/analyzeCommandFamilies', + { uri: document.uri.toString() } + ); + + this.currentAnalysis = analysis; + this.updateStatusBarText(analysis); + } catch (error) { + console.error('Error analyzing command families:', error); + this.statusBarItem.hide(); } - - /** Update the status bar text based on analysis result */ - private updateStatusBarText(analysis: CommandFamiliesAnalysis) { - const completed = Object.values(analysis).filter( - commands => Array.isArray(commands) && commands.length > 0 - ).length; - - const icon = completed === 5 ? '$(check)' : '$(info)'; - this.statusBarItem.text = `${icon} code_aster: ${completed}/5 steps`; + } + + /** Update the status bar text based on analysis result */ + private updateStatusBarText(analysis: CommandFamiliesAnalysis) { + const completed = Object.values(analysis).filter( + (commands) => Array.isArray(commands) && commands.length > 0 + ).length; + + const icon = completed === 5 ? '$(check)' : '$(info)'; + this.statusBarItem.text = `${icon} code_aster: ${completed}/5 steps`; + } + + /** Show a QuickPick with detailed commands for each family */ + private async showDetails() { + if (!this.currentAnalysis) { + return; } - /** Show a QuickPick with detailed commands for each family */ - private async showDetails() { - if (!this.currentAnalysis) {return;} + const analysis = this.currentAnalysis; - const analysis = this.currentAnalysis; + const items = COMMAND_FAMILIES.map((family) => { + const commands = analysis[family.key] || []; + const icon = commands.length > 0 ? '$(check)' : '$(circle-slash)'; + const detail = + commands.length > 0 ? `Commands: ${commands.join(', ')}` : 'No commands defined yet'; + return { label: `${icon} ${family.label}`, detail, key: family.key }; + }); - const items = COMMAND_FAMILIES.map(family => { - const commands = analysis[family.key] || []; - const icon = commands.length > 0 ? '$(check)' : '$(circle-slash)'; - const detail = commands.length > 0 ? `Commands: ${commands.join(', ')}` : 'No commands defined yet'; - return { label: `${icon} ${family.label}`, detail, key: family.key }; - }); + const selectedFamily = await vscode.window.showQuickPick(items, { + placeHolder: 'code_aster command families: select a family to view commands', + }); - const selectedFamily = await vscode.window.showQuickPick(items, { - placeHolder: 'code_aster command families: select a family to view commands' - }); - - if (!selectedFamily) {return;} - - const selectedKey = selectedFamily.key; - const commands = this.completeFamilies[selectedKey] || []; - if (commands.length === 0) {return;} - - const commandItems = commands.map(cmd => ({ label: `$(symbol-method) ${cmd}` })); - await vscode.window.showQuickPick(commandItems, { placeHolder: `${selectedFamily.key} commands`, canPickMany: false }); + if (!selectedFamily) { + return; } - /** Dispose status bar and listeners */ - public dispose() { - this.statusBarItem.dispose(); - this.disposables.forEach(d => d.dispose()); + const selectedKey = selectedFamily.key; + const commands = this.completeFamilies[selectedKey] || []; + if (commands.length === 0) { + return; } + + const commandItems = commands.map((cmd) => ({ label: `$(symbol-method) ${cmd}` })); + await vscode.window.showQuickPick(commandItems, { + placeHolder: `${selectedFamily.key} commands`, + canPickMany: false, + }); + } + + /** Dispose status bar and listeners */ + public dispose() { + this.statusBarItem.dispose(); + this.disposables.forEach((d) => d.dispose()); + } } diff --git a/src/VisuManager.ts b/src/VisuManager.ts index f87de08..f0dd0aa 100644 --- a/src/VisuManager.ts +++ b/src/VisuManager.ts @@ -1,27 +1,27 @@ -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; -import { spawn } from "child_process"; -import { sendTelemetry, TelemetryType } from "./telemetry"; -import { WebviewVisu } from "./WebviewVisu"; -import { TextDecoder } from "util"; +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; +import { spawn } from 'child_process'; +import { sendTelemetry, TelemetryType } from './telemetry'; +import { WebviewVisu } from './WebviewVisu'; +import { TextDecoder } from 'util'; /** * List of supported Code Aster command file extensions. */ export const SUPPORTED_COMM_EXTENSIONS = [ - ".comm", - ".com", - ".com0", - ".com1", - ".com2", - ".com3", - ".com4", - ".com5", - ".com6", - ".com7", - ".com8", - ".com9", + '.comm', + '.com', + '.com0', + '.com1', + '.com2', + '.com3', + '.com4', + '.com5', + '.com6', + '.com7', + '.com8', + '.com9', ]; /** @@ -31,15 +31,13 @@ export const SUPPORTED_COMM_EXTENSIONS = [ * @returns True if the file has a valid comm extension, false otherwise */ function isCommFile(filePath: string): boolean { - const config = vscode.workspace.getConfiguration("vs-code-aster"); + const config = vscode.workspace.getConfiguration('vs-code-aster'); const configuredExtensions = config.get( - "commFileExtensions", - SUPPORTED_COMM_EXTENSIONS, + 'commFileExtensions', + SUPPORTED_COMM_EXTENSIONS ); const ext = path.extname(filePath).toLowerCase(); - return configuredExtensions.some( - (extConfig) => extConfig.toLowerCase() === ext, - ); + return configuredExtensions.some((extConfig) => extConfig.toLowerCase() === ext); } /** @@ -83,14 +81,12 @@ export class VisuManager { const editor = vscode.window.activeTextEditor; if (!editor) { - vscode.window.showWarningMessage("No active editor."); + vscode.window.showWarningMessage('No active editor.'); return; } const filePath = editor.document.uri.fsPath; if (!isCommFile(filePath)) { - vscode.window.showWarningMessage( - "The active file is not a Code Aster command file.", - ); + vscode.window.showWarningMessage('The active file is not a Code Aster command file.'); return; } @@ -118,14 +114,18 @@ export class VisuManager { const fileContexts = await readObjFilesContent(objUris); - const testDir = path.resolve(__dirname, ".."); + const testDir = path.resolve(__dirname, '..'); + + const commName = path.basename(commUri.fsPath, path.extname(commUri.fsPath)); const visu = new WebviewVisu( - "meshViewer", + 'meshViewer', testDir, - "resources/visu_vtk/index.html", + 'webviews/viewer/dist/index.html', fileContexts, objUris.map((uri) => path.basename(uri.fsPath)), + undefined, + commName ); this.views.set(key, { commUri, objUris, visu }); @@ -144,6 +144,21 @@ export class VisuManager { } public listenCommFiles() { + vscode.window.onDidChangeActiveTextEditor((editor) => { + if (!editor) { + return; + } + const filePath = editor.document.uri.fsPath; + if (!isCommFile(filePath)) { + return; + } + const entry = this.getViewer(editor.document.uri); + if (!entry || entry.visu.panel.active) { + return; + } + entry.visu.panel.reveal(undefined, true); + }); + vscode.window.onDidChangeTextEditorSelection((event) => { const editor = event.textEditor; const filePath = editor.document.uri.fsPath; @@ -154,9 +169,7 @@ export class VisuManager { const commUri = editor.document.uri; const firstSelection = editor.selections.find((sel) => !sel.isEmpty); - const selectedText = firstSelection - ? editor.document.getText(firstSelection) - : ""; + const selectedText = firstSelection ? editor.document.getText(firstSelection) : ''; const entry = this.getViewer(commUri); if (!entry) { return; @@ -170,10 +183,8 @@ export class VisuManager { * Reads the contents of all .obj files and returns them as a string array. * @param objUris Array of vscode.Uri for .obj files */ -export async function readObjFilesContent( - objUris: vscode.Uri[], -): Promise { - const decoder = new TextDecoder("utf-8"); +export async function readObjFilesContent(objUris: vscode.Uri[]): Promise { + const decoder = new TextDecoder('utf-8'); const contexts: string[] = []; for (const uri of objUris) { try { @@ -197,14 +208,10 @@ export function findMedFiles(commFilePath: string): string[] { try { const dir = path.dirname(commFilePath); const commFileName = path.basename(commFilePath); - const exportFiles = fs - .readdirSync(dir) - .filter((f) => f.endsWith(".export")); + const exportFiles = fs.readdirSync(dir).filter((f) => f.endsWith('.export')); if (exportFiles.length === 0) { - vscode.window.showErrorMessage( - `No .export file found in directory: ${dir}`, - ); + vscode.window.showErrorMessage(`No .export file found in directory: ${dir}`); return []; } @@ -212,7 +219,7 @@ export function findMedFiles(commFilePath: string): string[] { for (const exportFile of exportFiles) { const exportPath = path.join(dir, exportFile); - const content = fs.readFileSync(exportPath, "utf8"); + const content = fs.readFileSync(exportPath, 'utf8'); if (!content.includes(commFileName)) { continue; @@ -220,16 +227,16 @@ export function findMedFiles(commFilePath: string): string[] { const lines = content.split(/\r?\n/); for (const line of lines) { - const cleanLine = line.split("#")[0].trim(); + const cleanLine = line.split('#')[0].trim(); const tokens = cleanLine.split(/\s+/); - if (tokens.length !== 5 || tokens[0] !== "F") { + if (tokens.length !== 5 || tokens[0] !== 'F') { continue; } const [, type, name, ioFlag] = tokens; - if (!type.endsWith("med") || ioFlag !== "D") { + if (!type.endsWith('med') || ioFlag !== 'D') { continue; } @@ -241,7 +248,7 @@ export function findMedFiles(commFilePath: string): string[] { foundMedFiles.push(medPath); } else { vscode.window.showErrorMessage( - `The file "${medFileName}" mentioned in "${exportFile}" does not exist in the current directory (${path.basename(dir)}/).`, + `The file "${medFileName}" mentioned in "${exportFile}" does not exist in the current directory (${path.basename(dir)}/).` ); } } @@ -249,14 +256,14 @@ export function findMedFiles(commFilePath: string): string[] { if (foundMedFiles.length === 0) { vscode.window.showErrorMessage( - `No .export file in "${path.basename(dir)}/" references any input med file associated with ${commFileName}.`, + `No .export file in "${path.basename(dir)}/" references any input med file associated with ${commFileName}.` ); } return foundMedFiles; } catch (err) { vscode.window.showErrorMessage( - `Error while searching for .med file: ${(err as Error).message}`, + `Error while searching for .med file: ${(err as Error).message}` ); return []; } @@ -274,7 +281,7 @@ export async function getObjFiles(medFiles: string[]): Promise { const mmedDir = path.dirname(mmedFilePath); const ext = path.extname(mmedFilePath); const mmedBase = path.basename(mmedFilePath, ext); - const visuDataDir = path.join(mmedDir, ".visu_data"); + const visuDataDir = path.join(mmedDir, '.visu_data'); if (!fs.existsSync(visuDataDir)) { fs.mkdirSync(visuDataDir, { recursive: true }); console.log(`[getObjFiles] Created directory: ${visuDataDir}`); @@ -285,9 +292,7 @@ export async function getObjFiles(medFiles: string[]): Promise { const objStat = fs.statSync(objFilePath); if (objStat.mtime < mmedStat.mtime) { vscode.window.showInformationMessage( - `.obj file is outdated and being regenerated: ${path.basename( - objFilePath, - )}`, + `.obj file is outdated and being regenerated: ${path.basename(objFilePath)}` ); console.log(`[getObjFiles] .obj file is outdated: ${objFilePath}`); await generateObjFromMed(mmedFilePath, objFilePath); @@ -297,7 +302,7 @@ export async function getObjFiles(medFiles: string[]): Promise { } else { console.log(`[getObjFiles] .obj file not found for ${mmedBase}.`); vscode.window.showInformationMessage( - `Creating .obj file for: ${path.basename(mmedFilePath)}`, + `Creating .obj file for: ${path.basename(mmedFilePath)}` ); await generateObjFromMed(mmedFilePath, objFilePath); if (fs.existsSync(objFilePath)) { @@ -310,11 +315,11 @@ export async function getObjFiles(medFiles: string[]): Promise { if (msg.includes("No module named 'medcoupling'")) { vscode.window.showErrorMessage( "Python module 'medcoupling' is not installed. " + - "Please install it by running `pip install medcoupling` in your Python environment, then retry.", + 'Please install it by running `pip install medcoupling` in your Python environment, then retry.' ); } else { vscode.window.showErrorMessage( - `Error while searching for .obj file: ${(err as Error).message}`, + `Error while searching for .obj file: ${(err as Error).message}` ); } } @@ -327,67 +332,59 @@ export async function getObjFiles(medFiles: string[]): Promise { * @param medFilePath Path to the input .med file * @param objFilePath Path to the output .obj file */ -async function generateObjFromMed( - medFilePath: string, - objFilePath: string, -): Promise { +async function generateObjFromMed(medFilePath: string, objFilePath: string): Promise { return new Promise((resolve, reject) => { // Locate med2obj.py script - assumed to be in python/asterstudy/post or similar - const scriptPath = path.join(__dirname, "..", "python", "med2obj.py"); + const scriptPath = path.join(__dirname, '..', 'python', 'med2obj.py'); console.log( - `[generateObjFromMed] Executing: python ${scriptPath} ${medFilePath} ${objFilePath}`, + `[generateObjFromMed] Executing: python ${scriptPath} ${medFilePath} ${objFilePath}` ); - const config = vscode.workspace.getConfiguration("vs-code-aster"); - const pythonExecutablePath = config.get( - "pythonExecutablePath", - "python3", - ); + const config = vscode.workspace.getConfiguration('vs-code-aster'); + const pythonExecutablePath = config.get('pythonExecutablePath', 'python3'); const process = spawn( pythonExecutablePath, - [scriptPath, "-i", medFilePath, "-o", objFilePath], + [scriptPath, '-i', medFilePath, '-o', objFilePath], { cwd: path.dirname(medFilePath), - }, + } ); - let stderr = ""; + let stderr = ''; let settled = false; - process.stderr.on("data", (data) => { + process.stderr.on('data', (data) => { stderr += data.toString(); console.log(`[generateObjFromMed] stderr: ${data}`); }); - process.on("error", (err: NodeJS.ErrnoException) => { + process.on('error', (err: NodeJS.ErrnoException) => { if (settled) { return; } settled = true; console.error(`[generateObjFromMed] Process error: ${err.message}`); - if (err.code === "ENOENT") { + if (err.code === 'ENOENT') { reject( new Error( `Python executable not found: "${pythonExecutablePath}". ` + - `Please update the "vs-code-aster.pythonExecutablePath" setting.`, - ), + `Please update the "vs-code-aster.pythonExecutablePath" setting.` + ) ); } else { reject(new Error(`Failed to generate .obj file: ${err.message}`)); } }); - process.on("close", (code) => { + process.on('close', (code) => { if (settled) { return; } settled = true; if (code === 0) { - console.log( - `[generateObjFromMed] Successfully generated: ${objFilePath}`, - ); + console.log(`[generateObjFromMed] Successfully generated: ${objFilePath}`); resolve(); } else { const errorMsg = `med2obj.py exited with code ${code}. ${stderr}`; diff --git a/src/WebviewVisu.ts b/src/WebviewVisu.ts index 32522b7..5ca0789 100644 --- a/src/WebviewVisu.ts +++ b/src/WebviewVisu.ts @@ -1,6 +1,6 @@ -import * as vscode from "vscode"; -import * as path from "path"; -import * as fs from "fs"; +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; /** * Provides basic dialog semantics over a VS Code webview panel for mesh visualization. @@ -38,7 +38,8 @@ export class WebviewVisu implements vscode.Disposable { htmlFileName: string, fileContexts: string[], objFilenames: string[], - viewColumn?: vscode.ViewColumn + viewColumn?: vscode.ViewColumn, + title?: string ) { viewColumn = viewColumn || vscode.ViewColumn.Beside; @@ -52,26 +53,24 @@ export class WebviewVisu implements vscode.Disposable { // Get HTML file path const htmlFilePath = path.join(resourceRootDir, htmlFileName); - // Extract title from HTML file - let htmlFileContent = fs.readFileSync(htmlFilePath, { encoding: "utf8" }); - const title = this.extractHtmlTitle(htmlFileContent, "Visualizer"); + // Use provided title or fall back to the HTML tag + if (!title) { + const htmlFileContent = fs.readFileSync(htmlFilePath, { encoding: 'utf8' }); + title = this.extractHtmlTitle(htmlFileContent, 'Visualizer'); + } // Create webview panel with icon - this.panel = vscode.window.createWebviewPanel( - viewType, - title, - viewColumn, - options - ); - this.panel.iconPath = vscode.Uri.file( - path.join(resourceRootDir, "resources", "icons", "3d.svg") - ); - console.log("[WebviewVisu] Webview panel created"); + this.panel = vscode.window.createWebviewPanel(viewType, title, viewColumn, options); + this.panel.iconPath = { + light: vscode.Uri.file(path.join(resourceRootDir, 'media', 'icons', '3d.svg')), + dark: vscode.Uri.file(path.join(resourceRootDir, 'media', 'icons', '3d_light.svg')), + }; + console.log('[WebviewVisu] Webview panel created'); // Set HTML content for the webview const html = this.preprocessWebviewHtml(this.panel, htmlFilePath); this.panel.webview.html = html; - console.log("[WebviewVisu] HTML content set in webview"); + console.log('[WebviewVisu] HTML content set in webview'); // Initialize selectedGroups this.selectedGroups = []; @@ -79,43 +78,65 @@ export class WebviewVisu implements vscode.Disposable { // Listen for messages from the webview this.panel.webview.onDidReceiveMessage((e) => { switch (e.type) { - case "ready": + case 'ready': // Webview is ready, send initialization message - console.log("[WebviewVisu] Webview ready signal received"); + console.log('[WebviewVisu] Webview ready signal received'); if (objFilenames) { - console.log("[WebviewVisu] Sending init with files:", objFilenames); + console.log('[WebviewVisu] Sending init with files:', objFilenames); + const config = vscode.workspace.getConfiguration('vs-code-aster'); + const settings = { + hiddenObjectOpacity: config.get<number>('viewer.hiddenObjectOpacity', 0), + edgeMode: config.get<string>('viewer.edgeMode', 'threshold'), + groupTransparency: config.get<number>('viewer.groupTransparency', 0.2), + showOrientationWidget: config.get<boolean>('viewer.showOrientationWidget', true), + }; this.panel.webview.postMessage({ - type: "init", - body: { fileContexts, objFilenames }, + type: 'init', + body: { fileContexts, objFilenames, settings }, }); } break; - case "debugPanel": + case 'saveSettings': + // Persist viewer settings back to VS Code configuration + const cfg = vscode.workspace.getConfiguration('vs-code-aster'); + const settingKeys = [ + 'hiddenObjectOpacity', + 'edgeMode', + 'groupTransparency', + 'showOrientationWidget', + ]; + for (const key of settingKeys) { + if (e.settings[key] !== undefined) { + cfg.update(`viewer.${key}`, e.settings[key], vscode.ConfigurationTarget.Global); + } + } + break; + case 'debugPanel': // Log debug messages from the webview - console.log("[WebviewVisu] Message received from webview:", e.text); + console.log('[WebviewVisu] Message received from webview:', e.text); break; - case "groups": + case 'groups': // Receive the list of groups from the webview and store it let groupList = e.groupList; - console.log("Group list : ", groupList); + console.log('Group list : ', groupList); this.groups = groupList; this.panel.webview.postMessage({ - type: "addGroupButtons", + type: 'addGroupButtons', body: { groupList }, }); break; default: - console.warn("[WebviewVisu] Unknown message type:", e.type); + console.warn('[WebviewVisu] Unknown message type:', e.type); } }); // Dispose the webview panel when it is closed this.panel.onDidDispose(() => { - console.log("[WebviewVisu] Webview panel disposed"); + console.log('[WebviewVisu] Webview panel disposed'); this.dispose(); }, null); - console.log("[WebviewVisu] Constructor finished"); + console.log('[WebviewVisu] Constructor finished'); } /** @@ -129,20 +150,20 @@ export class WebviewVisu implements vscode.Disposable { } // Parse the text to find group names + // Group keys are like "all_mesh.obj::SURFACE_1::type"; match against the short name only const readGroups = this.groups?.filter((groupName) => { - const regex = new RegExp( - `\\b${groupName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b` - ); + const shortName = groupName.includes('::') ? groupName.split('::')[2]! : groupName; + const regex = new RegExp(`\\b${shortName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`); return regex.test(text); }) || []; // Hide groups that are no longer in the text this.selectedGroups = this.selectedGroups.filter((oldGroup) => { if (!readGroups.includes(oldGroup)) { - console.log("Hide group:", oldGroup); + console.log('Hide group:', oldGroup); this.panel.webview.postMessage({ - type: "displayGroup", + type: 'displayGroup', body: { group: oldGroup, visible: false }, }); return false; @@ -153,9 +174,9 @@ export class WebviewVisu implements vscode.Disposable { // Show groups that are new to the text readGroups.forEach((group) => { if (!this.selectedGroups.includes(group)) { - console.log("Display group:", group); + console.log('Display group:', group); this.panel.webview.postMessage({ - type: "displayGroup", + type: 'displayGroup', body: { group, visible: true }, }); this.selectedGroups.push(group); @@ -179,25 +200,17 @@ export class WebviewVisu implements vscode.Disposable { * @param htmlFilePath The path to the HTML file. * @returns The preprocessed HTML content as a string. */ - private preprocessWebviewHtml( - panel: vscode.WebviewPanel, - htmlFilePath: string - ): string { - let html = fs.readFileSync(htmlFilePath, { encoding: "utf8" }); + private preprocessWebviewHtml(panel: vscode.WebviewPanel, htmlFilePath: string): string { + let html = fs.readFileSync(htmlFilePath, { encoding: 'utf8' }); const htmlDir = path.dirname(htmlFilePath); // Replace relative paths (href/src/img) with valid URIs for the webview - html = html.replace( - /(<link.+?href="|<script.+?src="|<img.+?src=")(.+?)"/g, - (match, p1, p2) => { - const resourceFullPath = path.join(htmlDir, p2); - const uri = panel.webview.asWebviewUri( - vscode.Uri.file(resourceFullPath) - ); - return `${p1}${uri.toString()}"`; - } - ); + html = html.replace(/(<link.+?href="|<script.+?src="|<img.+?src=")(.+?)"/g, (match, p1, p2) => { + const resourceFullPath = path.join(htmlDir, p2); + const uri = panel.webview.asWebviewUri(vscode.Uri.file(resourceFullPath)); + return `${p1}${uri.toString()}"`; + }); html = html.replace(/\${webview.cspSource}/g, panel.webview.cspSource); diff --git a/src/extension.ts b/src/extension.ts index 7ff276d..15f77bd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,42 +11,40 @@ import { LspServer } from './LspServer'; import { StatusBar } from './StatusBar'; import { setTelemetryContext } from './telemetry'; - /** * Main activation function for the extension. Registers all commands. * * @param context The VS Code extension context. */ export async function activate(context: vscode.ExtensionContext) { - - // Set up telemetry context - setTelemetryContext(context); - - const runaster = vscode.commands.registerCommand('vs-code-aster.run-aster', () => { - RunAster.runCodeAster(); - }); - - const createExportDoc = vscode.commands.registerCommand('vs-code-aster.exportDoc', () => { - ExportEditor.initExportEditor(); - }); - - const createMesh = vscode.commands.registerCommand('vs-code-aster.meshViewer', () => { - VisuManager.instance.createOrShowMeshViewer(); - }); - - await LspServer.instance.start(context); - const lspServer = vscode.commands.registerCommand('vs-code-aster.restartLSPServer', async () => { - LspServer.instance.restart(); - }); - - StatusBar.instance.activate(context); - - context.subscriptions.push(runaster); - context.subscriptions.push(createExportDoc); - context.subscriptions.push(createMesh); - context.subscriptions.push(lspServer); + // Set up telemetry context + setTelemetryContext(context); + + const runaster = vscode.commands.registerCommand('vs-code-aster.run-aster', () => { + RunAster.runCodeAster(); + }); + + const createExportDoc = vscode.commands.registerCommand('vs-code-aster.exportDoc', () => { + ExportEditor.initExportEditor(); + }); + + const createMesh = vscode.commands.registerCommand('vs-code-aster.meshViewer', () => { + VisuManager.instance.createOrShowMeshViewer(); + }); + + await LspServer.instance.start(context); + const lspServer = vscode.commands.registerCommand('vs-code-aster.restartLSPServer', async () => { + LspServer.instance.restart(); + }); + + StatusBar.instance.activate(context); + + context.subscriptions.push(runaster); + context.subscriptions.push(createExportDoc); + context.subscriptions.push(createMesh); + context.subscriptions.push(lspServer); } export function deactivate(): Thenable<void> | undefined { - return LspServer.instance.deactivate(); -} \ No newline at end of file + return LspServer.instance.deactivate(); +} diff --git a/src/telemetry.ts b/src/telemetry.ts index fc710bd..a8229c4 100644 --- a/src/telemetry.ts +++ b/src/telemetry.ts @@ -1,5 +1,5 @@ -import * as vscode from "vscode"; -import * as utils from "./utils"; +import * as vscode from 'vscode'; +import * as utils from './utils'; /** * Telemetry event types @@ -25,9 +25,8 @@ interface TelemetryData { /** * Default telemetry server URL */ -const TELEMETRY_SERVER_URL = - "https://7a98391a395292bd9f0f.lambda.simvia-app.fr/"; -const TELEMETRY_USER_ID_KEY = "telemetryUserId"; +const TELEMETRY_SERVER_URL = 'https://7a98391a395292bd9f0f.lambda.simvia-app.fr/'; +const TELEMETRY_USER_ID_KEY = 'telemetryUserId'; /** * Global extension context for telemetry @@ -70,13 +69,11 @@ export async function getOrCreateUserTelemetryID( export async function sendTelemetry(type: TelemetryType): Promise<void> { try { // Check if telemetry is enabled - const config = vscode.workspace.getConfiguration("vs-code-aster"); - const isTelemetryEnabled = config.get<boolean>("enableTelemetry", true); + const config = vscode.workspace.getConfiguration('vs-code-aster'); + const isTelemetryEnabled = config.get<boolean>('enableTelemetry', true); if (!isTelemetryEnabled) { - console.log( - `[telemetry] Skipped event (telemetry disabled): ${TelemetryType[type]}` - ); + console.log(`[telemetry] Skipped event (telemetry disabled): ${TelemetryType[type]}`); return; } diff --git a/src/utils.ts b/src/utils.ts index 3b7124b..97b8e9d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,6 @@ -import * as path from "path"; -import * as fs from "fs"; -import * as vscode from "vscode"; +import * as path from 'path'; +import * as fs from 'fs'; +import * as vscode from 'vscode'; /** * Utility functions for the VS Code Aster extension. @@ -12,81 +12,79 @@ import * as vscode from "vscode"; * Generates a v4 UUID for unique identification. * Uses dynamic import to support the ESM-only `uuid` package in a CommonJS module. * Falls back to a default UUID string if the uuid package fails to load. - * + * * @returns A promise that resolves to a v4 UUID string */ export async function generateUuid(): Promise<string> { try { - const mod = (await import("uuid")) as any; + const mod = (await import('uuid')) as any; const v4 = mod.v4 ?? mod.default?.v4 ?? mod.default ?? mod; - if (typeof v4 === "function") { + if (typeof v4 === 'function') { return v4(); } - throw new Error("uuid.v4 is not a function"); + throw new Error('uuid.v4 is not a function'); } catch (err) { console.log( `[telemetry] Failed to load uuid dynamically: ${ err instanceof Error ? err.message : String(err) }` ); - return "00000000-0000-0000-0000-000000000000"; + return '00000000-0000-0000-0000-000000000000'; } } /** * Gets the current timezone offset as a formatted string. * Returns the offset in the format ±HH:MM (e.g., "+02:00" or "-05:30"). - * + * * @returns Formatted timezone offset string */ export function getTimezoneOffsetString(): string { const offset = new Date().getTimezoneOffset(); - const sign = offset <= 0 ? "+" : "-"; + const sign = offset <= 0 ? '+' : '-'; const absMin = Math.abs(offset); const hours = Math.floor(absMin / 60) .toString() - .padStart(2, "0"); - const minutes = (absMin % 60).toString().padStart(2, "0"); + .padStart(2, '0'); + const minutes = (absMin % 60).toString().padStart(2, '0'); return `${sign}${hours}:${minutes}`; } /** * Retrieves the extension package version from package.json. * Falls back to "0.0.0" if the package.json file cannot be read or parsed. - * + * * @returns The extension version string or "0.0.0" if unavailable */ export function getPackageVersion(): string { try { - const pkgPath = path.resolve(__dirname, "..", "package.json"); + const pkgPath = path.resolve(__dirname, '..', 'package.json'); if (!fs.existsSync(pkgPath)) { - return "0.0.0"; + return '0.0.0'; } - const raw = fs.readFileSync(pkgPath, { encoding: "utf8" }); + const raw = fs.readFileSync(pkgPath, { encoding: 'utf8' }); const parsed = JSON.parse(raw); - return typeof parsed.version === "string" && parsed.version.length - ? parsed.version - : "0.0.0"; + return typeof parsed.version === 'string' && parsed.version.length ? parsed.version : '0.0.0'; } catch (e) { - return "0.0.0"; + return '0.0.0'; } } /** * Gets the VS Code version information for telemetry purposes. * Returns the VS Code application name and version in the format "app/version". - * + * * @returns A promise that resolves to the version string or "unknown" if unavailable */ export async function getVSCodeVersion(): Promise<string> { try { // Prefer the IDE/app name if available, otherwise fall back to 'vscode' - const appName = ((vscode.env as any).appName as string) || "vscode"; - const version = vscode.version || "unknown"; - const safeApp = appName.replace(/\s+/g, "_"); + const appName = ((vscode.env as any).appName as string) || 'vscode'; + const version = vscode.version || 'unknown'; + const safeApp = appName.replace(/\s+/g, '_'); return `${safeApp}/${version}`; } catch (err) { - return "unknown"; + return 'unknown'; } } @@ -94,7 +92,7 @@ export async function getVSCodeVersion(): Promise<string> { * Sends a JSON POST request with a timeout. * Automatically aborts the request if it exceeds the specified timeout. * Used primarily for sending telemetry data to the server. - * + * * @param urlStr The URL to send the request to * @param obj The data object to send as JSON * @param timeoutMs Request timeout in milliseconds (default: 3000) @@ -109,8 +107,8 @@ export async function sendJsonRequestWithTimeout( const id = setTimeout(() => controller.abort(), timeoutMs); try { await fetch(urlStr, { - method: "POST", - headers: { "Content-Type": "application/json" }, + method: 'POST', + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(obj), signal: controller.signal, }); @@ -118,4 +116,3 @@ export async function sendJsonRequestWithTimeout( clearTimeout(id); } } - diff --git a/tsconfig.json b/tsconfig.json index e004a91..f39381d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,13 @@ { - "compilerOptions": { - "rootDir": "src", - "types": ["@types/node"], - "module": "Node16", - "target": "ES2022", - "lib": [ - "ES2022" - ], - "sourceMap": true, - "strict": true, - "skipLibCheck": true - } + "compilerOptions": { + "rootDir": "src", + "types": ["@types/node"], + "module": "Node16", + "target": "ES2022", + "lib": ["ES2022"], + "sourceMap": true, + "strict": true, + "skipLibCheck": true + }, + "include": ["src/**/*"] } - - - diff --git a/webviews/export/export.css b/webviews/export/export.css new file mode 100644 index 0000000..bda9324 --- /dev/null +++ b/webviews/export/export.css @@ -0,0 +1,162 @@ +body { + margin: 32px auto; + max-width: 600px; + font-family: 'Segoe UI', 'Roboto', Arial, sans-serif; + color: #222; + background: linear-gradient(135deg, #f6fafd 0%, #e9f0f7 100%); + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06); + border-radius: 12px; + padding: 32px 40px 40px 40px; +} + +h2, +h3 { + color: #174a6e; + margin-bottom: 0.5em; + letter-spacing: 0.01em; +} + +h3 { + font-size: 1.1em; + font-weight: 600; + margin-top: 1.5em; +} + +div.field { + margin-top: 1em; + margin-bottom: 1em; + clear: both; + padding: 0.7em 0.5em; + display: flex; + align-items: center; + background: rgba(255, 255, 255, 0.8); + border-radius: 6px; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.02); + transition: background 0.2s; +} + +div.label { + width: 10em; + margin-right: 1em; + font-weight: 600; + color: #246; + letter-spacing: 0.01em; +} + +div.field select, +div.field input { + flex: 1; + min-width: 0; + padding: 0.5em 0.8em; + border: 1px solid #bcd2e6; + border-radius: 4px; + font-size: 1em; + background-color: #fafdff; + transition: + border 0.2s, + box-shadow 0.2s; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03); +} + +div.field input { + width: 100%; +} + +div.file-row > * { + margin-right: 12px; +} + +div.file-row > *:last-child { + margin-right: 0; +} + +div.field select:focus, +div.field input:focus { + border-color: #007acc; + box-shadow: 0 0 0 2px #b3e1ff; + outline: none; + background: #f2faff; +} + +div.submit { + margin-top: 2.5em; + clear: both; + text-align: right; +} + +div.submit button { + margin-left: 0.5em; + padding: 0.6em 1.4em; + font-size: 1.08em; + border: none; + border-radius: 5px; + cursor: pointer; + background: linear-gradient(90deg, #007acc 70%, #005f99 100%); + color: white; + font-weight: 600; + letter-spacing: 0.02em; + box-shadow: 0 2px 8px rgba(0, 122, 204, 0.07); + transition: + background 0.2s, + transform 0.1s; +} + +div.submit button:hover, +div.submit button:focus { + background: linear-gradient(90deg, #005f99 60%, #007acc 100%); + transform: translateY(-1px) scale(1.04); +} + +div.suggestion-box { + position: absolute; + left: 0; + min-width: 100%; + background: #fff; + border: 1px solid #bcd2e6; + border-radius: 4px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09); + z-index: 10; +} + +div.highlighted-suggestion { + background-color: #e0f0ff; + font-weight: bold; + border-left: 3px solid #007acc; +} + +div.field input.input-warning { + border: 1.5px solid #d45858 !important; + background-color: #faecec !important; +} + +div.logo-container { + position: absolute; + top: 34px; + right: 36px; + display: flex; + gap: 18px; + align-items: center; + z-index: 10; + max-width: 220px; + max-height: 60px; + overflow: hidden; +} + +img.logo-img { + max-height: 54px; + max-width: 90px; + height: auto; + width: auto; + object-fit: contain; + display: block; + filter: drop-shadow(0 2px 8px rgba(0, 0, 0, 0.07)); + transition: filter 0.2s; +} + +img.logo-img:hover { + filter: drop-shadow(0 4px 12px #007acc33); +} + +#submitCreate { + font-weight: bold; +} diff --git a/webviews/export/export.html b/webviews/export/export.html new file mode 100644 index 0000000..e43ca20 --- /dev/null +++ b/webviews/export/export.html @@ -0,0 +1,92 @@ +<!doctype html> +<html lang="en"> + <head> + <title>Export File Creation + + + + + + + + +
+ Logo 1 + Logo 2 +
+ +

Export File Creation

+ +
+
File name:
+ +
+ +
+
Time Limit:
+ +
+
+ +
+
Memory Limit:
+ +
+
+ +
+
NCPUs:
+ +
+
+ +
+
MPI NBCPU:
+ +
+
+ +
+
MPI NBNOEUD:
+ +
+
+ +

For each file, fill in the format, name, and unite value.

+ +

+ Input Files + + +

+ +
+ +

+ +

+ Output Files + + +

+ +
+ +

+ +
+ + +
+ + + + diff --git a/resources/export_form/export.js b/webviews/export/export.js similarity index 67% rename from resources/export_form/export.js rename to webviews/export/export.js index c9b2d1a..80a1953 100644 --- a/resources/export_form/export.js +++ b/webviews/export/export.js @@ -3,80 +3,121 @@ let nameText, createButton, cancelButton; let timeLimit, memoryLimit, ncpus, mpiNbcpu, mpiNbnoeud; let lastActiveInput = null; -const allowedTypes = ['nom', 'comm', 'med', 'msh', 'datg', 'dat', 'rmed', 'mmed', 'base','mess', 'libr']; +const allowedTypes = [ + 'nom', + 'comm', + 'med', + 'msh', + 'datg', + 'dat', + 'rmed', + 'mmed', + 'base', + 'mess', + 'libr', +]; const defaultUnits = { - nom: '0', comm: '1', med: '20', msh: '19', datg: '16', dat: '29', - rmed: '80', base: '0', mess: '6', mmed: '20', libr : '16' + nom: '0', + comm: '1', + med: '20', + msh: '19', + datg: '16', + dat: '29', + rmed: '80', + base: '0', + mess: '6', + mmed: '20', + libr: '16', }; const formData = { - name: '', - parameters: { time_limit: '300', memory_limit: '1024', ncpus: '1', mpi_nbcpu: '4', mpi_nbnoeud: '1' }, - inputFiles: [], - outputFiles: [] + name: '', + parameters: { + time_limit: '300', + memory_limit: '1024', + ncpus: '1', + mpi_nbcpu: '4', + mpi_nbnoeud: '1', + }, + inputFiles: [], + outputFiles: [], }; let existingFiles = []; - // Initialize form and attach event listeners window.addEventListener('load', () => { - try { - vscode = acquireVsCodeApi(); - } catch (e) { - console.error(e.message); - } - - // Create initial input/output file rows - modifyFileRows(true, true); - modifyFileRows(true, true); - modifyFileRows(true, false); - formData.name = "simvia.export"; - - // DOM elements - nameText = document.getElementById('envName'); - createButton = document.getElementById('boutonCreation'); - cancelButton = document.getElementById('boutonAnnulation'); - addOutputFileButton = document.getElementById('addOutputFile'); - addInputFileButton = document.getElementById('addInputFile'); - removeOutputFileButton = document.getElementById('removeOutputFile'); - removeInputFileButton = document.getElementById('removeInputFile'); - timeLimit = document.getElementById('time_limit'); - memoryLimit = document.getElementById('memory_limit'); - ncpus = document.getElementById('ncpus'); - mpiNbcpu = document.getElementById('mpi_nbcpu'); - mpiNbnoeud = document.getElementById('mpi_nbnoeud'); - - - nameText.addEventListener('keyup', validate); - nameText.addEventListener('change', validate); - validate(); - - createButton.addEventListener('click', submitCreate); - cancelButton.addEventListener('click', submitCancel); - - addOutputFileButton.addEventListener('click', () => modifyFileRows(true, false)); - addInputFileButton.addEventListener('click', () => modifyFileRows(true, true)); - removeOutputFileButton.addEventListener('click', () => modifyFileRows(false, false)); - removeInputFileButton.addEventListener('click', () => modifyFileRows(false, true)); - - // Update form data on input changes - nameText.addEventListener('input', () => { formData.name = nameText.value.trim(); }); - timeLimit.addEventListener('input', () => { formData.parameters.time_limit = timeLimit.value.trim(); verifyValueInput(timeLimit, formData.parameters.time_limit); }); - memoryLimit.addEventListener('input', () => { formData.parameters.memory_limit = memoryLimit.value.trim(); verifyValueInput(memoryLimit, formData.parameters.memory_limit); }); - ncpus.addEventListener('input', () => { formData.parameters.ncpus = ncpus.value.trim(); verifyValueInput(ncpus, formData.parameters.ncpus); }); - mpiNbcpu.addEventListener('input', () => { formData.parameters.mpi_nbcpu = mpiNbcpu.value.trim(); verifyValueInput(mpiNbcpu, formData.parameters.mpi_nbcpu); }); - mpiNbnoeud.addEventListener('input', () => { formData.parameters.mpi_nbnoeud = mpiNbnoeud.value.trim(); verifyValueInput(mpiNbnoeud, formData.parameters.mpi_nbnoeud); }); + try { + vscode = acquireVsCodeApi(); + } catch (e) { + console.error(e.message); + } + + // Create initial input/output file rows + modifyFileRows(true, true); + modifyFileRows(true, true); + modifyFileRows(true, false); + formData.name = 'simvia.export'; + + // DOM elements + nameText = document.getElementById('envName'); + createButton = document.getElementById('boutonCreation'); + cancelButton = document.getElementById('boutonAnnulation'); + addOutputFileButton = document.getElementById('addOutputFile'); + addInputFileButton = document.getElementById('addInputFile'); + removeOutputFileButton = document.getElementById('removeOutputFile'); + removeInputFileButton = document.getElementById('removeInputFile'); + timeLimit = document.getElementById('time_limit'); + memoryLimit = document.getElementById('memory_limit'); + ncpus = document.getElementById('ncpus'); + mpiNbcpu = document.getElementById('mpi_nbcpu'); + mpiNbnoeud = document.getElementById('mpi_nbnoeud'); + + nameText.addEventListener('keyup', validate); + nameText.addEventListener('change', validate); + validate(); + + createButton.addEventListener('click', submitCreate); + cancelButton.addEventListener('click', submitCancel); + + addOutputFileButton.addEventListener('click', () => modifyFileRows(true, false)); + addInputFileButton.addEventListener('click', () => modifyFileRows(true, true)); + removeOutputFileButton.addEventListener('click', () => modifyFileRows(false, false)); + removeInputFileButton.addEventListener('click', () => modifyFileRows(false, true)); + + // Update form data on input changes + nameText.addEventListener('input', () => { + formData.name = nameText.value.trim(); + }); + timeLimit.addEventListener('input', () => { + formData.parameters.time_limit = timeLimit.value.trim(); + verifyValueInput(timeLimit, formData.parameters.time_limit); + }); + memoryLimit.addEventListener('input', () => { + formData.parameters.memory_limit = memoryLimit.value.trim(); + verifyValueInput(memoryLimit, formData.parameters.memory_limit); + }); + ncpus.addEventListener('input', () => { + formData.parameters.ncpus = ncpus.value.trim(); + verifyValueInput(ncpus, formData.parameters.ncpus); }); + mpiNbcpu.addEventListener('input', () => { + formData.parameters.mpi_nbcpu = mpiNbcpu.value.trim(); + verifyValueInput(mpiNbcpu, formData.parameters.mpi_nbcpu); + }); + mpiNbnoeud.addEventListener('input', () => { + formData.parameters.mpi_nbnoeud = mpiNbnoeud.value.trim(); + verifyValueInput(mpiNbnoeud, formData.parameters.mpi_nbnoeud); + }); +}); function verifyValueInput(inputItem, value) { const intVal = Number(value); if (Number.isInteger(intVal)) { inputItem.classList.remove('input-warning'); - } - else { + } else { inputItem.classList.add('input-warning'); - } + } } // Add or remove file rows dynamically @@ -93,7 +134,6 @@ function modifyFileRows(add, input, fileObj) { // Dynamic creation of file input row with type/unit handling function addFileRow(container, targetArray, fileObj) { - const copy = fileObj ? true : false; const wrapper = document.createElement('div'); wrapper.className = 'field'; @@ -110,8 +150,10 @@ function addFileRow(container, targetArray, fileObj) { const select = document.createElement('select'); - select.innerHTML = allowedTypes.map(type => ``).join(''); - + select.innerHTML = allowedTypes + .map((type) => ``) + .join(''); + row.appendChild(select); const nameWrapper = document.createElement('div'); @@ -136,20 +178,20 @@ function addFileRow(container, targetArray, fileObj) { select.value = type; inputName.value = fileObj.name; inputUnit.value = fileObj.unit; - } - - else { + } else { fileObj = { type: 'nom', name: '', unit: '0' }; inputName.placeholder = 'File Name : '; inputUnit.value = '0'; } - select.addEventListener('input', () => {fileObj.type = select.value.trim(); + select.addEventListener('input', () => { + fileObj.type = select.value.trim(); const unit = defaultUnits[fileObj.type]; inputUnit.value = unit; fileObj.unit = unit; }); - inputUnit.addEventListener('input', () => {const value = inputUnit.value.trim(); + inputUnit.addEventListener('input', () => { + const value = inputUnit.value.trim(); verifyValueInput(inputUnit, inputUnit.value.trim()); fileObj.unit = value; }); @@ -157,7 +199,6 @@ function addFileRow(container, targetArray, fileObj) { inputName.fileObj = fileObj; if (targetArray === formData.inputFiles) { - const triggerHandle = () => { fileObj.name = inputName.value.trim(); handleFileNameInput(inputName); @@ -169,52 +210,50 @@ function addFileRow(container, targetArray, fileObj) { inputName.addEventListener('blur', () => { // 100 ms delay to allow clicking on a suggestion // without this, the suggestions would disappear before the click registers - setTimeout(() => removeSuggestions(), 100); + setTimeout(() => removeSuggestions(), 100); }); - } else { - inputName.addEventListener('input', () => fileObj.name = inputName.value.trim()); + inputName.addEventListener('input', () => (fileObj.name = inputName.value.trim())); } if (!copy) { targetArray.push(fileObj); } } - function removeFileRow(container, targetArray) { if (container.lastElementChild) { container.removeChild(container.lastElementChild); - targetArray.pop(); + targetArray.pop(); } } function handleFileNameInput(inputElement) { - lastActiveInput = inputElement; - const row = inputElement.parentElement?.parentElement; + lastActiveInput = inputElement; + const row = inputElement.parentElement?.parentElement; const select = row?.querySelector('select'); const selectedType = select ? select.value.trim() : ''; - vscode.postMessage({ - command: 'autocomplete', - value: inputElement.value, - type: selectedType - }); + vscode.postMessage({ + command: 'autocomplete', + value: inputElement.value, + type: selectedType, + }); } function removeSuggestions() { - const existing = lastActiveInput.parentElement.querySelector('.suggestion-box'); - if (existing) { - existing.remove(); - } + const existing = lastActiveInput.parentElement.querySelector('.suggestion-box'); + if (existing) { + existing.remove(); + } } -window.addEventListener('message', event => { - const message = event.data; +window.addEventListener('message', (event) => { + const message = event.data; - if (message.command === 'autocompleteResult') { + if (message.command === 'autocompleteResult') { lastActiveInput.classList.remove('input-warning'); - showSuggestions(message.suggestions, lastActiveInput); - } + showSuggestions(message.suggestions, lastActiveInput); + } if (message.command === 'autocompleteFailed') { lastActiveInput.classList.add('input-warning'); @@ -222,12 +261,12 @@ window.addEventListener('message', event => { if (existing) { existing.remove(); } - } + } if (message.command === 'verifyFileNames') { existingFiles = message.files; - } - + } + if (message.command === 'exportFileAlreadyDefined') { copyExportFile(message.formData); } @@ -270,20 +309,18 @@ function copyExportFile(exportData) { } for (const file of exportData.inputFiles) { - const fileObj = {type: file.type, name: file.name, unit: file.unit}; + const fileObj = { type: file.type, name: file.name, unit: file.unit }; formData.inputFiles.unshift(fileObj); modifyFileRows(true, true, fileObj); } - + for (const file of exportData.outputFiles) { - const fileObj = {type: file.type, name: file.name, unit: file.unit}; + const fileObj = { type: file.type, name: file.name, unit: file.unit }; formData.outputFiles.unshift(fileObj); modifyFileRows(true, false, fileObj); } - } - function showSuggestions(suggestions, inputElement) { const existing = inputElement.parentElement.querySelector('.suggestion-box'); if (existing) { @@ -320,9 +357,7 @@ function showSuggestions(suggestions, inputElement) { let selectedIndex = 0; const updateHighlight = () => { - items.forEach((el, i) => - el.classList.toggle('highlighted-suggestion', i === selectedIndex) - ); + items.forEach((el, i) => el.classList.toggle('highlighted-suggestion', i === selectedIndex)); }; inputElement.addEventListener('keydown', function handleKeyDown(event) { @@ -334,8 +369,7 @@ function showSuggestions(suggestions, inputElement) { event.preventDefault(); selectedIndex = (selectedIndex - 1 + items.length) % items.length; updateHighlight(); - } else if (event.key === 'Enter' || event.key === 'ArrowRight' - ||event.key === 'Tab') { + } else if (event.key === 'Enter' || event.key === 'ArrowRight' || event.key === 'Tab') { event.preventDefault(); inputElement.value = suggestions[selectedIndex]; inputElement.removeEventListener('keydown', handleKeyDown); @@ -355,16 +389,12 @@ function showSuggestions(suggestions, inputElement) { inputElement.parentElement.appendChild(box); } - - - function submitCreate() { const errorMsg = checkFields(); if (errorMsg) { vscode.postMessage({ command: 'wrongCreation', value: errorMsg }); - } - else { + } else { const lines = []; const filename = formData.name; lines.push(filename); @@ -379,15 +409,14 @@ function submitCreate() { for (const file of formData.outputFiles) { lines.push(`F ${file.type} ${file.name} R ${file.unit}`); - } + } const content = lines.join('\n'); - vscode.postMessage({ command: 'result', value: content}); + vscode.postMessage({ command: 'result', value: content }); } } function checkFields() { - for (const [key, value] of Object.entries(formData.parameters)) { const intVal = Number(value.trim()); if (!value || !Number.isInteger(intVal)) { @@ -404,7 +433,9 @@ function checkFields() { if (!Number.isInteger(intVal)) { return `Input file #${i + 1} is invalid: unit must be an integer.`; } - let alreadyUsed = formData.outputFiles.some(test => Number(file.unit) !== 0 && test.unit === file.unit); + let alreadyUsed = formData.outputFiles.some( + (test) => Number(file.unit) !== 0 && test.unit === file.unit + ); for (let j = 0; j < formData.inputFiles.length; j++) { if (intVal && i !== j && formData.inputFiles[j].unit === file.unit) { alreadyUsed = true; @@ -425,7 +456,9 @@ function checkFields() { if (!Number.isInteger(intVal)) { return `Output file #${i + 1} is invalid: unit must be an integer.`; } - let alreadyUsed = formData.inputFiles.some(test => Number(file.unit) !== 0 && test.unit === file.unit); + let alreadyUsed = formData.inputFiles.some( + (test) => Number(file.unit) !== 0 && test.unit === file.unit + ); for (let j = 0; j < formData.outputFiles.length; j++) { if (intVal && i !== j && formData.outputFiles[j].unit === file.unit) { alreadyUsed = true; @@ -435,18 +468,16 @@ function checkFields() { if (alreadyUsed) { return `Output file #${i + 1} is invalid: ${intVal} is already used as a unit value.`; } - } return ''; } - function submitCancel() { - vscode.postMessage({ command: 'cancel' }); + vscode.postMessage({ command: 'cancel' }); } function validate() { - const isValid = !!nameText.value; - createButton.disabled = !isValid; + const isValid = !!nameText.value; + createButton.disabled = !isValid; } diff --git a/webviews/viewer/index.html b/webviews/viewer/index.html new file mode 100644 index 0000000..318a9bc --- /dev/null +++ b/webviews/viewer/index.html @@ -0,0 +1,14 @@ + + + + + + MeshViewer + + + +
+
+ + + diff --git a/resources/visu_vtk/js/vtk.js b/webviews/viewer/js/vtk.js similarity index 100% rename from resources/visu_vtk/js/vtk.js rename to webviews/viewer/js/vtk.js diff --git a/webviews/viewer/src/app.css b/webviews/viewer/src/app.css new file mode 100644 index 0000000..87b5902 --- /dev/null +++ b/webviews/viewer/src/app.css @@ -0,0 +1,96 @@ +@import "tailwindcss"; + +@theme { + --color-ui-bg: var(--ui-bg); + --color-ui-fg: var(--ui-fg); + --color-ui-btn: var(--ui-btn-bg); + --color-ui-btn-hover: var(--ui-btn-hover-bg); + --color-ui-btn-fg: var(--ui-btn-fg); + --color-ui-popup-bg: var(--ui-popup-bg); + --color-ui-border: var(--ui-border); + --color-ui-text-primary: var(--ui-text-primary); + --color-ui-text-secondary: var(--ui-text-secondary); + --color-ui-text-muted: var(--ui-text-muted); + --color-ui-elem: var(--ui-element-bg); + --color-ui-elem-hover: var(--ui-element-bg-hover); + --color-ui-muted: var(--ui-bg-translucent); + --color-ui-link: var(--vscode-textLink-foreground, #0078d4); +} + +:root { + --ui-bg: var(--vscode-sideBar-background, var(--vscode-editor-background, #e8eaf0)); + --ui-fg: var(--vscode-sideBar-foreground, var(--vscode-editor-foreground, #1f1f1f)); + --ui-btn-bg: var(--vscode-button-background, #0078d4); + --ui-btn-fg: var(--vscode-button-foreground, #ffffff); + --ui-btn-hover-bg: var(--vscode-button-hoverBackground, #005fa3); + --ui-popup-bg: var(--vscode-editorWidget-background, var(--vscode-editor-background, #f3f3f3)); + --ui-border: var(--vscode-widget-border, var(--vscode-editorWidget-border, rgba(0,0,0,0.1))); + --icon-filter: none; + + --ui-text-primary: color-mix(in srgb, var(--ui-fg) 90%, transparent); + --ui-text-secondary: color-mix(in srgb, var(--ui-fg) 70%, transparent); + --ui-text-muted: color-mix(in srgb, var(--ui-fg) 55%, transparent); + --ui-element-bg: color-mix(in srgb, var(--ui-fg) 10%, transparent); + --ui-element-bg-hover: color-mix(in srgb, var(--ui-fg) 18%, transparent); + --ui-bg-translucent: color-mix(in srgb, var(--ui-bg) 85%, transparent); + --ui-highlight-text: rgba(255, 255, 255, 0.9); +} + +body.vscode-dark, +body.vscode-high-contrast { + --icon-filter: invert(1); + --ui-highlight-text: rgba(0, 0, 0, 0.8); +} + +kbd { + @apply px-1 py-px rounded-sm; + color: var(--vscode-textLink-foreground, #0078d4); + background: color-mix(in srgb, var(--ui-bg) 70%, transparent); +} + +input[type="checkbox"].custom-cb:focus { + outline: none; +} + +input[type="checkbox"].custom-cb { + appearance: none; + width: 13px; + height: 13px; + flex-shrink: 0; + border-radius: 3px; + border: 1.5px solid var(--ui-text-secondary); + cursor: pointer; + position: relative; + transition: background 0.1s, border-color 0.1s; +} + +input[type="checkbox"].custom-cb:checked { + background: var(--ui-btn-bg); + border-color: var(--ui-btn-bg); +} + +input[type="checkbox"].custom-cb:checked::after { + content: ''; + position: absolute; + inset: 0; + margin: auto; + width: 4px; + height: 7px; + border-right: 1.5px solid var(--ui-btn-fg); + border-bottom: 1.5px solid var(--ui-btn-fg); + transform: translateY(-1px) rotate(45deg); +} + +#sidebarGroups, +#helpPopup .overflow-y-auto, +#settingsPopup .overflow-y-auto, +#groupsPopup .overflow-y-auto { + scrollbar-width: none; +} + +#sidebarGroups::-webkit-scrollbar, +#helpPopup .overflow-y-auto::-webkit-scrollbar, +#settingsPopup .overflow-y-auto::-webkit-scrollbar, +#groupsPopup .overflow-y-auto::-webkit-scrollbar { + display: none; +} diff --git a/webviews/viewer/src/components/ActionButtons.svelte b/webviews/viewer/src/components/ActionButtons.svelte new file mode 100644 index 0000000..872c819 --- /dev/null +++ b/webviews/viewer/src/components/ActionButtons.svelte @@ -0,0 +1,44 @@ + + +
+
+ + +
+
+
+ + +
+
diff --git a/webviews/viewer/src/components/App.svelte b/webviews/viewer/src/components/App.svelte new file mode 100644 index 0000000..90a1298 --- /dev/null +++ b/webviews/viewer/src/components/App.svelte @@ -0,0 +1,67 @@ + + +{#if hasData} + { + openPopup = 'groups'; + }} + /> +{:else} + +{/if} + +{#if hasData} + { + openPopup = 'settings'; + }} + onOpenHelp={() => { + openPopup = 'help'; + }} + /> + + +{/if} + +{#if openPopup} + { + openPopup = null; + }} + > + {#if openPopup === 'help'} + { + openPopup = null; + }} + /> + {:else if openPopup === 'settings'} + { + openPopup = null; + }} + /> + {:else if openPopup === 'groups'} + { + openPopup = null; + }} + /> + {/if} + +{/if} diff --git a/webviews/viewer/src/components/AxisButtons.svelte b/webviews/viewer/src/components/AxisButtons.svelte new file mode 100644 index 0000000..38447ec --- /dev/null +++ b/webviews/viewer/src/components/AxisButtons.svelte @@ -0,0 +1,27 @@ + + +
+ + + +
diff --git a/webviews/viewer/src/components/GroupButton.svelte b/webviews/viewer/src/components/GroupButton.svelte new file mode 100644 index 0000000..35d7047 --- /dev/null +++ b/webviews/viewer/src/components/GroupButton.svelte @@ -0,0 +1,53 @@ + + +{#if !isHidden} + +{/if} diff --git a/webviews/viewer/src/components/LoadingScreen.svelte b/webviews/viewer/src/components/LoadingScreen.svelte new file mode 100644 index 0000000..0111f3d --- /dev/null +++ b/webviews/viewer/src/components/LoadingScreen.svelte @@ -0,0 +1,10 @@ + + +
+
+ Loading meshes... +
diff --git a/webviews/viewer/src/components/ObjectSection.svelte b/webviews/viewer/src/components/ObjectSection.svelte new file mode 100644 index 0000000..065e2e9 --- /dev/null +++ b/webviews/viewer/src/components/ObjectSection.svelte @@ -0,0 +1,142 @@ + + +{#if contextMenu} +
{ + e.preventDefault(); + closeContextMenu(); + }} + role="presentation" + >
+
+ +
+{/if} + + + + e.key === 'Enter' && toggleCollapsed()} + role="button" + tabindex="0" + > + {objectName} + + + + +{#if isHidden} +
+ {groupCount} groups +
+{:else if !collapsed} +
+ {#each faces as groupName} + + {/each} + {#each nodes as groupName} + + {/each} + {#if hiddenGroupCount > 0} +
+ {hiddenGroupCount} hidden +
+ {/if} +
+{:else} +
+ {groupCount} groups +
+{/if} diff --git a/webviews/viewer/src/components/Sidebar.svelte b/webviews/viewer/src/components/Sidebar.svelte new file mode 100644 index 0000000..e61cc07 --- /dev/null +++ b/webviews/viewer/src/components/Sidebar.svelte @@ -0,0 +1,33 @@ + + +
+
+ {#each Object.entries($groupHierarchy) as [key, data]} + + {/each} +
+ + + +
+ + +
diff --git a/webviews/viewer/src/components/TopActions.svelte b/webviews/viewer/src/components/TopActions.svelte new file mode 100644 index 0000000..8b3bbe1 --- /dev/null +++ b/webviews/viewer/src/components/TopActions.svelte @@ -0,0 +1,37 @@ + + +
+ + +
diff --git a/webviews/viewer/src/components/ZoomWidget.svelte b/webviews/viewer/src/components/ZoomWidget.svelte new file mode 100644 index 0000000..620ac98 --- /dev/null +++ b/webviews/viewer/src/components/ZoomWidget.svelte @@ -0,0 +1,62 @@ + + +
+
+ + {zoomText} +
+ {#if !$isAtDefaultZoom} + + {/if} +
diff --git a/webviews/viewer/src/components/popups/GroupsPopup.svelte b/webviews/viewer/src/components/popups/GroupsPopup.svelte new file mode 100644 index 0000000..d0fe1c6 --- /dev/null +++ b/webviews/viewer/src/components/popups/GroupsPopup.svelte @@ -0,0 +1,149 @@ + + +
+
+ Sidebar groups + + Choose which groups are shown in the sidebar. Hidden groups remain visible in the 3D view. + +
+ +
+ {#each objects as obj (obj.key)} + {@const allOff = allUnchecked(obj.key, obj.allGroups)} +
+
+
+ + {obj.name} +
+ +
+ + {#each obj.allGroups as group} + + {/each} +
+ {/each} +
+ +
+ + +
+
diff --git a/webviews/viewer/src/components/popups/HelpPopup.svelte b/webviews/viewer/src/components/popups/HelpPopup.svelte new file mode 100644 index 0000000..59d87b8 --- /dev/null +++ b/webviews/viewer/src/components/popups/HelpPopup.svelte @@ -0,0 +1,238 @@ + + + + +
+ + +
+
+ {#if activeTab === 'Camera'} +
+ Drag to rotate + Ctrl+Drag to rotate around a single axis + Shift+Drag to pan + Zoom in / out + + + 2.0× + + + + + + Open the zoom level selector to choose a preset + + + + 2.0× + + + + + + Reset zoom to 1× — appears only when zoom ≠ 1× + + X + Y + Z + + Align camera along that axis — buttons at the bottom of the sidebar +
+ {:else if activeTab === 'Objects'} +
+ + + mesh + + + Click the name to collapse or expand its groups + + + + mesh + + + Click to show or hide an entire object + + + + mesh + + + Right-click for more options — e.g. hide all other objects +
+ {:else if activeTab === 'Groups'} +
+ + + group_A + + Click a group to highlight it — the object becomes transparent so the group + stands out. Click again to unhighlight. + + + + + + + Click to choose which groups appear in the sidebar — hidden groups remain + visible in the 3D view + + + + + + + Click to clear all highlights +
+ {:else if activeTab === 'Files'} +
+

+ .med mesh files are automatically converted to .obj when opened. +

+

+ Converted files are cached in a hidden .visu_data/ folder in your workspace and + reused on subsequent opens. +

+
+ {:else if activeTab === 'About'} +
+

+ This extension is made by Simvia. +

+

+ Source code and issue tracker are available on GitHub. +

+
+ {/if} +
+ +
+ +
+
+
+ + diff --git a/webviews/viewer/src/components/popups/Popup.svelte b/webviews/viewer/src/components/popups/Popup.svelte new file mode 100644 index 0000000..7930420 --- /dev/null +++ b/webviews/viewer/src/components/popups/Popup.svelte @@ -0,0 +1,22 @@ + + + diff --git a/webviews/viewer/src/components/popups/SettingsPopup.svelte b/webviews/viewer/src/components/popups/SettingsPopup.svelte new file mode 100644 index 0000000..2f370b1 --- /dev/null +++ b/webviews/viewer/src/components/popups/SettingsPopup.svelte @@ -0,0 +1,390 @@ + + +{#snippet tip(text: string)} + + + + +{/snippet} + +
+
+ + +
+
+ {#if activeTab === 'Edges'} +
+
+ Edge rendering mode + {@render tip( + 'Choose when mesh edges are visible: always, never, or only when zooming in. Threshold mode shows edges abruptly at a zoom level; gradual mode fades them in (may impact performance on dense meshes).' + )} +
+
+ {edgeModeLabel} + +
+ + {edgeModeDesc} + + {#if showThresholdSection} +
+
+
+ + {@render tip( + 'Higher values show edges at a lower zoom level, from farther away.' + )} +
+ + {edgeThresholdDisplay.toPrecision(edgeThresholdDisplay < 1 ? 2 : 3)}× + +
+ + Higher values show edges from farther away. +
+ {/if} +
+ {:else if activeTab === 'Visibility'} +
+
+
+
+ + {@render tip( + 'At 0% hidden objects are fully invisible. Above 0% they remain as faint ghosts.' + )} +
+ {hiddenOpacityPct}% +
+ + When hiding an object with the eye button, it can remain slightly visible as a ghost. +
+
+
+
+ + {@render tip( + 'When a sub-group is highlighted, the parent mesh fades to this opacity so the selected group stands out.' + )} +
+ {groupTransparencyPct}% +
+ + Opacity of the parent mesh when a sub-group is highlighted. +
+
+ {:else if activeTab === 'Display'} +
+
+ +
+
+ Orientation widget + {@render tip( + 'Toggle the XYZ axes indicator in the bottom-right corner of the viewport.' + )} +
+ Show the axes widget in the bottom-right corner. +
+
+
+ {/if} +
+ +
+ + +
+
+
diff --git a/webviews/viewer/src/icons/ChevronIcon.svelte b/webviews/viewer/src/icons/ChevronIcon.svelte new file mode 100644 index 0000000..b08fee6 --- /dev/null +++ b/webviews/viewer/src/icons/ChevronIcon.svelte @@ -0,0 +1,16 @@ + + + + + diff --git a/webviews/viewer/src/icons/ClearIcon.svelte b/webviews/viewer/src/icons/ClearIcon.svelte new file mode 100644 index 0000000..bc83fef --- /dev/null +++ b/webviews/viewer/src/icons/ClearIcon.svelte @@ -0,0 +1,18 @@ + + + + + + + diff --git a/webviews/viewer/src/icons/EyeIcon.svelte b/webviews/viewer/src/icons/EyeIcon.svelte new file mode 100644 index 0000000..dcf30d1 --- /dev/null +++ b/webviews/viewer/src/icons/EyeIcon.svelte @@ -0,0 +1,19 @@ + + + + + + diff --git a/webviews/viewer/src/icons/EyeOffIcon.svelte b/webviews/viewer/src/icons/EyeOffIcon.svelte new file mode 100644 index 0000000..8f28752 --- /dev/null +++ b/webviews/viewer/src/icons/EyeOffIcon.svelte @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/webviews/viewer/src/icons/FaceIcon.svelte b/webviews/viewer/src/icons/FaceIcon.svelte new file mode 100644 index 0000000..6abea79 --- /dev/null +++ b/webviews/viewer/src/icons/FaceIcon.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/webviews/viewer/src/icons/FilterIcon.svelte b/webviews/viewer/src/icons/FilterIcon.svelte new file mode 100644 index 0000000..d470d9c --- /dev/null +++ b/webviews/viewer/src/icons/FilterIcon.svelte @@ -0,0 +1,18 @@ + + + + + diff --git a/webviews/viewer/src/icons/MouseLeftIcon.svelte b/webviews/viewer/src/icons/MouseLeftIcon.svelte new file mode 100644 index 0000000..596b181 --- /dev/null +++ b/webviews/viewer/src/icons/MouseLeftIcon.svelte @@ -0,0 +1,24 @@ + + + + + + + + + diff --git a/webviews/viewer/src/icons/MouseRightIcon.svelte b/webviews/viewer/src/icons/MouseRightIcon.svelte new file mode 100644 index 0000000..3cde6d6 --- /dev/null +++ b/webviews/viewer/src/icons/MouseRightIcon.svelte @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/webviews/viewer/src/icons/MouseScrollIcon.svelte b/webviews/viewer/src/icons/MouseScrollIcon.svelte new file mode 100644 index 0000000..b8f0827 --- /dev/null +++ b/webviews/viewer/src/icons/MouseScrollIcon.svelte @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/webviews/viewer/src/icons/NodeIcon.svelte b/webviews/viewer/src/icons/NodeIcon.svelte new file mode 100644 index 0000000..d0d42f9 --- /dev/null +++ b/webviews/viewer/src/icons/NodeIcon.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/webviews/viewer/src/icons/ObjectIcon.svelte b/webviews/viewer/src/icons/ObjectIcon.svelte new file mode 100644 index 0000000..9dda598 --- /dev/null +++ b/webviews/viewer/src/icons/ObjectIcon.svelte @@ -0,0 +1,14 @@ + + + + + diff --git a/webviews/viewer/src/icons/QuestionIcon.svelte b/webviews/viewer/src/icons/QuestionIcon.svelte new file mode 100644 index 0000000..3f02565 --- /dev/null +++ b/webviews/viewer/src/icons/QuestionIcon.svelte @@ -0,0 +1,18 @@ + + + + + + + diff --git a/webviews/viewer/src/icons/ResetIcon.svelte b/webviews/viewer/src/icons/ResetIcon.svelte new file mode 100644 index 0000000..9a41d2f --- /dev/null +++ b/webviews/viewer/src/icons/ResetIcon.svelte @@ -0,0 +1,17 @@ + + + + + + diff --git a/webviews/viewer/src/icons/SettingsIcon.svelte b/webviews/viewer/src/icons/SettingsIcon.svelte new file mode 100644 index 0000000..83b9f89 --- /dev/null +++ b/webviews/viewer/src/icons/SettingsIcon.svelte @@ -0,0 +1,19 @@ + + + + + + diff --git a/webviews/viewer/src/icons/ZoomIcon.svelte b/webviews/viewer/src/icons/ZoomIcon.svelte new file mode 100644 index 0000000..92a57c0 --- /dev/null +++ b/webviews/viewer/src/icons/ZoomIcon.svelte @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/webviews/viewer/src/lib/Controller.ts b/webviews/viewer/src/lib/Controller.ts new file mode 100644 index 0000000..fe7c124 --- /dev/null +++ b/webviews/viewer/src/lib/Controller.ts @@ -0,0 +1,78 @@ +import { VtkApp } from './core/VtkApp'; +import { CreateGroups } from './data/CreateGroups'; +import { VisibilityManager } from './commands/VisibilityManager'; +import { CameraManager } from './interaction/CameraManager'; +import { groupHierarchy as groupHierarchyStore } from './state'; +import type { Group } from './data/Group'; + +export class Controller { + private static _i: Controller; + private _scene: HTMLElement | null = null; + private _vsCodeApi: any = null; + private _groups: Record | null = null; + private _groupHierarchy: Record | null = null; + + static get Instance(): Controller { + if (!this._i) { + this._i = new Controller(); + } + return this._i; + } + + init(scene: HTMLElement, vsCodeApiEntry: any): void { + this._scene = scene; + this._vsCodeApi = vsCodeApiEntry; + VtkApp.Instance.init(scene); + } + + getScene(): HTMLElement | null { + return this._scene; + } + + getVSCodeAPI(): any { + return this._vsCodeApi; + } + + loadFiles(fileContexts: string[], fileNames: string[]): void { + const lfr = new CreateGroups(fileContexts, fileNames); + lfr.do(); + this._vsCodeApi.postMessage({ + type: 'groups', + groupList: this.getGroupNames(), + }); + } + + saveGroups(groups: Record, groupHierarchy: Record): void { + this._groups = groups; + this._groupHierarchy = groupHierarchy; + + groupHierarchyStore.set(groupHierarchy); + + this.initManagers(); + + this._vsCodeApi.postMessage({ + type: 'debugPanel', + text: 'Actors and hierarchy saved', + }); + } + + private initManagers(): void { + if (!this._groups || !this._groupHierarchy) return; + VisibilityManager.Instance.init(this._groups, this._groupHierarchy); + CameraManager.Instance.init(this._groups); + } + + refreshThemeColors(): void { + if (!this._groups) return; + for (const group of Object.values(this._groups)) { + group.applyThemeColor(); + } + } + + getGroupNames(): string[] { + if (!this._groups) { + return []; + } + return Object.keys(this._groups).filter((key) => key.includes('::')); + } +} diff --git a/webviews/viewer/src/lib/commands/VisibilityManager.ts b/webviews/viewer/src/lib/commands/VisibilityManager.ts new file mode 100644 index 0000000..afb7f3d --- /dev/null +++ b/webviews/viewer/src/lib/commands/VisibilityManager.ts @@ -0,0 +1,209 @@ +import { Controller } from '../Controller'; +import { VtkApp } from '../core/VtkApp'; +import { GlobalSettings } from '../settings/GlobalSettings'; +import { highlightedGroups, hiddenObjects } from '../state'; +import type { Group } from '../data/Group'; + +export class VisibilityManager { + private static _i: VisibilityManager; + groups: Record = {}; + private visibleGroupsByObject: Record = {}; + hiddenObjects: Record = {}; + private highlightedGroupsSet: Set = new Set(); + + static get Instance(): VisibilityManager { + if (!this._i) { + this._i = new VisibilityManager(); + } + return this._i; + } + + init(groups: Record, objects: Record): void { + this.groups = groups; + this.visibleGroupsByObject = {}; + this.hiddenObjects = {}; + this.highlightedGroupsSet = new Set(); + + for (const object in objects) { + this.visibleGroupsByObject[object] = 0; + this.hiddenObjects[object] = false; + } + + hiddenObjects.set(new Set()); + highlightedGroups.set(new Map()); + } + + setVisibility( + groupName: string, + visible?: boolean + ): { visible: boolean; color: number[]; isFaceGroup: boolean } | undefined { + const post = (text: string) => { + Controller.Instance.getVSCodeAPI().postMessage({ type: 'debugPanel', text }); + }; + + const group = this.groups[groupName]; + if (!group) { + post(`setVisibility: group "${groupName}" has no group defined`); + return; + } + const object = group.fileGroup; + if (!object) { + post(`setVisibility: group "${groupName}" has no parent object`); + return; + } + const actor = group.actor; + if (!actor) { + post(`setVisibility: no actor found for group "${groupName}"`); + return; + } + + const color = group.getColor(); + const isFaceGroup = group.isFaceGroup; + + const wasHighlighted = this.highlightedGroupsSet.has(groupName); + const isHighlighted = typeof visible === 'boolean' ? visible : !wasHighlighted; + + if (isHighlighted) { + this.highlightedGroupsSet.add(groupName); + highlightedGroups.update((map) => { + map.set(groupName, color); + return map; + }); + } else { + this.highlightedGroupsSet.delete(groupName); + highlightedGroups.update((map) => { + map.delete(groupName); + return map; + }); + } + + if (!this.hiddenObjects[object]) { + group.setVisibility(isHighlighted); + } + + if (wasHighlighted !== isHighlighted) { + const visibleGroupsCount = this.visibleGroupsByObject[object]; + if (!this.hiddenObjects[object]) { + if ( + (visibleGroupsCount === 0 && isHighlighted) || + (visibleGroupsCount === 1 && !isHighlighted) + ) { + this.setTransparence(isHighlighted, object); + } + } + this.visibleGroupsByObject[object] += isHighlighted ? 1 : -1; + } + + VtkApp.Instance.getRenderWindow().render(); + + return { visible: isHighlighted, color, isFaceGroup }; + } + + toggleObjectVisibility(object: string): boolean { + const nowVisible = this.hiddenObjects[object]; + this.hiddenObjects[object] = !nowVisible; + + hiddenObjects.update((s) => { + if (nowVisible) s.delete(object); + else s.add(object); + return s; + }); + + const fileGroup = this.groups[object]; + if (fileGroup) { + if (nowVisible) { + fileGroup.actor.setVisibility(true); + const opacity = + this.visibleGroupsByObject[object] > 0 ? GlobalSettings.Instance.groupTransparency : 1.0; + fileGroup.setOpacity(opacity); + } else { + const hiddenOpacity = GlobalSettings.Instance.hiddenObjectOpacity; + if (hiddenOpacity === 0) { + fileGroup.actor.setVisibility(false); + } else { + fileGroup.actor.setVisibility(true); + fileGroup.setOpacity(hiddenOpacity); + } + } + } + + for (const [groupName, group] of Object.entries(this.groups)) { + if (group.fileGroup === object) { + group.actor.setVisibility(nowVisible && this.highlightedGroupsSet.has(groupName)); + } + } + + VtkApp.Instance.getRenderWindow().render(); + return nowVisible; + } + + setTransparence(transparent: boolean, object: string): void { + if (!this.groups || this.hiddenObjects[object]) { + return; + } + const meshOpacity = transparent ? GlobalSettings.Instance.groupTransparency : 1; + const group = this.groups[object]; + group.setOpacity(meshOpacity); + } + + applyGroupTransparency(): void { + for (const object in this.visibleGroupsByObject) { + if (this.hiddenObjects[object]) continue; + if (this.visibleGroupsByObject[object] > 0) { + this.groups[object]?.setOpacity(GlobalSettings.Instance.groupTransparency); + } + } + VtkApp.Instance.getRenderWindow().render(); + } + + hideAllOthers(object: string): void { + for (const key in this.hiddenObjects) { + if (key === object) continue; + const isAlreadyHidden = this.hiddenObjects[key]; + if (!isAlreadyHidden) { + this.toggleObjectVisibility(key); + } + } + if (this.hiddenObjects[object]) { + this.toggleObjectVisibility(object); + } + } + + applyHiddenObjectOpacity(): void { + const hiddenOpacity = GlobalSettings.Instance.hiddenObjectOpacity; + for (const object in this.hiddenObjects) { + if (!this.hiddenObjects[object]) continue; + const fileGroup = this.groups[object]; + if (!fileGroup) continue; + if (hiddenOpacity === 0) { + fileGroup.actor.setVisibility(false); + } else { + fileGroup.actor.setVisibility(true); + fileGroup.setOpacity(hiddenOpacity); + } + } + VtkApp.Instance.getRenderWindow().render(); + } + + clear(): void { + for (const [, group] of Object.entries(this.groups)) { + if (!group.actor) { + continue; + } + if (group.fileGroup === null) { + continue; + } + group.setVisibility(false); + } + + this.highlightedGroupsSet.clear(); + highlightedGroups.set(new Map()); + + for (const object in this.visibleGroupsByObject) { + this.setTransparence(false, object); + this.visibleGroupsByObject[object] = 0; + } + + VtkApp.Instance.getRenderWindow().render(); + } +} diff --git a/webviews/viewer/src/lib/core/VtkApp.ts b/webviews/viewer/src/lib/core/VtkApp.ts new file mode 100644 index 0000000..9337d6c --- /dev/null +++ b/webviews/viewer/src/lib/core/VtkApp.ts @@ -0,0 +1,90 @@ +import { Controller } from '../Controller'; + +export class VtkApp { + private static _i: VtkApp; + private fullScreenRenderer: any; + renderer: any; + renderWindow: any; + + static get Instance(): VtkApp { + if (!this._i) { + this._i = new VtkApp(); + } + return this._i; + } + + private _readEditorBackground(): number[] { + const raw = getComputedStyle(document.body) + .getPropertyValue('--vscode-editor-background') + .trim(); + const match = raw.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); + if (match) { + return [ + parseInt(match[1], 16) / 255, + parseInt(match[2], 16) / 255, + parseInt(match[3], 16) / 255, + ]; + } + return [0.4, 0.6, 1.0]; + } + + updateBackground(): void { + this.renderer.setBackground(this._readEditorBackground()); + } + + init(scene: HTMLElement): void { + if (!window.vtk) { + return; + } + + this.fullScreenRenderer = vtk.Rendering.Misc.vtkFullScreenRenderWindow.newInstance({ + rootContainer: scene, + background: this._readEditorBackground(), + }); + + this.renderer = this.fullScreenRenderer.getRenderer(); + this.renderWindow = this.fullScreenRenderer.getRenderWindow(); + + this.updateCameraOffset(); + + const controls = document.getElementById('controls'); + if (controls) { + new ResizeObserver(() => this.updateCameraOffset()).observe(controls); + } + window.addEventListener('resize', () => this.updateCameraOffset()); + + new MutationObserver(() => { + this.updateBackground(); + Controller.Instance.refreshThemeColors(); + this.renderWindow.render(); + }).observe(document.body, { attributes: true, attributeFilter: ['class'] }); + + Controller.Instance.getVSCodeAPI().postMessage({ + type: 'debugPanel', + text: 'vtkAppInitialized', + }); + } + + updateCameraOffset(): void { + if (!this.renderer) return; + const controls = document.getElementById('controls'); + const sidebarActions = document.getElementById('sidebarActions'); + const sidebarWidth = controls ? controls.offsetWidth - (sidebarActions?.offsetWidth ?? 0) : 0; + const offset = sidebarWidth / window.innerWidth; + this.renderer.getActiveCamera().setWindowCenter(-offset, 0); + this.renderWindow.render(); + + const zoomWidget = document.getElementById('zoomWidget'); + if (zoomWidget) { + zoomWidget.style.left = `${sidebarWidth + (window.innerWidth - sidebarWidth) / 2}px`; + } + } + + getRenderer(): any { + return this.renderer; + } + + getRenderWindow(): any { + return this.renderWindow; + } +} diff --git a/webviews/viewer/src/lib/data/CreateGroups.ts b/webviews/viewer/src/lib/data/CreateGroups.ts new file mode 100644 index 0000000..9b51c7c --- /dev/null +++ b/webviews/viewer/src/lib/data/CreateGroups.ts @@ -0,0 +1,124 @@ +import { GlobalSettings } from '../settings/GlobalSettings'; +import { ObjLoader } from './ObjLoader'; +import { FaceActorCreator } from './create/FaceActorCreator'; +import { NodeActorCreator } from './create/NodeActorCreator'; +import { Group } from './Group'; +import { Controller } from '../Controller'; +import { VtkApp } from '../core/VtkApp'; + +export class CreateGroups { + private fileContexts: string[]; + private fileNames: string[]; + groups: Record = {}; + + constructor(fileContexts: string[], fileNames: string[]) { + this.fileContexts = fileContexts; + this.fileNames = fileNames; + } + + do(): void { + const result = ObjLoader.loadFiles(this.fileContexts, this.fileNames); + const post = (text: string) => { + Controller.Instance.getVSCodeAPI().postMessage({ type: 'debugPanel', text }); + }; + + if (!result) { + return; + } + + const { + vertices, + cells, + cellIndexToGroup, + nodes, + nodeIndexToGroup, + faceGroups, + nodeGroups, + groupHierarchy, + } = result; + + const faceActorCreator = new FaceActorCreator(vertices, cells, cellIndexToGroup); + const nodeActorCreator = new NodeActorCreator(vertices, nodes, nodeIndexToGroup); + + for (const fileGroup in groupHierarchy) { + const groupId = faceGroups.indexOf(fileGroup); + + const _oc = GlobalSettings.Instance.objectColors; + const objColor = _oc[GlobalSettings.Instance.objIndex % _oc.length]; + (groupHierarchy[fileGroup] as any).color = objColor; + + const { + actor, + colorIndex: fileColorIndex, + isObjectActor: fileIsObj, + cellCount: fileCellCount, + } = faceActorCreator.create(fileGroup, groupId); + + const groupInstance = new Group( + actor, + fileGroup, + true, + null, + null, + fileColorIndex, + fileIsObj, + fileCellCount + ); + this.groups[fileGroup] = groupInstance; + + const size = this.computeSize(actor); + + for (const faceGroup of groupHierarchy[fileGroup].faces) { + const faceGroupId = faceGroups.indexOf(`${fileGroup}::${faceGroup}::face`); + const { + actor: faceActor, + colorIndex: faceColorIndex, + isObjectActor: faceIsObj, + cellCount: faceCellCount, + } = faceActorCreator.create(faceGroup, faceGroupId); + const subGroup = new Group( + faceActor, + faceGroup, + true, + fileGroup, + size, + faceColorIndex, + faceIsObj, + faceCellCount + ); + this.groups[`${fileGroup}::${faceGroup}::face`] = subGroup; + } + + for (const nodeGroup of groupHierarchy[fileGroup].nodes) { + const nodeGroupId = nodeGroups.indexOf(`${fileGroup}::${nodeGroup}::node`); + const { actor: nodeActor, colorIndex: nodeColorIndex } = + nodeActorCreator.create(nodeGroupId); + const subGroup = new Group( + nodeActor, + nodeGroup, + false, + fileGroup, + size, + nodeColorIndex, + false + ); + this.groups[`${fileGroup}::${nodeGroup}::node`] = subGroup; + } + } + + VtkApp.Instance.getRenderer().resetCamera(); + VtkApp.Instance.getRenderWindow().render(); + post(`actors : ${Object.keys(this.groups).length}`); + + Controller.Instance.saveGroups(this.groups, groupHierarchy); + } + + private computeSize(actor: any): number { + const bounds = actor.getBounds(); + const dx = bounds[1] - bounds[0]; + const dy = bounds[3] - bounds[2]; + const dz = bounds[5] - bounds[4]; + const size = Math.sqrt(dx * dx + dy * dy + dz * dz); + return Math.max(size, 1e-3); + } +} diff --git a/webviews/viewer/src/lib/data/Group.ts b/webviews/viewer/src/lib/data/Group.ts new file mode 100644 index 0000000..7ca47f5 --- /dev/null +++ b/webviews/viewer/src/lib/data/Group.ts @@ -0,0 +1,105 @@ +import { GlobalSettings } from '../settings/GlobalSettings'; + +export class Group { + actor: any; + name: string; + isFaceGroup: boolean; + fileGroup: string | null; + size: number | null; + colorIndex: number | null; + isObjectActor: boolean; + cellCount: number | null; + private _edgeT?: number; + + constructor( + actor: any, + name: string, + isFaceGroup: boolean, + fileGroup: string | null = null, + parentSize: number | null = null, + colorIndex: number | null = null, + isObjectActor = false, + cellCount: number | null = null + ) { + this.actor = actor; + this.name = name; + this.isFaceGroup = isFaceGroup; + this.fileGroup = fileGroup; + this.size = parentSize; + this.colorIndex = colorIndex; + this.isObjectActor = isObjectActor; + this.cellCount = cellCount; + } + + applyThemeColor(): void { + if (this.colorIndex === null) return; + const colors = this.isObjectActor + ? GlobalSettings.Instance.objectColors + : GlobalSettings.Instance.meshGroupColors; + const color = colors[this.colorIndex % colors.length]; + this.actor.getProperty().setColor(color); + this._applyEdgeColor(); + } + + updateEdgeVisibility(currentDistance: number, initialDistance: number): void { + if (this.cellCount === null) return; + const prop = this.actor.getProperty(); + const mode = GlobalSettings.Instance.edgeMode; + + if (mode === 'hide') { + prop.setEdgeVisibility(false); + return; + } + if (mode === 'show') { + prop.setEdgeVisibility(true); + this._applyFlatEdgeColor(prop); + return; + } + + const threshold = + initialDistance * + Math.sqrt(15000 / this.cellCount) * + GlobalSettings.Instance.edgeThresholdMultiplier; + + if (mode === 'threshold') { + prop.setEdgeVisibility(currentDistance < threshold); + this._applyFlatEdgeColor(prop); + return; + } + + prop.setEdgeVisibility(true); + this._edgeT = Math.min(1, Math.max(0, threshold / currentDistance)); + this._applyEdgeColor(); + } + + private _applyFlatEdgeColor(prop: any): void { + const op = GlobalSettings.Instance.edgeOpacity; + const [r, g, b] = prop.getColor(); + prop.setEdgeColor(r * (1 - op), g * (1 - op), b * (1 - op)); + } + + private _applyEdgeColor(): void { + const t = this._edgeT ?? 0; + const op = GlobalSettings.Instance.edgeOpacity; + const [r, g, b] = this.actor.getProperty().getColor(); + this.actor.getProperty().setEdgeColor(r * (1 - t * op), g * (1 - t * op), b * (1 - t * op)); + } + + setSize(distance: number): void { + const decay = (this.size ?? 1) / 5; + const scale = Math.max(30 * (1 / Math.sqrt(1 + distance / decay)), 0); + this.actor.getProperty().setPointSize(scale); + } + + getColor(): number[] { + return this.actor.getProperty().getColor(); + } + + setVisibility(visible: boolean): void { + this.actor.setVisibility(visible); + } + + setOpacity(opacity: number): void { + this.actor.getProperty().setOpacity(opacity); + } +} diff --git a/webviews/viewer/src/lib/data/ObjLoader.ts b/webviews/viewer/src/lib/data/ObjLoader.ts new file mode 100644 index 0000000..ee3d42f --- /dev/null +++ b/webviews/viewer/src/lib/data/ObjLoader.ts @@ -0,0 +1,112 @@ +import { Controller } from '../Controller'; + +export interface ObjLoaderResult { + vertices: { x: number; y: number; z: number }[]; + cells: number[][]; + cellIndexToGroup: number[]; + nodes: number[]; + nodeIndexToGroup: number[]; + faceGroups: string[]; + nodeGroups: string[]; + groupHierarchy: Record; +} + +export class ObjLoader { + static loadFiles(fileContexts: string[], fileNames: string[]): ObjLoaderResult { + const vertices: { x: number; y: number; z: number }[] = []; + const cells: number[][] = []; + const cellIndexToGroup: number[] = []; + const nodes: number[] = []; + const nodeIndexToGroup: number[] = []; + const faceGroups: string[] = []; + const nodeGroups: string[] = []; + const groupHierarchy: Record = {}; + + let nbVertices = 0; + let groupId = -1; + let nodeGroupId = -1; + + for (let i = 0; i < fileContexts.length; i++) { + try { + groupId++; + const skinName = 'all_' + fileNames[i]; + + groupHierarchy[skinName] = { faces: [], nodes: [] }; + faceGroups.push(skinName); + nbVertices = vertices.length; + + const lines = fileContexts[i].split('\n').map((l) => l.replace('\r', '')); + + for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) { + const line = lines[lineIdx]; + const ss = line.split(' ').filter((p) => p.length !== 0); + if (ss.length === 0) { + continue; + } + + switch (ss[0]) { + case 'v': + vertices.push({ + x: Number.parseFloat(ss[1]), + y: Number.parseFloat(ss[2]), + z: Number.parseFloat(ss[3]), + }); + break; + + case 'f': { + const faceIndices = ss.slice(1).map((p) => Number.parseInt(p) - 1 + nbVertices); + cells.push(faceIndices); + cellIndexToGroup.push(groupId); + break; + } + + case 'g': { + groupId++; + const faceGroupName = ss[1] || `group${groupId}`; + faceGroups.push(`${skinName}::${faceGroupName}::face`); + groupHierarchy[skinName].faces.push(faceGroupName); + break; + } + + case 'ng': { + nodeGroupId++; + const nodeGroupName = ss[1] || `nodeGroup${nodeGroupId}`; + nodeGroups.push(`${skinName}::${nodeGroupName}::node`); + groupHierarchy[skinName].nodes.push(nodeGroupName); + break; + } + + case 'p': { + const nodeIndex = parseInt(ss[1]); + nodes.push(nodeIndex - 1 + nbVertices); + nodeIndexToGroup.push(nodeGroupId); + break; + } + } + } + } catch (fileError: any) { + Controller.Instance.getVSCodeAPI().postMessage({ + type: 'debugPanel', + text: `ERROR: ${fileError.message}`, + }); + throw fileError; + } + } + + Controller.Instance.getVSCodeAPI().postMessage({ + type: 'debugPanel', + text: `TOTAL: ${vertices.length} vertices, ${cells.length} cells, ${nodes.length} nodes`, + }); + + return { + vertices, + cells, + cellIndexToGroup, + nodes, + nodeIndexToGroup, + faceGroups, + nodeGroups, + groupHierarchy, + }; + } +} diff --git a/webviews/viewer/src/lib/data/create/FaceActorCreator.ts b/webviews/viewer/src/lib/data/create/FaceActorCreator.ts new file mode 100644 index 0000000..a8bca45 --- /dev/null +++ b/webviews/viewer/src/lib/data/create/FaceActorCreator.ts @@ -0,0 +1,102 @@ +import { GlobalSettings } from '../../settings/GlobalSettings'; +import { VtkApp } from '../../core/VtkApp'; + +export class FaceActorCreator { + private vertices: { x: number; y: number; z: number }[]; + private cells: number[][]; + private cellIndexToGroup: number[]; + + constructor( + vertices: { x: number; y: number; z: number }[], + cells: number[][], + cellIndexToGroup: number[] + ) { + this.vertices = vertices; + this.cells = cells; + this.cellIndexToGroup = cellIndexToGroup; + } + + create( + groupName: string, + groupId: number + ): { actor: any; colorIndex: number; isObjectActor: boolean; cellCount: number } { + const { polyData, cellCount } = this.prepare(groupId); + + const actor = vtk.Rendering.Core.vtkActor.newInstance(); + const mapper = vtk.Rendering.Core.vtkMapper.newInstance(); + + mapper.setInputData(polyData); + actor.setMapper(mapper); + + const { colorIndex, isObjectActor } = this.setProperty(actor, groupName, cellCount); + VtkApp.Instance.getRenderer().addActor(actor); + + return { actor, colorIndex, isObjectActor, cellCount }; + } + + private prepare(groupId: number): { polyData: any; cellCount: number } { + const pd = vtk.Common.DataModel.vtkPolyData.newInstance(); + + const pts = vtk.Common.Core.vtkPoints.newInstance(); + const coords = new Float32Array(this.vertices.length * 3); + this.vertices.forEach((v, i) => { + coords[3 * i] = v.x; + coords[3 * i + 1] = v.y; + coords[3 * i + 2] = v.z; + }); + pts.setData(coords, 3); + pd.setPoints(pts); + + const cellIndices = this.cellIndexToGroup + .map((g, idx) => (g === groupId ? idx : -1)) + .filter((idx) => idx !== -1); + + const cellCount = cellIndices.length; + if (cellCount > 0) { + const cellArray = vtk.Common.Core.vtkCellArray.newInstance({ + values: Uint32Array.from( + cellIndices.flatMap((i) => { + const c = this.cells[i]; + return [c.length, ...c]; + }) + ), + }); + pd.setPolys(cellArray); + } + + return { polyData: pd, cellCount }; + } + + private setProperty( + actor: any, + groupName: string, + _cellCount: number + ): { colorIndex: number; isObjectActor: boolean } { + const prop = actor.getProperty(); + + let colorIndex: number; + let isObjectActor: boolean; + if (groupName.includes('all_')) { + isObjectActor = true; + colorIndex = GlobalSettings.Instance.objIndex; + prop.setColor(GlobalSettings.Instance.getColorForObject()); + } else { + isObjectActor = false; + colorIndex = GlobalSettings.Instance.grpIndex; + prop.setColor(GlobalSettings.Instance.getColorForGroup()); + prop.setOpacity(1.0); + actor.setVisibility(false); + } + + const [r, g, b] = prop.getColor(); + prop.setEdgeVisibility(true); + prop.setEdgeColor(r, g, b); + prop.setLineWidth(0.3); + prop.setInterpolationToPhong(); + prop.setAmbient(GlobalSettings.Instance.ambientIntensity); + prop.setSpecular(GlobalSettings.Instance.specular); + prop.setSpecularPower(GlobalSettings.Instance.specularPower); + + return { colorIndex, isObjectActor }; + } +} diff --git a/webviews/viewer/src/lib/data/create/NodeActorCreator.ts b/webviews/viewer/src/lib/data/create/NodeActorCreator.ts new file mode 100644 index 0000000..d3b5714 --- /dev/null +++ b/webviews/viewer/src/lib/data/create/NodeActorCreator.ts @@ -0,0 +1,79 @@ +import { GlobalSettings } from '../../settings/GlobalSettings'; +import { VtkApp } from '../../core/VtkApp'; + +export class NodeActorCreator { + private vertices: { x: number; y: number; z: number }[]; + private nodes: number[]; + private nodeIndexToGroup: number[]; + + constructor( + vertices: { x: number; y: number; z: number }[], + nodes: number[], + nodeIndexToGroup: number[] + ) { + this.vertices = vertices; + this.nodes = nodes; + this.nodeIndexToGroup = nodeIndexToGroup; + } + + create(groupId: number): { actor: any; colorIndex: number } { + const polyData = this.prepare(groupId); + + const mapper = vtk.Rendering.Core.vtkMapper.newInstance(); + mapper.setInputData(polyData); + + const actor = vtk.Rendering.Core.vtkActor.newInstance(); + actor.setMapper(mapper); + + const colorIndex = this.setProperty(actor); + VtkApp.Instance.getRenderer().addActor(actor); + + return { actor, colorIndex }; + } + + private prepare(groupId: number): any { + const pd = vtk.Common.DataModel.vtkPolyData.newInstance(); + + const nodeIndices = this.nodeIndexToGroup + .map((g, idx) => (g === groupId ? idx : -1)) + .filter((idx) => idx !== -1); + + if (nodeIndices.length > 0) { + const pts = vtk.Common.Core.vtkPoints.newInstance(); + const data: number[] = []; + + for (const idx of nodeIndices) { + const v = this.vertices[this.nodes[idx]]; + if (v) { + data.push(v.x, v.y, v.z); + } + } + + pts.setData(Float32Array.from(data), 3); + pd.setPoints(pts); + + const numPoints = data.length / 3; + const verts = vtk.Common.Core.vtkCellArray.newInstance(); + const vertData: number[] = []; + + for (let i = 0; i < numPoints; i++) { + vertData.push(1, i); + } + + verts.setData(Uint32Array.from(vertData)); + pd.setVerts(verts); + } + + return pd; + } + + private setProperty(actor: any): number { + const prop = actor.getProperty(); + const colorIndex = GlobalSettings.Instance.grpIndex; + prop.setRepresentation(0); + prop.setOpacity(1); + actor.setVisibility(false); + prop.setColor(GlobalSettings.Instance.getColorForGroup()); + return colorIndex; + } +} diff --git a/webviews/viewer/src/lib/interaction/AxesCreator.ts b/webviews/viewer/src/lib/interaction/AxesCreator.ts new file mode 100644 index 0000000..61cbf60 --- /dev/null +++ b/webviews/viewer/src/lib/interaction/AxesCreator.ts @@ -0,0 +1,122 @@ +export class AxesCreator { + private axisRadius = 0.02; + + private colors = { + x: [1, 0, 0], + y: [0.251, 0.529, 0.376], + z: [0, 0, 1], + }; + + static createCustomAxesActor(): any { + const instance = new AxesCreator(); + + const axisRadius = instance.axisRadius; + const sphereRadius = 0.1; + const sphereTheta = 12; + const spherePhi = 12; + + const addColor = (polyData: any, color: number[]) => { + const scalars = vtk.Common.Core.vtkDataArray.newInstance({ + numberOfComponents: 3, + values: new Uint8Array(polyData.getPoints().getNumberOfPoints() * 3), + name: 'color', + }); + + const colors = scalars.getData(); + const rgb = color.map((c) => Math.round(c * 255)); + for (let i = 0; i < colors.length; i += 3) { + colors[i] = rgb[0]; + colors[i + 1] = rgb[1]; + colors[i + 2] = rgb[2]; + } + + polyData.getPointData().setScalars(scalars); + }; + + const xAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); + xAxisSource.setInputData( + vtk.Filters.Sources.vtkCylinderSource + .newInstance({ + radius: axisRadius, + resolution: 20, + direction: [1, 0, 0], + center: [0.5, 0, 0], + }) + .getOutputData() + ); + xAxisSource.addInputData( + vtk.Filters.Sources.vtkSphereSource + .newInstance({ + radius: sphereRadius, + center: [1, 0, 0], + thetaResolution: sphereTheta, + phiResolution: spherePhi, + }) + .getOutputData() + ); + const xAxis = xAxisSource.getOutputData(); + addColor(xAxis, instance.colors.x); + + const yAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); + yAxisSource.setInputData( + vtk.Filters.Sources.vtkCylinderSource + .newInstance({ + radius: axisRadius, + resolution: 20, + direction: [0, 1, 0], + center: [0, 0.5, 0], + }) + .getOutputData() + ); + yAxisSource.addInputData( + vtk.Filters.Sources.vtkSphereSource + .newInstance({ + radius: sphereRadius, + center: [0, 1, 0], + thetaResolution: sphereTheta, + phiResolution: spherePhi, + }) + .getOutputData() + ); + const yAxis = yAxisSource.getOutputData(); + addColor(yAxis, instance.colors.y); + + const zAxisSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); + zAxisSource.setInputData( + vtk.Filters.Sources.vtkCylinderSource + .newInstance({ + radius: axisRadius, + resolution: 20, + direction: [0, 0, 1], + center: [0, 0, 0.5], + }) + .getOutputData() + ); + zAxisSource.addInputData( + vtk.Filters.Sources.vtkSphereSource + .newInstance({ + radius: sphereRadius, + center: [0, 0, 1], + thetaResolution: sphereTheta, + phiResolution: spherePhi, + }) + .getOutputData() + ); + const zAxis = zAxisSource.getOutputData(); + addColor(zAxis, instance.colors.z); + + const axesSource = vtk.Filters.General.vtkAppendPolyData.newInstance(); + axesSource.setInputData(xAxis); + axesSource.addInputData(yAxis); + axesSource.addInputData(zAxis); + + const axesMapper = vtk.Rendering.Core.vtkMapper.newInstance(); + axesMapper.setInputData(axesSource.getOutputData()); + + const axesActor = vtk.Rendering.Core.vtkActor.newInstance(); + axesActor.setMapper(axesMapper); + axesActor.getProperty().setLighting(false); + + return axesActor; + } +} diff --git a/webviews/viewer/src/lib/interaction/CameraManager.ts b/webviews/viewer/src/lib/interaction/CameraManager.ts new file mode 100644 index 0000000..184f651 --- /dev/null +++ b/webviews/viewer/src/lib/interaction/CameraManager.ts @@ -0,0 +1,158 @@ +import { VtkApp } from '../core/VtkApp'; +import { AxesCreator } from './AxesCreator'; +import { zoomRatio, isAtDefaultZoom } from '../state'; +import type { Group } from '../data/Group'; + +export class CameraManager { + private static _i: CameraManager; + private camera: any; + private initialDistance = 0; + private lastDistance = 0; + nodesGroups: Record = {}; + faceGroups: Record = {}; + private orientationWidget: any; + + static get Instance(): CameraManager { + if (!this._i) { + this._i = new CameraManager(); + } + return this._i; + } + + init(groups: Record): void { + this.nodesGroups = {}; + this.faceGroups = {}; + + const renderer = VtkApp.Instance.getRenderer(); + this.camera = renderer.getActiveCamera(); + this.initialDistance = this.camera.getDistance(); + this.lastDistance = this.initialDistance; + + for (const [groupName, group] of Object.entries(groups)) { + if (!group.isFaceGroup) { + this.nodesGroups[groupName] = group; + group.setSize(this.lastDistance); + } else if (group.cellCount !== null) { + this.faceGroups[groupName] = group; + group.updateEdgeVisibility(this.lastDistance, this.initialDistance); + } + } + + this._updateZoomIndicator(this.initialDistance); + this.createAxisMarker(); + this.activateSizeUpdate(); + } + + private activateSizeUpdate(): void { + this.camera.onModified(() => { + const currentDistance = this.camera.getDistance(); + this._updateZoomIndicator(currentDistance); + if (Math.abs(currentDistance - this.lastDistance) > 1e-2) { + for (const nodeGroup of Object.values(this.nodesGroups)) { + nodeGroup.setSize(currentDistance); + } + for (const faceGroup of Object.values(this.faceGroups)) { + faceGroup.updateEdgeVisibility(currentDistance, this.initialDistance); + } + this.lastDistance = currentDistance; + } + }); + } + + private _updateZoomIndicator(currentDistance: number): void { + const ratio = this.initialDistance / currentDistance; + let text: string; + if (ratio >= 10) text = `${Math.round(ratio)}×`; + else if (ratio >= 1) text = `${ratio.toFixed(1)}×`; + else text = `${ratio.toFixed(2)}×`; + + zoomRatio.set(ratio); + isAtDefaultZoom.set(Math.abs(ratio - 1) < 0.01); + + const zoomIndicator = document.getElementById('zoomIndicator'); + if (zoomIndicator) zoomIndicator.textContent = text; + } + + resetZoom(): void { + VtkApp.Instance.getRenderer().resetCamera(); + VtkApp.Instance.updateCameraOffset(); + } + + setZoom(ratio: number): void { + const focalPoint = this.camera.getFocalPoint(); + const position = this.camera.getPosition(); + const dx = position[0] - focalPoint[0]; + const dy = position[1] - focalPoint[1]; + const dz = position[2] - focalPoint[2]; + const currentDist = Math.sqrt(dx * dx + dy * dy + dz * dz); + const scale = this.initialDistance / ratio / currentDist; + this.camera.setPosition( + focalPoint[0] + dx * scale, + focalPoint[1] + dy * scale, + focalPoint[2] + dz * scale + ); + VtkApp.Instance.getRenderer().resetCameraClippingRange(); + VtkApp.Instance.updateCameraOffset(); + } + + refreshEdgeVisibility(): void { + for (const faceGroup of Object.values(this.faceGroups)) { + faceGroup.updateEdgeVisibility(this.lastDistance, this.initialDistance); + } + VtkApp.Instance.getRenderWindow().render(); + } + + setOrientationWidgetVisible(visible: boolean): void { + this.orientationWidget.setEnabled(visible); + VtkApp.Instance.getRenderWindow().render(); + } + + setCameraAxis(axis: string): void { + if (!this.camera) { + return; + } + + const focalPoint = this.camera.getFocalPoint(); + const distance = this.camera.getDistance(); + + let newPosition = [0, 0, 0]; + let viewUp = [0, 0, 1]; + + switch (axis.toLowerCase()) { + case 'x': + newPosition = [focalPoint[0] + distance, focalPoint[1], focalPoint[2]]; + break; + case 'y': + newPosition = [focalPoint[0], focalPoint[1] + distance, focalPoint[2]]; + break; + case 'z': + newPosition = [focalPoint[0], focalPoint[1], focalPoint[2] + distance]; + viewUp = [0, 1, 0]; + break; + default: + return; + } + + this.camera.setPosition(...newPosition); + this.camera.setViewUp(viewUp); + VtkApp.Instance.getRenderer().resetCameraClippingRange(); + VtkApp.Instance.getRenderWindow().render(); + } + + private createAxisMarker(): any { + const axes = AxesCreator.createCustomAxesActor(); + + const widget = vtk.Interaction.Widgets.vtkOrientationMarkerWidget.newInstance({ + actor: axes, + interactor: VtkApp.Instance.getRenderWindow().getInteractor(), + }); + widget.setEnabled(true); + widget.setViewportCorner( + vtk.Interaction.Widgets.vtkOrientationMarkerWidget.Corners.BOTTOM_RIGHT + ); + widget.setViewportSize(0.15); + + this.orientationWidget = widget; + return axes; + } +} diff --git a/webviews/viewer/src/lib/settings/GlobalSettings.ts b/webviews/viewer/src/lib/settings/GlobalSettings.ts new file mode 100644 index 0000000..8c37640 --- /dev/null +++ b/webviews/viewer/src/lib/settings/GlobalSettings.ts @@ -0,0 +1,117 @@ +import type { EdgeMode } from '../state'; + +export class GlobalSettings { + private static _instance: GlobalSettings; + + static get Instance(): GlobalSettings { + if (!this._instance) { + this._instance = new GlobalSettings(); + } + return this._instance; + } + + grpIndex = 0; + objIndex = 0; + + backgroundColor = [0.6627, 0.796, 0.91]; + ambientLightColor = [0.2, 0.2, 0.2]; + lightColor = [0.6667, 0.6667, 0.6667]; + surfaceInsideColor = [1, 1, 0]; + surfaceOutsideColor = [0.537, 0.529, 0.529]; + localSelectedColor = [1, 1, 1]; + surfaceTransparentColor = [0.553, 0.749, 0.42]; + surfaceRenderOrder = 0; + wireframeColor = [0, 0, 0]; + wireframeOpacity = 0.35; + wireframeAlpha = 1; + wireframeRenderOrder = 10; + wireframeSelectedColor = [1, 1, 1]; + wireframeSelectedRenderOrder = 11; + drawLineColor = [1, 0, 0]; + drawLineHelperRenderOrder = 12; + selectHelperColor = [1, 1, 1]; + selectionPointColor = [1, 0, 0]; + + hiddenObjectOpacity = 0; + edgeMode: EdgeMode = 'threshold'; + edgeThresholdMultiplier = 1; + specular = 0.3; + specularPower = 15; + ambientIntensity = 0.1; + edgeOpacity = 0.7; + groupTransparency = 0.2; + showOrientationWidget = true; + + get isDark(): boolean { + return ( + document.body.classList.contains('vscode-dark') || + document.body.classList.contains('vscode-high-contrast') + ); + } + + private _meshGroupColors = [ + [0.902, 0.098, 0.294], + [0.235, 0.706, 0.294], + [1, 0.882, 0.098], + [0.941, 0.196, 0.902], + [0.961, 0.51, 0.192], + [0.569, 0.118, 0.706], + [0.275, 0.941, 0.941], + [0.737, 0.965, 0.047], + [0.98, 0.745, 0.745], + [0, 0.502, 0.502], + [0.902, 0.745, 1], + [0.604, 0.388, 0.141], + [0.263, 0.388, 0.847], + [1, 0.98, 0.784], + [0.502, 0, 0], + [0.667, 1, 0.764], + [0.502, 0.502, 0], + [1, 0.847, 0.694], + [0, 0, 0.463], + [0.502, 0.502, 0.502], + ]; + + get meshGroupColors(): number[][] { + if (this.isDark) return this._meshGroupColors; + return this._meshGroupColors.map(([r, g, b]) => [r * 0.72, g * 0.72, b * 0.72]); + } + + getColorForGroup(): number[] { + const idx = this.grpIndex % this._meshGroupColors.length; + this.grpIndex++; + return this.meshGroupColors[idx]; + } + + private _objectColorsLight = [ + [0.4, 0.62, 0.82], + [0.28, 0.7, 0.58], + [0.88, 0.56, 0.28], + [0.6, 0.4, 0.8], + [0.38, 0.72, 0.42], + [0.82, 0.38, 0.44], + [0.38, 0.68, 0.82], + [0.82, 0.62, 0.38], + ]; + + private _objectColorsDark = [ + [0.44, 0.72, 0.98], + [0.24, 0.88, 0.7], + [0.98, 0.66, 0.32], + [0.72, 0.5, 0.98], + [0.4, 0.9, 0.5], + [0.98, 0.42, 0.52], + [0.36, 0.8, 0.98], + [0.98, 0.74, 0.44], + ]; + + get objectColors(): number[][] { + return this.isDark ? this._objectColorsDark : this._objectColorsLight; + } + + getColorForObject(): number[] { + const idx = this.objIndex % this.objectColors.length; + this.objIndex++; + return this.objectColors[idx]; + } +} diff --git a/webviews/viewer/src/lib/state.ts b/webviews/viewer/src/lib/state.ts new file mode 100644 index 0000000..f1cc5f5 --- /dev/null +++ b/webviews/viewer/src/lib/state.ts @@ -0,0 +1,31 @@ +import { writable } from 'svelte/store'; + +export type GroupHierarchy = Record; +export type HighlightedGroups = Map; +export type HiddenObjects = Set; + +export type EdgeMode = 'gradual' | 'threshold' | 'show' | 'hide'; + +export interface Settings { + hiddenObjectOpacity: number; + edgeMode: EdgeMode; + edgeThresholdMultiplier: number; + groupTransparency: number; + showOrientationWidget: boolean; +} + +export const groupHierarchy = writable({}); +export const highlightedGroups = writable(new Map()); +export const hiddenObjects = writable(new Set()); +export const zoomRatio = writable(1); +export const isAtDefaultZoom = writable(true); +export const settings = writable({ + hiddenObjectOpacity: 0, + edgeMode: 'threshold', + edgeThresholdMultiplier: 1, + groupTransparency: 0.2, + showOrientationWidget: true, +}); + +// Map> — groups NOT shown in sidebar (hidden) +export const sidebarHiddenGroups = writable>>(new Map()); diff --git a/webviews/viewer/src/lib/ui/CustomDropdown.ts b/webviews/viewer/src/lib/ui/CustomDropdown.ts new file mode 100644 index 0000000..5134a2c --- /dev/null +++ b/webviews/viewer/src/lib/ui/CustomDropdown.ts @@ -0,0 +1,113 @@ +export interface DropdownOption { + value: string; + label: string; +} + +export class CustomDropdown { + private _trigger: HTMLElement; + private _options: DropdownOption[]; + private _onSelect: (value: string) => void; + private _getValue: (() => string | null) | null; + private _align: 'left' | 'right'; + private _panel: HTMLElement | null = null; + + constructor( + trigger: HTMLElement, + options: DropdownOption[], + onSelect: (value: string) => void, + getValue: (() => string | null) | null = null, + opts: { align?: 'left' | 'right' } = {} + ) { + this._trigger = trigger; + this._options = options; + this._onSelect = onSelect; + this._getValue = getValue; + this._align = opts.align ?? 'left'; + + trigger.addEventListener('click', (e) => { + e.stopPropagation(); + this._panel ? this.close() : this._open(); + }); + document.addEventListener('click', () => this.close()); + } + + private _open(): void { + const currentValue = this._getValue?.(); + const showCheckmarks = this._getValue != null; + + const panel = document.createElement('div'); + panel.style.cssText = ` + position: fixed; + z-index: 9999; + background: var(--ui-popup-bg); + border: 1px solid var(--ui-border); + border-radius: 4px; + box-shadow: 0 4px 16px rgba(0,0,0,0.25); + padding: 3px 0; + overflow: hidden; + `; + panel.addEventListener('click', (e) => e.stopPropagation()); + + for (const { value, label } of this._options) { + const isSelected = value === currentValue; + const item = document.createElement('div'); + item.style.cssText = ` + display: flex; + align-items: center; + gap: 8px; + padding: 5px 10px; + font-size: 0.75rem; + cursor: pointer; + color: var(--ui-fg); + white-space: nowrap; + ${this._align === 'right' ? 'justify-content: flex-end;' : ''} + ${isSelected ? 'font-weight: 600;' : ''} + `; + + if (showCheckmarks) { + const check = document.createElement('span'); + check.textContent = '✓'; + check.style.cssText = `font-size: 0.6rem; flex-shrink: 0; width: 10px; opacity: ${isSelected ? 1 : 0};`; + item.appendChild(check); + } + + const labelEl = document.createElement('span'); + labelEl.textContent = label; + item.appendChild(labelEl); + + item.addEventListener('mouseenter', () => { + item.style.background = 'var(--ui-element-bg-hover)'; + }); + item.addEventListener('mouseleave', () => { + item.style.background = ''; + }); + item.addEventListener('click', () => { + this._onSelect(value); + this.close(); + }); + + panel.appendChild(item); + } + + document.body.appendChild(panel); + + const rect = this._trigger.getBoundingClientRect(); + const panelW = Math.max(panel.offsetWidth, rect.width); + const panelH = panel.offsetHeight; + panel.style.minWidth = `${panelW}px`; + + let left = rect.left + rect.width / 2 - panelW / 2; + left = Math.max(4, Math.min(left, window.innerWidth - panelW - 4)); + panel.style.left = `${left}px`; + + const openUp = window.innerHeight - rect.bottom < panelH + 8; + panel.style.top = openUp ? `${rect.top - panelH - 4}px` : `${rect.bottom + 4}px`; + + this._panel = panel; + } + + close(): void { + this._panel?.remove(); + this._panel = null; + } +} diff --git a/webviews/viewer/src/lib/vtk.d.ts b/webviews/viewer/src/lib/vtk.d.ts new file mode 100644 index 0000000..4cb6f92 --- /dev/null +++ b/webviews/viewer/src/lib/vtk.d.ts @@ -0,0 +1,5 @@ +declare const vtk: any; + +interface Window { + vtk: any; +} diff --git a/webviews/viewer/src/main.ts b/webviews/viewer/src/main.ts new file mode 100644 index 0000000..08f6f9e --- /dev/null +++ b/webviews/viewer/src/main.ts @@ -0,0 +1,63 @@ +import { mount } from 'svelte'; +import App from './components/App.svelte'; +import { Controller } from './lib/Controller'; +import { VisibilityManager } from './lib/commands/VisibilityManager'; +import { CameraManager } from './lib/interaction/CameraManager'; +import { GlobalSettings } from './lib/settings/GlobalSettings'; +import { settings } from './lib/state'; +import type { EdgeMode } from './lib/state'; +import './app.css'; + +declare function acquireVsCodeApi(): { + postMessage(msg: unknown): void; + getState(): unknown; + setState(state: unknown): void; +}; + +const vscode = acquireVsCodeApi(); +const scene = document.getElementById('scene')!; + +mount(App, { target: document.getElementById('app')! }); + +Controller.Instance.init(scene, vscode); + +window.addEventListener('message', async (e) => { + const { type, body } = e.data; + + switch (type) { + case 'init': { + Controller.Instance.loadFiles(body.fileContexts, body.objFilenames); + if (body.settings) { + const s = body.settings; + if (s.hiddenObjectOpacity !== undefined) + GlobalSettings.Instance.hiddenObjectOpacity = s.hiddenObjectOpacity; + if (s.edgeMode !== undefined) GlobalSettings.Instance.edgeMode = s.edgeMode as EdgeMode; + if (s.edgeThresholdMultiplier !== undefined) + GlobalSettings.Instance.edgeThresholdMultiplier = s.edgeThresholdMultiplier; + if (s.groupTransparency !== undefined) + GlobalSettings.Instance.groupTransparency = s.groupTransparency; + if (s.showOrientationWidget !== undefined) + GlobalSettings.Instance.showOrientationWidget = s.showOrientationWidget; + settings.update((cur) => ({ + hiddenObjectOpacity: s.hiddenObjectOpacity ?? cur.hiddenObjectOpacity, + edgeMode: (s.edgeMode ?? cur.edgeMode) as EdgeMode, + edgeThresholdMultiplier: s.edgeThresholdMultiplier ?? cur.edgeThresholdMultiplier, + groupTransparency: s.groupTransparency ?? cur.groupTransparency, + showOrientationWidget: s.showOrientationWidget ?? cur.showOrientationWidget, + })); + VisibilityManager.Instance.applyHiddenObjectOpacity(); + CameraManager.Instance.refreshEdgeVisibility(); + if (s.showOrientationWidget === false) { + CameraManager.Instance.setOrientationWidgetVisible(false); + } + } + break; + } + + case 'displayGroup': + VisibilityManager.Instance.setVisibility(body.group, body.visible); + break; + } +}); + +vscode.postMessage({ type: 'ready' }); diff --git a/webviews/viewer/svelte.config.js b/webviews/viewer/svelte.config.js new file mode 100644 index 0000000..4c6b24b --- /dev/null +++ b/webviews/viewer/svelte.config.js @@ -0,0 +1,5 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +export default { + preprocess: vitePreprocess(), +}; diff --git a/webviews/viewer/tsconfig.json b/webviews/viewer/tsconfig.json new file mode 100644 index 0000000..c7942f0 --- /dev/null +++ b/webviews/viewer/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ESNext", "DOM"], + "moduleResolution": "bundler", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowImportingTsExtensions": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/webviews/viewer/vite.config.ts b/webviews/viewer/vite.config.ts new file mode 100644 index 0000000..cb6d765 --- /dev/null +++ b/webviews/viewer/vite.config.ts @@ -0,0 +1,28 @@ +import { defineConfig } from 'vite'; +import { svelte } from '@sveltejs/vite-plugin-svelte'; +import tailwindcss from '@tailwindcss/vite'; +import { resolve } from 'path'; +import { createRequire } from 'module'; + +const require = createRequire(import.meta.url); +const pkg = require('../../package.json'); + +export default defineConfig({ + define: { + __APP_VERSION__: JSON.stringify(pkg.version), + }, + root: resolve(__dirname), + base: './', + build: { + outDir: resolve(__dirname, 'dist'), + emptyOutDir: true, + rollupOptions: { + output: { + entryFileNames: 'assets/index.js', + chunkFileNames: 'assets/[name].js', + assetFileNames: 'assets/index.[ext]', + }, + }, + }, + plugins: [svelte(), tailwindcss()], +});