diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 0000000..8e97178
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,105 @@
+/* eslint-env node */
+
+const { defineConfig } = require('eslint-define-config');
+const prettierConfig = require('./.prettierrc.js');
+
+module.exports = defineConfig({
+ root: true,
+ env: {
+ browser: true,
+ es6: true,
+ node: true,
+ jest: true,
+ },
+ extends: [
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/eslint-recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:import/recommended',
+ 'plugin:import/electron',
+ 'plugin:import/typescript',
+ 'prettier',
+ '@vue/eslint-config-typescript',
+ 'plugin:vue/vue3-essential',
+ 'plugin:vuejs-accessibility/recommended',
+ ],
+ plugins: ['prettier', 'vuejs-accessibility', '@typescript-eslint'],
+ parser: 'vue-eslint-parser',
+ parserOptions: {
+ parser: '@typescript-eslint/parser',
+ ecmaVersion: 2020,
+ sourceType: 'module',
+ },
+ rules: {
+ indent: [
+ 'error',
+ 2,
+ {
+ SwitchCase: 1,
+ },
+ ],
+ 'max-len': [
+ 'error',
+ {
+ code: 120,
+ },
+ ],
+ 'no-console': [
+ 'error',
+ {
+ allow: ['warn', 'error'],
+ },
+ ],
+ 'comma-dangle': ['error', 'always-multiline'],
+ 'space-before-function-paren': [
+ 'warn',
+ {
+ anonymous: 'ignore',
+ named: 'never',
+ asyncArrow: 'always',
+ },
+ ],
+ 'prettier/prettier': [
+ 'error',
+ {
+ ...prettierConfig,
+ },
+ ],
+ 'vue/html-indent': ['error', 2],
+ 'vue/multiline-html-element-content-newline': 'off',
+ 'vue/multi-word-component-names': 'off',
+ 'vue/max-attributes-per-line': 0,
+ 'vue/require-default-prop': 0,
+ 'vue/no-multiple-template-root': 0,
+ '@typescript-eslint/no-unused-vars': [
+ 'warn',
+ {
+ varsIgnorePattern: '^_$',
+ argsIgnorePattern: '^_$',
+ },
+ ],
+ },
+ settings: {
+ 'import/resolver': {
+ typescript: {
+ alwaysTryTypes: true,
+ project: './tsconfig.json',
+ },
+ },
+ },
+ ignorePatterns: ['*.test.ts'],
+ overrides: [
+ {
+ files: ['tests/**/*'],
+ env: {
+ jest: true,
+ },
+ },
+ {
+ files: ['*.vue'],
+ rules: {
+ 'max-len': 'off',
+ },
+ },
+ ],
+});
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 1391624..0000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "env": {
- "browser": true,
- "es6": true,
- "node": true
- },
- "extends": [
- "eslint:recommended",
- "plugin:@typescript-eslint/eslint-recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:import/recommended",
- "plugin:import/electron",
- "plugin:import/typescript"
- ],
- "parser": "@typescript-eslint/parser",
- "rules": {
- "indent": [
- "error",
- 2,
- {
- "SwitchCase": 1
- }
- ],
- "max-len": [
- "error",
- {
- "code": 120
- }
- ],
- "no-console": [
- "error",
- {
- "allow": [
- "warn",
- "error"
- ]
- }
- ]
- },
- "ignorePatterns": [
- "*.test.ts"
- ],
- "overrides": [
- {
- "files": [
- "tests/**/*"
- ],
- "env": {
- "jest": true
- }
- }
- ]
-}
diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
index d2b0636..99d489f 100644
--- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md
+++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
@@ -6,9 +6,8 @@ about: "Report something that's broken."
-- Sentinel Version: 1.0.5
-- PHP Version: 7.4.13 / 8.0.2
-- Database Driver & Version: MySQL 5.7
+- Comet Version: 2.0.4
+- TypeScript Version: 4.5.4
### Description
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..2c84d91
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,32 @@
+name: Lint
+
+on:
+ push:
+ branches:
+ - main
+ - release
+ - feature/*
+ pull_request:
+ branches:
+ - main
+ - release
+ - feature/*
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+
+ - name: Set up Node.js
+ uses: actions/setup-node@v2
+ with:
+ node-version: '20'
+
+ - name: Install dependencies
+ run: npm install
+
+ - name: Lint app
+ run: npm run lint
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..ded82e2
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+auto-install-peers = true
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 91a2761..0000000
--- a/.prettierrc
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "semi": true,
- "trailingComma": "all",
- "singleQuote": true,
- "printWidth": 120,
- "tabWidth": 2,
- "useTabs": false,
- "endOfLine": "auto"
-}
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 0000000..e0e7a5d
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,10 @@
+module.exports = {
+ semi: true,
+ trailingComma: 'all',
+ singleQuote: true,
+ printWidth: 120,
+ tabWidth: 2,
+ useTabs: false,
+ endOfLine: 'auto',
+ spaceBeforeFunctionParen: false
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 72446f4..25fa621 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,3 @@
{
- "typescript.tsdk": "node_modules/typescript/lib"
+ "typescript.tsdk": "node_modules/typescript/lib"
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 926cb9a..f7a20da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,30 @@
# Release Notes
-## [Unreleased](https://github.com/stellar-comet/comet/compare/v1.0.0...HEAD)
+## [Unreleased](https://github.com/stellar-comet/comet/compare/v2.0.4...HEAD)
+
+## [v2.0.4](https://github.com/stellar-comet/comet/compare/v1.0.0...v2.0.4) - 2024-09-14
+
+### Added
+
+- Dark mode
+- Multi-language support
+- Audio conversion support
+
+### Changed
+
+- Improved UI design with better user experience
+- Improved conversion performance withy less resource usage
+- Improved conversion quality with better audio quality
+
+### Fixed
+
+- Non-persistent state issue
+- Conversion issue with some video files on some platforms and architectures
+- Conversion quality issue with some video files
+- High resource usage issue
+- Removed files would still be included in conversion queue
+
+**Full Changelog**: https://github.com/stellar-comet/comet/compare/v1.0.0...v2.0.4
## [v1.0.0](https://github.com/stellar-comet/comet/compare/v0.0.3...v1.0.0) - 2024-09-02
diff --git a/README.md b/README.md
index f5bfb7d..57fad2b 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
@@ -8,54 +8,69 @@
> [!WARNING]
-> We don't have an Apple Developer account yet, and the application is not code-signed for both Mac and Windows. Therefore, the applications will show a warning popup on the first start. On Mac, click **Okay**, then go to **Settings / Privacy & Security** and scroll down until you see a button **Open anyway**. You'll have to do this once. On Windows, you may see a warning message indicating that the app is from an unknown publisher. Click **More info** and then **Run anyway** to proceed.
+> **We don't have an Apple Developer account yet, and the application is not code-signed for both Mac and Windows. Therefore, the applications will show a warning popup on the first start.**
+> On **Mac**, click **Okay**, then go to **Settings / Privacy & Security** and scroll down until you see a button **Open anyway**.
+> On **Windows**, you may see a warning message indicating that the app is from an unknown publisher. Click **More info** and then **Run anyway** to proceed.
+
+---
## About Comet
-**Comet** is a cross-platform video and audio converter application designed to make media conversion as easy and accessible as possible. Leveraging the power of [FFmpeg](https://ffmpeg.org/), Comet allows users to convert video and audio files into a variety of formats, all within a simple, intuitive interface.
+**Comet** is a cross-platform media converter application designed to make the conversion of video, audio, and image files as easy and accessible as possible. Built on top of [FFmpeg](https://ffmpeg.org/), **Jimp**, and **Electron**, Comet offers a seamless and efficient user experience for media conversions, all within a simple, intuitive interface.
![Comet UI 1](./assets/screenshot_1.png)
![Comet UI 2](./assets/screenshot_2.png)
![Comet UI 3](./assets/screenshot_3.png)
![Comet UI 4](./assets/screenshot_4.png)
+---
+
## Project Overview
-Comet's goal is to provide a free, user-friendly, and visually appealing application for converting video and audio files. Whether you need to convert a single file or multiple files at once, Comet is here to help.
+Comet's goal is to provide a **free, user-friendly, and visually appealing** application for converting media files. Whether you need to convert a single file or multiple files at once, Comet is designed to make the process straightforward.
### Key Features
-- **Cross-Platform Compatibility:** Runs on macOS, Windows, and Linux.
-- **Video and Audio Conversion:** Supports conversion to a wide range of video formats (MP4, MKV, AVI, MOV, etc.) and audio formats (MP3, WAV, AAC, FLAC, etc.).
+- **Cross-Platform Compatibility:** Works seamlessly on macOS, Windows, and Linux.
+- **Video, Audio, and Image Conversion:**
+ - Video formats: MP4, MKV, AVI, MOV, etc.
+ - Audio formats: MP3, WAV, AAC, FLAC, etc.
+ - Image formats: JPEG, PNG, BMP, ICO, ICNS, etc.
- **Bulk File Conversion:** Easily upload and convert multiple files in one go.
-- **User-Friendly Interface:** A clean and intuitive UI that simplifies the conversion process.
-- **Real-Time Conversion Feedback:** Conversion progress is tracked and displayed to the user, with real-time updates and error handling.
-- **Fast Conversion:** Powered by FFmpeg, known for its speed and efficiency in media processing.
-- **Dark Mode:** Provides a dark theme for users who prefer a more comfortable visual experience.
+- **Real-Time Progress Tracking:** Track the progress of each conversion with real-time feedback.
+- **Dark Mode:** A sleek dark theme for more comfortable use.
- **Multi-Language Support:** Available in multiple languages for a global audience.
+- **Cancel/Resume Conversions:** Cancel ongoing conversions, with options to manage individual items in the queue.
+- **Jimp and FFmpeg Integration:** Use Jimp for images and FFmpeg for audio/video conversion.
+
+---
-### Current Status
+## Recent Updates
-The project has made significant progress:
+- **Unified Conversion Handler:** We’ve refactored the media conversion process to use an **Adapter Pattern**, allowing for a unified conversion handler for video, audio, and image files using either **FFmpeg** or **Jimp** depending on the file type.
+- **Advanced Testing:** Expanded unit tests using **Jest** to cover media conversion handlers and IPC processes.
+- **Improved Performance:** Faster conversions through optimizations to how we handle bulk file uploads and media processing queues.
+- **Enhanced UI and UX:** More responsive interface and clearer progress tracking for large file batches.
-- **Basic UI and Core Functionality:** The user interface is fully implemented, supporting bulk file uploads, conversion status tracking, and real-time feedback.
-- **FFmpeg Integration:** The core video and audio conversion functionality is complete, making the app fully functional.
-- **Cross-Platform Distributables:** Distributables for macOS, Windows, and Linux have been successfully created. However, due to the high cost of an Apple Developer membership, the app is currently not code-signed or notarized for macOS, which may present challenges when running it on Mac devices.
+---
## Technologies Used
- **Electron:** For building the cross-platform desktop application.
- **Vue.js (with Composition API and TypeScript):** For the frontend UI.
-- **FFmpeg:** The core engine for video and audio format conversion.
-- **Node.js:** Backend services and script automation.
-- **Vite:** For fast and modern build tooling.
+- **FFmpeg & Jimp:** Core engines for media conversion (video/audio via FFmpeg, images via Jimp).
+- **Node.js:** Backend services and media processing.
+- **Vite:** Modern build tool for fast development.
- **Tailwind CSS:** For styling and responsive design.
+- **i18n:** Internationalization for multi-language support.
- **Jest:** For unit testing.
-- **GitHub Actions:** For CI/CD and release automation.
+- **GitHub Actions:** Continuous Integration/Continuous Deployment (CI/CD) and release automation.
+
+---
-### Getting Started
+## Getting Started
-To get started with development:
+To get started with Comet:
1. **Clone the repository:**
@@ -83,59 +98,53 @@ To get started with development:
```
5. **Test your changes:**
- - Ensure your changes do not break existing functionality.
- - Write unit tests if possible and applicable.
-## Roadmap
+ ```bash
+ npm run test
+ ```
-- **Phase 1:** Basic UI Implementation (Completed)
- - File upload functionality.
- - Simple file selection and list management.
+---
-- **Phase 2:** FFmpeg Integration (Completed)
- - Implement core conversion functionality.
- - Support for multiple video formats.
- - Real-time conversion feedback.
+## Roadmap
-- **Phase 3:** UI Enhancements and Customization Options (Completed)
- - Output format selection and settings.
- - Batch processing capabilities.
+- **Phase 1:** Basic UI Implementation (Completed)
+ - File upload functionality, file list management.
-- **Phase 4:** Cross-Platform Testing and Release (In Progress)
- - Test and refine the app on macOS, Windows, and Linux.
- - **Package the app for distribution** on various platforms.
- - **Overcome code signing challenges**, particularly on macOS due to the cost of an Apple Developer membership.
- - Prepare for the first public release.
+- **Phase 2:** FFmpeg & Jimp Integration (Completed)
+ - Core conversion functionality for video, audio, and images.
-## Support
+- **Phase 3:** UI Enhancements (Completed)
+ - Improved conversion progress tracking and batch conversion options.
-If you find this project helpful or interesting, please consider giving it a ⭐. Your support and feedback are greatly appreciated!
+- **Phase 4:** Cross-Platform Testing and Releases (In Progress)
+ - Testing on macOS, Windows, and Linux.
+ - Package the app for distribution across platforms.
+ - Address macOS code-signing challenges (currently blocked by lack of Apple Developer account).
-## Contributors
+---
-- **Jerome Thayananthajothy** - Project Lead & Developer
-- [**Contributors List**](https://github.com/stellar-comet/comet/graphs/contributors) - A big thank you to all the amazing contributors!
+## Contributing
-## How to Contribute
+Contributions are welcome! Here’s how you can contribute:
-We welcome contributions and collaboration! Whether you're a seasoned developer or just starting out, there's a place for you in our project. Here's how you can help:
+1. **Fork the Repository:** Create a fork of this repository.
+2. **Clone the Repo:** Clone the forked repository to your local machine.
+3. **Create a Branch:** Create a new branch for your feature or fix.
+4. **Make Your Changes:** Ensure your changes work as expected and pass tests.
+5. **Submit a Pull Request:** Once done, submit a PR to the `main` branch.
+6. **Star the Repo:** If you like Comet, please give it a ⭐!
-1. **Fork the Repository:** Start by forking this repository to your GitHub account.
-2. **Clone the Repo:** Clone the forked repo to your local machine using `git clone`.
-3. **Set Up the Environment:** Follow the steps below to get the project running on your local machine.
-4. **Create a Branch:** Create a new branch for the feature or fix you plan to work on.
-5. **Submit a Pull Request:** Once your changes are ready, submit a pull request to the `main` branch of this repository.
-6. **Star the Repository:** If you like this project, please give it a star on GitHub. It helps us gain visibility and grow our community!
+---
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
-## Acknowledgements
-
-- [FFmpeg](https://ffmpeg.org/) - The powerful multimedia framework that makes this project possible.
-- The Electron and Vue.js communities for their fantastic tools and support.
-
---
-Thank you for visiting our project! We’re excited to bring this tool to life and make media conversion easy and accessible for everyone. Any help, be it in coding, testing, or simply providing feedback, is invaluable. Let's create something great together!
+## Acknowledgements
+
+- [FFmpeg](https://ffmpeg.org/) - The powerful multimedia framework that powers video/audio conversion in Comet.
+- [Jimp](https://github.com/oliver-moran/jimp) - Image processing in Comet.
+- [Electron](https://www.electronjs.org/) - For building cross-platform desktop apps.
+- The [Vue.js](https://vuejs.org/) and [Tailwind CSS](https://tailwindcss.com/) communities for their fantastic tools and support.
diff --git a/assets/Banner.jpg b/assets/Banner.jpg
index 4cc8577..197e1b2 100644
Binary files a/assets/Banner.jpg and b/assets/Banner.jpg differ
diff --git a/assets/Profile.png b/assets/Profile.png
index 7d22400..31ed565 100644
Binary files a/assets/Profile.png and b/assets/Profile.png differ
diff --git a/assets/icon-1024.png b/assets/icon-1024.png
new file mode 100644
index 0000000..ff438ac
Binary files /dev/null and b/assets/icon-1024.png differ
diff --git a/assets/icon-256.png b/assets/icon-256.png
index 4e58478..8a9613d 100644
Binary files a/assets/icon-256.png and b/assets/icon-256.png differ
diff --git a/assets/icon-512.png b/assets/icon-512.png
index 7c46aae..3abd76c 100644
Binary files a/assets/icon-512.png and b/assets/icon-512.png differ
diff --git a/assets/icon-scaffold.png b/assets/icon-scaffold.png
deleted file mode 100644
index 93e00ae..0000000
Binary files a/assets/icon-scaffold.png and /dev/null differ
diff --git a/assets/icons/Win-Icon.ico b/assets/icons/Win-Icon.ico
new file mode 100644
index 0000000..afb3847
Binary files /dev/null and b/assets/icons/Win-Icon.ico differ
diff --git a/assets/icons/icon-256.png b/assets/icons/icon-256.png
new file mode 100644
index 0000000..326ee7e
Binary files /dev/null and b/assets/icons/icon-256.png differ
diff --git a/assets/icons/icon.icns b/assets/icons/icon.icns
index b298c69..b4fff93 100644
Binary files a/assets/icons/icon.icns and b/assets/icons/icon.icns differ
diff --git a/assets/icons/icon.ico b/assets/icons/icon.ico
deleted file mode 100644
index 9fbb25d..0000000
Binary files a/assets/icons/icon.ico and /dev/null differ
diff --git a/assets/icons/icon.png b/assets/icons/icon.png
index 9eaec08..41d48c2 100644
Binary files a/assets/icons/icon.png and b/assets/icons/icon.png differ
diff --git a/assets/icons/icon@2x.icns b/assets/icons/icon@2x.icns
index 2a17fe4..5a4ecaa 100644
Binary files a/assets/icons/icon@2x.icns and b/assets/icons/icon@2x.icns differ
diff --git a/assets/icons/setup-icon.ico b/assets/icons/setup-icon.ico
index 5847645..13991ba 100644
Binary files a/assets/icons/setup-icon.ico and b/assets/icons/setup-icon.ico differ
diff --git a/assets/loading.gif b/assets/loading.gif
index b361140..f7d180a 100644
Binary files a/assets/loading.gif and b/assets/loading.gif differ
diff --git a/assets/logo.png b/assets/logo.png
deleted file mode 100644
index 6ff4957..0000000
Binary files a/assets/logo.png and /dev/null differ
diff --git a/assets/screenshot_1.png b/assets/screenshot_1.png
index 278a9d0..d6a9bb8 100644
Binary files a/assets/screenshot_1.png and b/assets/screenshot_1.png differ
diff --git a/assets/screenshot_2.png b/assets/screenshot_2.png
index 7e1d052..c777fdf 100644
Binary files a/assets/screenshot_2.png and b/assets/screenshot_2.png differ
diff --git a/assets/screenshot_3.png b/assets/screenshot_3.png
index 5d98aec..c0bad7c 100644
Binary files a/assets/screenshot_3.png and b/assets/screenshot_3.png differ
diff --git a/assets/screenshot_4.png b/assets/screenshot_4.png
index 6930a2b..1692056 100644
Binary files a/assets/screenshot_4.png and b/assets/screenshot_4.png differ
diff --git a/assets/screenshot_5.png b/assets/screenshot_5.png
index b055a6f..db0c959 100644
Binary files a/assets/screenshot_5.png and b/assets/screenshot_5.png differ
diff --git a/assets/screenshot_6.png b/assets/screenshot_6.png
index 267b6c4..d162ea8 100644
Binary files a/assets/screenshot_6.png and b/assets/screenshot_6.png differ
diff --git a/bin/converter.sh b/bin/converter.sh
index 07c2541..21173dc 100755
--- a/bin/converter.sh
+++ b/bin/converter.sh
@@ -1,19 +1,78 @@
#!/bin/bash
+# This script converts all .m4v files in a directory to .mp4 files using ffmpeg.
+
# Directory containing the .m4v files
DIRECTORY="./input"
+# Exit immediately if a command exits with a non-zero status
+set -e
+
+# Function to install ffmpeg
+install_ffmpeg() {
+ if [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS
+ if ! command -v brew &>/dev/null; then
+ echo "Homebrew is not installed. Please install Homebrew first."
+ exit 1
+ fi
+ echo "Installing ffmpeg using Homebrew..."
+ brew install ffmpeg
+ elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
+ # Linux
+ if command -v apt-get &>/dev/null; then
+ echo "Installing ffmpeg using apt-get..."
+ sudo apt-get update
+ sudo apt-get install -y ffmpeg
+ else
+ echo "Unsupported Linux distribution. Please install ffmpeg manually."
+ exit 1
+ fi
+ else
+ echo "Unsupported OS. Please install ffmpeg manually."
+ exit 1
+ fi
+}
+
+# Check if ffmpeg is installed
+if ! command -v ffmpeg &>/dev/null; then
+ echo "ffmpeg could not be found. Attempting to install ffmpeg..."
+ install_ffmpeg
+ if ! command -v ffmpeg &>/dev/null; then
+ echo "ffmpeg installation failed. Please install ffmpeg manually."
+ exit 1
+ fi
+fi
+
+# Check if the directory exists
+if [ ! -d "$DIRECTORY" ]; then
+ echo "Directory $DIRECTORY does not exist."
+ exit 1
+fi
+
+# Check if there are any .m4v files in the directory
+shopt -s nullglob
+m4v_files=("$DIRECTORY"/*.m4v)
+if [ ${#m4v_files[@]} -eq 0 ]; then
+ echo "No .m4v files found in $DIRECTORY."
+ exit 1
+fi
+
# Iterate over all .m4v files in the directory
-for FILE in "$DIRECTORY"/*.m4v; do
+for FILE in "${m4v_files[@]}"; do
# Extract the filename without extension
BASENAME=$(basename "$FILE" .m4v)
# Convert the .m4v file to .mp4 using ffmpeg
+ echo "Converting $FILE to $DIRECTORY/${BASENAME}.mp4..."
ffmpeg -i "$FILE" -c copy "$DIRECTORY/${BASENAME}.mp4"
# Optional: remove the original .m4v file if conversion is successful
if [ $? -eq 0 ]; then
- rm "$FILE"
+ echo "Conversion successful, removing $FILE..."
+ rm -v "$FILE"
+ else
+ echo "Conversion failed for $FILE."
fi
done
diff --git a/forge.config.ts b/forge.config.ts
index 069d27b..dd5248c 100644
--- a/forge.config.ts
+++ b/forge.config.ts
@@ -33,12 +33,12 @@ const config: ForgeConfig = {
appBundleId: 'com.thavarshan.comet',
appCategoryType: 'public.app-category.video',
asar: {
- unpack: "**/node_modules/{ffmpeg-static,ffprobe-static}/**",
+ unpack: '**/node_modules/{ffmpeg-static,ffprobe-static}/**',
},
win32metadata: {
CompanyName: author.name,
OriginalFilename: productName,
- }
+ },
},
rebuildConfig: {},
makers: [
@@ -50,11 +50,11 @@ const config: ForgeConfig = {
authors: author.name,
exe: `${productName}.exe`,
iconUrl: 'https://github.com/stellar-comet/comet/blob/main/assets/icons/icon.ico',
- loadingGif: path.resolve(__dirname, 'assets/loading.gif'),
+ loadingGif: path.resolve(__dirname, 'assets', 'loading.gif'),
noMsi: true,
setupExe: `${name}-${version}-${arch}-setup.exe`,
setupIcon: path.resolve(iconDir, 'setup-icon.ico'),
- certificateFile: path.resolve(__dirname, 'tools/certs/dev-cert.pfx'),
+ certificateFile: path.resolve(__dirname, 'tools', 'certs', 'dev-cert.pfx'),
certificatePassword: process.env.CERT_PASSWORD,
}),
},
@@ -91,7 +91,7 @@ const config: ForgeConfig = {
name: '@electron-forge/maker-rpm',
platforms: ['linux'],
config: commonLinuxConfig,
- }
+ },
],
plugins: [
new VitePlugin({
@@ -143,10 +143,10 @@ const config: ForgeConfig = {
prerelease: false,
draft: true,
force: true,
- generateReleaseNotes: true
- }
- }
- ]
+ generateReleaseNotes: true,
+ },
+ },
+ ],
};
export default config;
diff --git a/forge.env.d.ts b/forge.env.d.ts
index b6ec6ca..d8d42de 100644
--- a/forge.env.d.ts
+++ b/forge.env.d.ts
@@ -1,4 +1,10 @@
-export { }; // Make this a module
+import { Media } from '@/types/media';
+import { ColorMode } from '@/types/theme';
+import { VideoFormat } from '@/enum/video-format';
+import { AudioFormat } from '@/enum/audio-format';
+import { ImageFormat } from '@/enum/image-format';
+
+export {}; // Make this a module
declare global {
// This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Vite
@@ -26,11 +32,19 @@ declare global {
arch: string;
platform: NodeJS.Platform;
selectDirectory: () => Promise;
- getDesktopPath: () => string;
+ getSystemTheme: () => ColorMode;
+ getDesktopPath: () => Promise;
getFilePath: (file: File) => string;
cancelConversion: () => Promise;
cancelItemConversion: (id: number | string) => Promise;
- convertVideo: (id: string, filePath: string, outputFormat: string, saveDirectory: string) => Promise;
+ convertMedia: (
+ id: string,
+ filePath: string,
+ outputFormat: VideoFormat | AudioFormat | ImageFormat,
+ saveDirectory: string,
+ mediaType: Media,
+ ) => Promise;
+ send: (channel: string, ...args: unknown[]) => void;
on: (channel: string, callback: (event: Electron.IpcRendererEvent, ...args: unknown[]) => void) => void;
removeAllListeners: (channel: string) => void;
};
diff --git a/index.html b/index.html
index 9ecabe3..ec1671c 100644
--- a/index.html
+++ b/index.html
@@ -1,5 +1,5 @@
-
+
diff --git a/jest.config.ts b/jest.config.ts
index 7dcf140..d57fe1d 100644
--- a/jest.config.ts
+++ b/jest.config.ts
@@ -14,45 +14,28 @@ const config: Config = {
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/*.d.ts', '!**/*constants.ts'],
coveragePathIgnorePatterns: ['/node_modules/', '/tests/.*\\.(ts|js)$'],
coverageReporters: ['json', 'html', 'lcov'],
- moduleFileExtensions: [
- "js",
- "mjs",
- "cjs",
- "jsx",
- "ts",
- "tsx",
- "json",
- "node",
- "vue"
- ],
+ moduleFileExtensions: ['js', 'mjs', 'cjs', 'jsx', 'ts', 'tsx', 'json', 'node', 'vue'],
moduleNameMapper: {
- "^@/(.*)$": "/src/$1",
- "^@vue/test-utils": "/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js",
- "radix-vue": "/node_modules/radix-vue/dist/radix-vue.cjs.js",
+ '^@/(.*)$': '/src/$1',
+ '^@vue/test-utils': '/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js',
+ 'radix-vue': '/node_modules/radix-vue/dist/radix-vue.cjs.js',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
- "^.+\\.(svg|png|jpg|jpeg|gif)$": "jest-transform-stub",
-
+ '^.+\\.(svg|png|jpg|jpeg|gif)$': 'jest-transform-stub',
},
resetMocks: false,
resetModules: true,
setupFilesAfterEnv: ['/tests/setup.ts'],
- testEnvironment: "jsdom",
+ testEnvironment: 'jsdom',
testEnvironmentOptions: {
- customExportConditions: ["node", "node-addons"]
+ customExportConditions: ['node', 'node-addons'],
},
- testMatch: [
- "**/__tests__/**/*.[jt]s?(x)",
- "**/tests/**/?(*.)+(spec|test).[tj]s?(x)"
- ],
+ testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/tests/**/?(*.)+(spec|test).[tj]s?(x)'],
testPathIgnorePatterns: ['/.tmp/'],
transform: {
- "^.+\\.vue$": "@vue/vue3-jest",
- "^.+\\.ts?$": "ts-jest"
+ '^.+\\.vue$': '@vue/vue3-jest',
+ '^.+\\.ts?$': 'ts-jest',
},
- transformIgnorePatterns: [
- "/node_modules/",
- "\\.pnp\\.[^\\/]+$"
- ],
+ transformIgnorePatterns: ['/node_modules/', '\\.pnp\\.[^\\/]+$'],
};
export default config;
diff --git a/package-lock.json b/package-lock.json
index 6eaab8c..7754da2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "comet",
- "version": "2.0.4",
+ "version": "2.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "comet",
- "version": "2.0.4",
+ "version": "2.1.1",
"license": "MIT",
"dependencies": {
"@intlify/message-compiler": "^10.0.1",
@@ -18,6 +18,7 @@
"ffprobe-static": "^3.1.0",
"filesize": "^10.1.4",
"fluent-ffmpeg": "^2.1.3",
+ "jimp": "^1.6.0",
"lucide-vue-next": "^0.435.0",
"mobx": "^6.13.2",
"namor": "^2.0.2",
@@ -46,6 +47,7 @@
"@intlify/vue-i18n-loader": "^4.2.0",
"@jest/globals": "^29.7.0",
"@reforged/maker-appimage": "^3.3.0",
+ "@rushstack/eslint-patch": "^1.5.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/user-event": "^14.5.2",
@@ -58,22 +60,31 @@
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-vue": "^5.1.2",
+ "@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.6",
"@vue/vue3-jest": "^29.2.6",
"autoprefixer": "^10.4.20",
"electron": "32.0.1",
"electron-devtools-installer": "^3.2.0",
"eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-define-config": "^2.1.0",
+ "eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-prettier": "^5.2.1",
+ "eslint-plugin-vue": "^9.18.0",
+ "eslint-plugin-vuejs-accessibility": "^2.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.45",
+ "prettier": "^3.3.3",
"tailwindcss": "^3.4.10",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "~4.5.4",
- "vite": "^5.4.2"
+ "vite": "^5.4.2",
+ "vue-eslint-parser": "^9.3.2"
},
"engines": {
"node": ">= 20.10.0"
@@ -3762,6 +3773,430 @@
"node": ">=8"
}
},
+ "node_modules/@jimp/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/file-ops": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "await-to-js": "^3.0.0",
+ "exif-parser": "^0.1.12",
+ "file-type": "^16.0.0",
+ "mime": "3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/core/node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@jimp/diff": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz",
+ "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "pixelmatch": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/file-ops": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz",
+ "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-bmp": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz",
+ "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "bmp-ts": "^1.0.9"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-gif": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz",
+ "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "gifwrap": "^0.10.1",
+ "omggif": "^1.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-jpeg": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz",
+ "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "jpeg-js": "^0.4.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-png": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz",
+ "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "pngjs": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-tiff": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz",
+ "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "utif2": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-blit": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz",
+ "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-blur": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz",
+ "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/utils": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-circle": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz",
+ "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-color": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz",
+ "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "tinycolor2": "^1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-contain": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz",
+ "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-cover": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz",
+ "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-crop": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz",
+ "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-displace": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz",
+ "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-dither": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz",
+ "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-fisheye": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz",
+ "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-flip": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz",
+ "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-hash": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz",
+ "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/js-bmp": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/js-tiff": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "any-base": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-mask": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz",
+ "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-print": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz",
+ "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "parse-bmfont-ascii": "^1.0.6",
+ "parse-bmfont-binary": "^1.0.6",
+ "parse-bmfont-xml": "^1.1.6",
+ "simple-xml-to-json": "^1.2.2",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-quantize": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz",
+ "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==",
+ "license": "MIT",
+ "dependencies": {
+ "image-q": "^4.0.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-resize": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz",
+ "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-rotate": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz",
+ "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-threshold": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz",
+ "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-hash": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/types": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz",
+ "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==",
+ "license": "MIT",
+ "dependencies": {
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/utils": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz",
+ "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "tinycolor2": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
@@ -3868,6 +4303,16 @@
"node": ">= 8"
}
},
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
"node_modules/@npmcli/fs": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz",
@@ -4192,6 +4637,19 @@
"node": ">=14"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@reforged/maker-appimage": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@reforged/maker-appimage/-/maker-appimage-3.3.2.tgz",
@@ -4490,6 +4948,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz",
+ "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -4977,6 +5442,12 @@
"node": ">=8"
}
},
+ "node_modules/@tokenizer/token": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
+ "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
+ "license": "MIT"
+ },
"node_modules/@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@@ -5606,38 +6077,300 @@
"@vue/shared": "3.5.2"
}
},
- "node_modules/@vue/compiler-sfc": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.2.tgz",
- "integrity": "sha512-vErEtybSU290LbMW+ChYllI9tNJEdTW1oU+8cZWINZyjlWeTSa9YqDl4/pZJSnozOI+HmcaC1Vz2eFKmXNSXZA==",
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.2.tgz",
+ "integrity": "sha512-vErEtybSU290LbMW+ChYllI9tNJEdTW1oU+8cZWINZyjlWeTSa9YqDl4/pZJSnozOI+HmcaC1Vz2eFKmXNSXZA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.25.3",
+ "@vue/compiler-core": "3.5.2",
+ "@vue/compiler-dom": "3.5.2",
+ "@vue/compiler-ssr": "3.5.2",
+ "@vue/shared": "3.5.2",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.11",
+ "postcss": "^8.4.44",
+ "source-map-js": "^1.2.0"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.2.tgz",
+ "integrity": "sha512-vMtA4tQK/AM3UAYJsmouQzQpgG+h9TKiD5BV+Zt+ZyAMdicxzSEEFGWf/CykRnDpqj9fMfIHPhOezJVNxiXe2A==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.2",
+ "@vue/shared": "3.5.2"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "6.6.4",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+ "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+ "license": "MIT"
+ },
+ "node_modules/@vue/eslint-config-typescript": {
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz",
+ "integrity": "sha512-StxLFet2Qe97T8+7L8pGlhYBBr8Eg05LPuTDVopQV6il+SK6qqom59BA/rcFipUef2jD8P2X44Vd8tMFytfvlg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "^6.7.0",
+ "@typescript-eslint/parser": "^6.7.0",
+ "vue-eslint-parser": "^9.3.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0",
+ "eslint-plugin-vue": "^9.0.0",
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
+ "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.1",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/type-utils": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/parser": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz",
+ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz",
+ "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/type-utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz",
+ "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "@typescript-eslint/utils": "6.21.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/types": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz",
+ "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz",
+ "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/visitor-keys": "6.21.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "9.0.3",
+ "semver": "^7.5.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/utils": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz",
+ "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@types/json-schema": "^7.0.12",
+ "@types/semver": "^7.5.0",
+ "@typescript-eslint/scope-manager": "6.21.0",
+ "@typescript-eslint/types": "6.21.0",
+ "@typescript-eslint/typescript-estree": "6.21.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.21.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz",
+ "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "6.21.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@vue/eslint-config-typescript/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@babel/parser": "^7.25.3",
- "@vue/compiler-core": "3.5.2",
- "@vue/compiler-dom": "3.5.2",
- "@vue/compiler-ssr": "3.5.2",
- "@vue/shared": "3.5.2",
- "estree-walker": "^2.0.2",
- "magic-string": "^0.30.11",
- "postcss": "^8.4.44",
- "source-map-js": "^1.2.0"
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/@vue/compiler-ssr": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.2.tgz",
- "integrity": "sha512-vMtA4tQK/AM3UAYJsmouQzQpgG+h9TKiD5BV+Zt+ZyAMdicxzSEEFGWf/CykRnDpqj9fMfIHPhOezJVNxiXe2A==",
- "license": "MIT",
+ "node_modules/@vue/eslint-config-typescript/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "license": "ISC",
"dependencies": {
- "@vue/compiler-dom": "3.5.2",
- "@vue/shared": "3.5.2"
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@vue/devtools-api": {
- "version": "6.6.4",
- "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
- "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
- "license": "MIT"
+ "node_modules/@vue/eslint-config-typescript/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/@vue/reactivity": {
"version": "3.5.2",
@@ -6013,6 +6746,12 @@
"node": ">=4"
}
},
+ "node_modules/any-base": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
+ "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==",
+ "license": "MIT"
+ },
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
@@ -6454,6 +7193,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/await-to-js": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz",
+ "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/b4a": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz",
@@ -6730,6 +7478,12 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"license": "MIT"
},
+ "node_modules/bmp-ts": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz",
+ "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==",
+ "license": "MIT"
+ },
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
@@ -6772,6 +7526,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true,
+ "license": "ISC"
+ },
"node_modules/boolean": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz",
@@ -9417,6 +10178,20 @@
"once": "^1.4.0"
}
},
+ "node_modules/enhanced-resolve": {
+ "version": "5.17.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
+ "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@@ -9786,6 +10561,41 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-config-prettier": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
+ "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-define-config": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-define-config/-/eslint-define-config-2.1.0.tgz",
+ "integrity": "sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/Shinigami92"
+ },
+ {
+ "type": "paypal",
+ "url": "https://www.paypal.com/donate/?hosted_button_id=L7GY729FBKTZY"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=9.0.0",
+ "pnpm": ">=8.6.0"
+ }
+ },
"node_modules/eslint-import-resolver-node": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
@@ -9808,6 +10618,42 @@
"ms": "^2.1.1"
}
},
+ "node_modules/eslint-import-resolver-typescript": {
+ "version": "3.6.3",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz",
+ "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.3.5",
+ "enhanced-resolve": "^5.15.0",
+ "eslint-module-utils": "^2.8.1",
+ "fast-glob": "^3.3.2",
+ "get-tsconfig": "^4.7.5",
+ "is-bun-module": "^1.0.2",
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts"
+ },
+ "peerDependencies": {
+ "eslint": "*",
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-module-utils": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.9.0.tgz",
@@ -9892,6 +10738,127 @@
"node": ">=0.10.0"
}
},
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz",
+ "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.9.1"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-vue": {
+ "version": "9.28.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.28.0.tgz",
+ "integrity": "sha512-ShrihdjIhOTxs+MfWun6oJWuk+g/LAhN+CiuOl/jjkG3l0F2AuK5NMTaWqyvBgkFtpYmyks6P4603mLmhNJW8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "globals": "^13.24.0",
+ "natural-compare": "^1.4.0",
+ "nth-check": "^2.1.1",
+ "postcss-selector-parser": "^6.0.15",
+ "semver": "^7.6.3",
+ "vue-eslint-parser": "^9.4.3",
+ "xml-name-validator": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-vue/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint-plugin-vuejs-accessibility": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vuejs-accessibility/-/eslint-plugin-vuejs-accessibility-2.4.1.tgz",
+ "integrity": "sha512-ZRZhPdslplZXSF71MtSG+zXYRAT5KiHR4JVuo/DERQf9noAkDvi5W418VOE1qllmJd7wTenndxi1q8XeDMxdHw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "aria-query": "^5.3.0",
+ "emoji-regex": "^10.0.0",
+ "vue-eslint-parser": "^9.0.1"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-vuejs-accessibility/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -10286,6 +11253,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/exif-parser": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
+ "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
+ },
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -10451,6 +11423,13 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -10600,6 +11579,23 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/file-type": {
+ "version": "16.5.4",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz",
+ "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-web-to-node-stream": "^3.0.0",
+ "strtok3": "^6.2.4",
+ "token-types": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
+ }
+ },
"node_modules/filelist": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
@@ -11207,6 +12203,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/get-tsconfig": {
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
+ "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "resolve-pkg-maps": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ }
+ },
+ "node_modules/gifwrap": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
+ "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==",
+ "license": "MIT",
+ "dependencies": {
+ "image-q": "^4.0.0",
+ "omggif": "^1.0.10"
+ }
+ },
"node_modules/giget": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/giget/-/giget-1.2.3.tgz",
@@ -11745,6 +12764,21 @@
"node": ">= 4"
}
},
+ "node_modules/image-q": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz",
+ "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "16.9.1"
+ }
+ },
+ "node_modules/image-q/node_modules/@types/node": {
+ "version": "16.9.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
+ "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
+ "license": "MIT"
+ },
"node_modules/immediate": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
@@ -12028,16 +13062,39 @@
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
"dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bun-module": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.2.1.tgz",
+ "integrity": "sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.6.3"
+ }
+ },
+ "node_modules/is-bun-module/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=10"
}
},
"node_modules/is-callable": {
@@ -14395,6 +15452,44 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
+ "node_modules/jimp": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz",
+ "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==",
+ "license": "MIT",
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/diff": "1.6.0",
+ "@jimp/js-bmp": "1.6.0",
+ "@jimp/js-gif": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/js-tiff": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/plugin-blur": "1.6.0",
+ "@jimp/plugin-circle": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-contain": "1.6.0",
+ "@jimp/plugin-cover": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-displace": "1.6.0",
+ "@jimp/plugin-dither": "1.6.0",
+ "@jimp/plugin-fisheye": "1.6.0",
+ "@jimp/plugin-flip": "1.6.0",
+ "@jimp/plugin-hash": "1.6.0",
+ "@jimp/plugin-mask": "1.6.0",
+ "@jimp/plugin-print": "1.6.0",
+ "@jimp/plugin-quantize": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/plugin-rotate": "1.6.0",
+ "@jimp/plugin-threshold": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/jiti": {
"version": "1.21.6",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
@@ -14404,6 +15499,12 @@
"jiti": "bin/jiti.js"
}
},
+ "node_modules/jpeg-js": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
+ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
+ "license": "BSD-3-Clause"
+ },
"node_modules/js-beautify": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.1.tgz",
@@ -16135,6 +17236,19 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
"node_modules/nwsapi": {
"version": "2.2.12",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.12.tgz",
@@ -16430,6 +17544,12 @@
"integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==",
"license": "MIT"
},
+ "node_modules/omggif": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
+ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==",
+ "license": "MIT"
+ },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -16733,7 +17853,6 @@
"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": {
@@ -16762,6 +17881,28 @@
"node": ">=0.10.0"
}
},
+ "node_modules/parse-bmfont-ascii": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
+ "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==",
+ "license": "MIT"
+ },
+ "node_modules/parse-bmfont-binary": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
+ "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==",
+ "license": "MIT"
+ },
+ "node_modules/parse-bmfont-xml": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz",
+ "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==",
+ "license": "MIT",
+ "dependencies": {
+ "xml-parse-from-string": "^1.0.0",
+ "xml2js": "^0.5.0"
+ }
+ },
"node_modules/parse-cache-control": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz",
@@ -16923,6 +18064,19 @@
"url": "https://github.com/sponsors/jet2jet"
}
},
+ "node_modules/peek-readable": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
+ "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -17048,6 +18202,27 @@
"node": ">= 6"
}
},
+ "node_modules/pixelmatch": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz",
+ "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==",
+ "license": "ISC",
+ "dependencies": {
+ "pngjs": "^6.0.0"
+ },
+ "bin": {
+ "pixelmatch": "bin/pixelmatch"
+ }
+ },
+ "node_modules/pixelmatch/node_modules/pngjs": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
+ "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@@ -17153,6 +18328,15 @@
"node": ">=10.4.0"
}
},
+ "node_modules/pngjs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
+ "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.19.0"
+ }
+ },
"node_modules/possible-typed-array-names": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
@@ -17354,6 +18538,35 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
+ "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -17819,6 +19032,36 @@
"ieee754": "^1.2.1"
}
},
+ "node_modules/readable-web-to-node-stream": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
+ "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/readdir-glob": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz",
@@ -18034,6 +19277,16 @@
"npm": ">=2"
}
},
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
+ },
"node_modules/resolve.exports": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
@@ -18324,6 +19577,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/sax": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+ "license": "ISC"
+ },
"node_modules/saxes": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
@@ -18544,6 +19803,15 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/simple-xml-to-json": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz",
+ "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.12.2"
+ }
+ },
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -19049,6 +20317,23 @@
"node": ">=0.10.0"
}
},
+ "node_modules/strtok3": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
+ "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "peek-readable": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
@@ -19175,6 +20460,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/synckit": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.1.tgz",
+ "integrity": "sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/tailwind-merge": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz",
@@ -19231,6 +20533,16 @@
"tailwindcss": ">=3.0.0 || insiders"
}
},
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@@ -19386,6 +20698,12 @@
"license": "MIT",
"optional": true
},
+ "node_modules/tinycolor2": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+ "license": "MIT"
+ },
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -19460,6 +20778,23 @@
"node": ">=0.6"
}
},
+ "node_modules/token-types": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
+ "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "ieee754": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
"node_modules/tough-cookie": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz",
@@ -19512,6 +20847,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
"node_modules/ts-interface-checker": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
@@ -20323,6 +21671,15 @@
"which": "bin/which"
}
},
+ "node_modules/utif2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz",
+ "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==",
+ "license": "MIT",
+ "dependencies": {
+ "pako": "^1.0.11"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -20483,6 +21840,71 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/vue-eslint-parser": {
+ "version": "9.4.3",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
+ "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.3.4",
+ "eslint-scope": "^7.1.1",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.3.1",
+ "esquery": "^1.4.0",
+ "lodash": "^4.17.21",
+ "semver": "^7.3.6"
+ },
+ "engines": {
+ "node": "^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=6.0.0"
+ }
+ },
+ "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/vue-eslint-parser/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/vue-eslint-parser/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/vue-i18n": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.0.tgz",
@@ -20907,6 +22329,34 @@
"node": ">=12"
}
},
+ "node_modules/xml-parse-from-string": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
+ "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==",
+ "license": "MIT"
+ },
+ "node_modules/xml2js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+ "license": "MIT",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xml2js/node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/xmlbuilder": {
"version": "15.1.1",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz",
@@ -21223,6 +22673,15 @@
"engines": {
"node": ">= 14"
}
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/package.json b/package.json
index 85bc4f1..4749ce8 100644
--- a/package.json
+++ b/package.json
@@ -2,11 +2,14 @@
"name": "comet",
"productName": "Comet",
"private": true,
- "version": "2.0.4",
- "description": "A simple video converter",
+ "version": "2.1.2",
+ "description": "A simple media converter",
"keywords": [
"comet",
"video",
+ "audio",
+ "image",
+ "media",
"converter",
"ffmpeg"
],
@@ -34,7 +37,8 @@
"make": "electron-forge make --verbose",
"publish": "electron-forge publish",
"test": "jest",
- "lint": "eslint --ext .ts,.tsx ."
+ "lint": "eslint . --ext .ts,.vue --ignore-path .gitignore",
+ "lint:fix": "npm run lint -- --fix"
},
"dependencies": {
"@intlify/message-compiler": "^10.0.1",
@@ -46,6 +50,7 @@
"ffprobe-static": "^3.1.0",
"filesize": "^10.1.4",
"fluent-ffmpeg": "^2.1.3",
+ "jimp": "^1.6.0",
"lucide-vue-next": "^0.435.0",
"mobx": "^6.13.2",
"namor": "^2.0.2",
@@ -74,6 +79,7 @@
"@intlify/vue-i18n-loader": "^4.2.0",
"@jest/globals": "^29.7.0",
"@reforged/maker-appimage": "^3.3.0",
+ "@rushstack/eslint-patch": "^1.5.1",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/user-event": "^14.5.2",
@@ -86,22 +92,31 @@
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@vitejs/plugin-vue": "^5.1.2",
+ "@vue/eslint-config-typescript": "^12.0.0",
"@vue/test-utils": "^2.4.6",
"@vue/vue3-jest": "^29.2.6",
"autoprefixer": "^10.4.20",
"electron": "32.0.1",
"electron-devtools-installer": "^3.2.0",
"eslint": "^8.57.0",
+ "eslint-config-prettier": "^9.0.0",
+ "eslint-define-config": "^2.1.0",
+ "eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-prettier": "^5.2.1",
+ "eslint-plugin-vue": "^9.18.0",
+ "eslint-plugin-vuejs-accessibility": "^2.2.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"postcss": "^8.4.45",
+ "prettier": "^3.3.3",
"tailwindcss": "^3.4.10",
"ts-jest": "^29.2.5",
"ts-node": "^10.9.2",
"typescript": "~4.5.4",
- "vite": "^5.4.2"
+ "vite": "^5.4.2",
+ "vue-eslint-parser": "^9.3.2"
},
"engines": {
"node": ">= 20.10.0"
diff --git a/src/consts/app.ts b/src/consts/app.ts
new file mode 100644
index 0000000..d73b3f5
--- /dev/null
+++ b/src/consts/app.ts
@@ -0,0 +1 @@
+export const APP_NAME = 'Comet';
diff --git a/src/consts/formats.ts b/src/consts/formats.ts
index cc8bb51..ae07829 100644
--- a/src/consts/formats.ts
+++ b/src/consts/formats.ts
@@ -1,5 +1,6 @@
-import { AudioFormat } from '@/enum/audio-format';
import { VideoFormat } from '@/enum/video-format';
+import { AudioFormat } from '@/enum/audio-format';
+import { ImageFormat } from '@/enum/image-format';
export const VIDEO_CONVERSION_FORMATS = [
VideoFormat.MP4,
@@ -24,7 +25,7 @@ export const VIDEO_CONVERSION_FORMATS = [
VideoFormat.MTS,
VideoFormat.OGV,
VideoFormat.RM,
- VideoFormat.SWF
+ VideoFormat.SWF,
];
export const AUDIO_CONVERSION_FORMATS = [
@@ -42,5 +43,14 @@ export const AUDIO_CONVERSION_FORMATS = [
AudioFormat.AC3,
AudioFormat.APE,
AudioFormat.MPC,
- AudioFormat.OPUS
+ AudioFormat.OPUS,
+];
+
+export const IMAGE_CONVERSION_FORMATS = [
+ ImageFormat.JPG,
+ ImageFormat.PNG,
+ ImageFormat.BMP,
+ ImageFormat.GIF,
+ ImageFormat.TIFF,
+ ImageFormat.JPEG,
];
diff --git a/src/enum/arch.ts b/src/enum/arch.ts
index a75245d..4b1106f 100644
--- a/src/enum/arch.ts
+++ b/src/enum/arch.ts
@@ -3,5 +3,5 @@ export enum Architecture {
X64 = 'x64',
ARM = 'arm',
ARM64 = 'arm64',
- UNKNOWN = 'unknown'
+ UNKNOWN = 'unknown',
}
diff --git a/src/enum/image-format.ts b/src/enum/image-format.ts
new file mode 100644
index 0000000..cae27a2
--- /dev/null
+++ b/src/enum/image-format.ts
@@ -0,0 +1,8 @@
+export enum ImageFormat {
+ JPG = 'jpg',
+ PNG = 'png',
+ BMP = 'bmp',
+ GIF = 'gif',
+ TIFF = 'tiff',
+ JPEG = 'jpeg',
+}
diff --git a/src/enum/ipc-event.ts b/src/enum/ipc-event.ts
index 158d236..42d6d2d 100644
--- a/src/enum/ipc-event.ts
+++ b/src/enum/ipc-event.ts
@@ -1,7 +1,7 @@
export enum IpcEvent {
CANCEL_CONVERSION = 'cancel-conversion',
CANCEL_ITEM_CONVERSION = 'cancel-item-conversion',
- CONVERT_VIDEO = 'convert-video',
+ CONVERT_MEDIA = 'convert-media',
DIALOG_SELECT_DIRECTORY = 'dialog:select-directory',
GET_DESKTOP_PATH = 'get-desktop-path',
SHOW_WINDOW = 'show-window',
@@ -12,12 +12,14 @@ export enum IpcEvent {
GET_PROJECT_NAME = 'get-project-name',
LOAD_GIST_REQUEST = 'load-gist-request',
LOAD_ELECTRON_EXAMPLE_REQUEST = 'load-electron-example-request',
+ NATIVE_THEME_UPDATED = 'native-theme-updated',
+ GET_SYSTEM_THEME = 'get-system-theme',
}
export const ipcMainEvents = [
IpcEvent.CANCEL_CONVERSION,
IpcEvent.CANCEL_ITEM_CONVERSION,
- IpcEvent.CONVERT_VIDEO,
+ IpcEvent.CONVERT_MEDIA,
IpcEvent.DIALOG_SELECT_DIRECTORY,
IpcEvent.GET_DESKTOP_PATH,
IpcEvent.SHOW_WINDOW,
@@ -28,5 +30,6 @@ export const ipcMainEvents = [
IpcEvent.GET_PROJECT_NAME,
IpcEvent.LOAD_GIST_REQUEST,
IpcEvent.LOAD_ELECTRON_EXAMPLE_REQUEST,
+ IpcEvent.NATIVE_THEME_UPDATED,
+ IpcEvent.GET_SYSTEM_THEME,
];
-
diff --git a/src/enum/media.ts b/src/enum/media.ts
new file mode 100644
index 0000000..831f542
--- /dev/null
+++ b/src/enum/media.ts
@@ -0,0 +1,5 @@
+export enum Media {
+ VIDEO = 'video',
+ IMAGE = 'image',
+ AUDIO = 'audio',
+}
diff --git a/src/enum/platform.ts b/src/enum/platform.ts
index 8ce16f2..a5c391d 100644
--- a/src/enum/platform.ts
+++ b/src/enum/platform.ts
@@ -1,5 +1,5 @@
export enum Platform {
DARWIN = 'darwin',
LINUX = 'linux',
- WIN32 = 'win32'
+ WIN32 = 'win32',
}
diff --git a/src/lib/conversion/conversion-handler.ts b/src/lib/conversion/conversion-handler.ts
new file mode 100644
index 0000000..e7629af
--- /dev/null
+++ b/src/lib/conversion/conversion-handler.ts
@@ -0,0 +1,77 @@
+import { Media } from '@/types/media';
+import { Media as MediaType } from '@/enum/media';
+import { VideoFormat } from '@/enum/video-format';
+import { AudioFormat } from '@/enum/audio-format';
+import { ImageFormat } from '@/enum/image-format';
+import { FfmpegAdapter } from './ffmpeg';
+import { JimpAdapter } from './jimp';
+import { Adapter } from '@/types/adapter';
+
+export class ConversionHandler {
+ protected conversions: Map = new Map();
+
+ /**
+ * Adds a new conversion to the handler.
+ */
+ async handle(
+ id: string,
+ filePath: string,
+ outputFormat: VideoFormat | AudioFormat | ImageFormat,
+ saveDirectory: string,
+ type: Media,
+ event: Electron.IpcMainInvokeEvent,
+ ): Promise {
+ const adapter = this.getAdapter(type);
+
+ this.conversions.set(id, adapter);
+
+ try {
+ const result = await adapter.convert(id, filePath, outputFormat, saveDirectory, event);
+
+ this.conversions.delete(id);
+
+ return result;
+ } catch (error) {
+ this.conversions.delete(id);
+
+ throw error;
+ }
+ }
+
+ /**
+ * Cancels the conversion with the given ID.
+ */
+ cancel(id: string): boolean {
+ const adapter = this.conversions.get(id);
+ if (adapter) {
+ const result = adapter.cancel(id);
+ this.conversions.delete(id);
+ return result;
+ }
+ return false;
+ }
+
+ /**
+ * Cancels all conversions.
+ */
+ cancelAll(): void {
+ this.conversions.forEach((adapter, id) => adapter.cancel(id));
+ this.conversions.clear();
+ }
+
+ /**
+ * Returns the appropriate adapter for the given type.
+ */
+ protected getAdapter(type: Media) {
+ switch (type) {
+ case MediaType.IMAGE:
+ return new JimpAdapter();
+ case MediaType.VIDEO:
+ return new FfmpegAdapter();
+ case MediaType.AUDIO:
+ return new FfmpegAdapter();
+ default:
+ throw new Error(`Unsupported type: ${type}`);
+ }
+ }
+}
diff --git a/src/lib/conversion/ffmpeg.ts b/src/lib/conversion/ffmpeg.ts
new file mode 100644
index 0000000..82f3846
--- /dev/null
+++ b/src/lib/conversion/ffmpeg.ts
@@ -0,0 +1,97 @@
+import path from 'node:path';
+import ffmpeg, { setFfmpegPath, setFfprobePath, ffprobe as ffmpegFfprobe } from 'fluent-ffmpeg';
+import ffmpegStatic from 'ffmpeg-static';
+import { path as ffprobePath } from 'ffprobe-static';
+import { Adapter } from '@/types/adapter';
+
+// Initialize FFmpeg paths
+let ffmpegPath: string;
+try {
+ if (!ffmpegStatic) throw new Error('ffmpegStatic not found');
+ ffmpegPath = ffmpegStatic.replace('app.asar', 'app.asar.unpacked');
+ const ffprobeResolvedPath = ffprobePath.replace('app.asar', 'app.asar.unpacked');
+ setFfmpegPath(ffmpegPath);
+ setFfprobePath(ffprobeResolvedPath);
+} catch (error) {
+ console.error('Failed to find ffmpegStatic:', error.message);
+}
+
+export class FfmpegAdapter implements Adapter {
+ /**
+ * Map of FFmpeg processes by ID.
+ */
+ protected ffmpegProcesses = new Map();
+
+ /**
+ * Converts the file at the given path to the specified output format.
+ */
+ convert(
+ id: string,
+ filePath: string,
+ outputFormat: string,
+ saveDirectory: string,
+ event: Electron.IpcMainInvokeEvent,
+ ): Promise {
+ const outputFileName = `${path.basename(filePath, path.extname(filePath))}.${outputFormat}`;
+ const outputPath = path.join(saveDirectory, outputFileName);
+
+ return new Promise((resolve, reject) => {
+ ffmpegFfprobe(filePath, (err, metadata) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+
+ const duration = metadata.format.duration;
+ const ffmpegCommand = ffmpeg(filePath)
+ .output(outputPath)
+ .on('progress', (progress) => {
+ const processedSeconds = this.parseTimemark(progress.timemark);
+ const calculatedProgress = duration ? (processedSeconds / duration) * 100 : 0;
+ event.sender.send('conversion-progress', { id, progress: calculatedProgress });
+ })
+ .on('end', () => {
+ event.sender.send('conversion-progress', { id, progress: 100 });
+ this.ffmpegProcesses.delete(id);
+ resolve(outputPath);
+ })
+ .on('error', (error: Error) => {
+ this.ffmpegProcesses.delete(id);
+ reject(error);
+ })
+ .save(outputPath);
+
+ this.ffmpegProcesses.set(id, ffmpegCommand);
+ });
+ });
+ }
+
+ /**
+ * Cancels the FFmpeg conversion process with the given ID.
+ */
+ cancel(id: string): boolean {
+ const ffmpegCommand = this.ffmpegProcesses.get(id);
+ if (!ffmpegCommand) return false;
+
+ try {
+ ffmpegCommand.kill('SIGKILL');
+ this.ffmpegProcesses.delete(id);
+ return true;
+ } catch (error) {
+ console.error(`Failed to kill FFmpeg process for ID: ${id}`, error);
+ return false;
+ }
+ }
+
+ /**
+ * Parses a FFmpeg timemark string into seconds.
+ */
+ protected parseTimemark(timemark: string): number {
+ const parts = timemark.split(':').reverse();
+ let seconds = 0;
+ if (parts.length > 0) seconds += parseFloat(parts[0]);
+ if (parts.length > 1) seconds += parseInt(parts[1]) * 60;
+ if (parts.length > 2) seconds += parseInt(parts[2]) * 3600;
+ return seconds;
+ }
+}
diff --git a/src/lib/conversion/jimp.ts b/src/lib/conversion/jimp.ts
new file mode 100644
index 0000000..f598142
--- /dev/null
+++ b/src/lib/conversion/jimp.ts
@@ -0,0 +1,42 @@
+import { Jimp } from 'jimp';
+import { promises as fs } from 'fs'; // Use `fs.promises` for async directory management
+import path from 'node:path';
+import { Adapter } from '@/types/adapter';
+
+export type JimpType = typeof Jimp;
+
+export class JimpAdapter implements Adapter {
+ protected jimpProcesses = new Map();
+
+ /**
+ * Converts the file at the given path to the specified output format.
+ */
+ async convert(
+ id: string,
+ filePath: string,
+ outputFormat: string,
+ saveDirectory: string,
+ event: Electron.IpcMainInvokeEvent,
+ ): Promise {
+ const outputFileName = `${path.basename(filePath, path.extname(filePath))}.${outputFormat}`;
+ const outputPath = path.join(saveDirectory, outputFileName);
+
+ await fs.mkdir(saveDirectory, { recursive: true });
+
+ const image = await Jimp.read(filePath);
+ this.jimpProcesses.set(id, image as unknown as JimpType);
+
+ await image.write(outputPath as `${string}.${string}`);
+ event.sender.send('conversion-progress', { id, progress: 100 });
+ this.jimpProcesses.delete(id);
+
+ return outputPath;
+ }
+
+ /**
+ * Cancels the Jimp conversion process with the given ID.
+ */
+ cancel(id: string): boolean {
+ return this.jimpProcesses.delete(id);
+ }
+}
diff --git a/src/lib/ffmpeg.ts b/src/lib/ffmpeg.ts
deleted file mode 100644
index df177dc..0000000
--- a/src/lib/ffmpeg.ts
+++ /dev/null
@@ -1,131 +0,0 @@
-import ffmpeg from 'fluent-ffmpeg';
-import ffmpegStatic from 'ffmpeg-static';
-import ffprobe from 'ffprobe-static';
-import path from 'node:path';
-
-const ffmpegProcesses = new Map();
-
-/**
- * Set the ffmpeg process for the given ID.
- *
- * @param {string} id
- * @param {ffmpeg.FfmpegCommand} ffmpegCommand
- */
-export function setFfmpegProcess(id: string, ffmpegCommand: ffmpeg.FfmpegCommand): void {
- ffmpegProcesses.set(id, ffmpegCommand);
-}
-
-let ffmpegPath: string;
-let ffprobePath: string;
-
-try {
- if (!ffmpegStatic) throw new Error('ffmpegStatic not found');
- ffmpegPath = ffmpegStatic.replace('app.asar', 'app.asar.unpacked');
- ffprobePath = ffprobe.path.replace('app.asar', 'app.asar.unpacked');
-
- ffmpeg.setFfmpegPath(ffmpegPath);
- ffmpeg.setFfprobePath(ffprobePath);
-} catch (error) {
- console.error('Failed to find ffmpegStatic:', error.message);
-}
-
-/**
- * Parse a timemark string into seconds.
- */
-export function parseTimemark(timemark: string): number {
- const parts = timemark.split(':').reverse();
- let seconds = 0;
- if (parts.length > 0) seconds += parseFloat(parts[0]);
- if (parts.length > 1) seconds += parseInt(parts[1]) * 60;
- if (parts.length > 2) seconds += parseInt(parts[2]) * 3600;
- return seconds;
-}
-
-/**
- * Handle the video conversion process.
- */
-export function handleConversion(
- event: Electron.IpcMainInvokeEvent,
- id: string,
- filePath: string,
- outputFormat: string,
- saveDirectory: string,
- resolve: (value: string) => void,
- reject: (reason: unknown) => void
-): void {
- const outputFileName = `${path.basename(filePath, path.extname(filePath))}.${outputFormat}`;
- const outputPath = path.join(saveDirectory, outputFileName);
-
- ffmpeg.ffprobe(filePath, (err, metadata) => {
- if (err) {
- reject(err);
- return;
- }
-
- const duration = metadata.format.duration;
-
- const ffmpegCommand = ffmpeg(filePath)
- .output(outputPath)
- .on('progress', (progress) => {
- const processedSeconds = parseTimemark(progress.timemark);
- const calculatedProgress = duration ? (processedSeconds / duration) * 100 : 0;
- event.sender.send('conversion-progress', { id, progress: calculatedProgress });
- })
- .on('end', () => {
- ffmpegProcesses.delete(id);
- resolve(outputPath);
- })
- .on('error', (error: Error) => {
- ffmpegProcesses.delete(id);
- if (error.message.includes('SIGKILL')) {
- reject(new Error('Conversion canceled by user'));
- } else {
- reject(error);
- }
- })
- .save(outputPath);
-
- setFfmpegProcess(id, ffmpegCommand);
- });
-}
-
-/**
- * Cancel a single FFmpeg process.
- */
-export function handleItemConversionCancellation(
- _event: Electron.IpcMainInvokeEvent,
- id: string
-): boolean {
- const ffmpegCommand = ffmpegProcesses.get(id);
-
- if (!ffmpegCommand) {
- console.warn(`No FFmpeg process found for ID: ${id}`);
- return false;
- }
-
- try {
- // Send SIGKILL to forcefully stop the process
- ffmpegCommand.kill('SIGKILL');
- ffmpegProcesses.delete(id);
- return true;
- } catch (error) {
- console.error(`Failed to kill FFmpeg process for ID: ${id}`, error);
- return false;
- }
-}
-
-/**
- * Cancel all FFmpeg processes.
- */
-export function handleConversionCancellation(_event: Electron.IpcMainInvokeEvent): boolean {
- for (const [id, ffmpegCommand] of ffmpegProcesses.entries()) {
- try {
- ffmpegCommand.kill('SIGKILL');
- ffmpegProcesses.delete(id);
- } catch (error) {
- console.error(`Failed to kill FFmpeg process for ID: ${id}`, error);
- return false;
- }
- }
- return true;
-}
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 86a80f7..a11e967 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -1,8 +1,8 @@
-export * from './desktop-path';
-export * from './windows';
-export * from './ffmpeg';
-export * from './ipc-handlers';
-export * from './get-project-name';
-export * from './devmode';
-export * from './devtools';
-export * from './squirrel';
+export * from './conversion/ffmpeg';
+export * from './utils/desktop-path';
+export * from './utils/get-project-name';
+export * from './utils/devmode';
+export * from './utils/devtools';
+export * from './system/ipc-handlers';
+export * from './system/windows';
+export * from './system/squirrel';
diff --git a/src/lib/ipc-handlers.ts b/src/lib/ipc-handlers.ts
deleted file mode 100644
index 6800e68..0000000
--- a/src/lib/ipc-handlers.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import {
- dialog,
- IpcMain,
- IpcMainInvokeEvent
-} from 'electron';
-import { getDesktopPath } from './desktop-path';
-import { IpcEvent } from '../enum/ipc-event';
-import {
- handleConversion,
- handleConversionCancellation,
- handleItemConversionCancellation
-} from './ffmpeg';
-
-/**
- * Configure the IPC handlers
- *
- * @param {IpcMain} ipcMain
- *
- * @returns {void}
- */
-export function configureIpcHandlers(ipcMain: IpcMain): void {
- ipcMain.handle(IpcEvent.GET_DESKTOP_PATH, () => {
- return getDesktopPath();
- });
-
- ipcMain.handle(IpcEvent.DIALOG_SELECT_DIRECTORY, async () => {
- const result = await dialog.showOpenDialog({
- properties: ['openDirectory'],
- });
-
- return result.canceled ? null : result.filePaths[0];
- });
-
- ipcMain.handle(IpcEvent.CONVERT_VIDEO, async (
- event: IpcMainInvokeEvent,
- { id, filePath, outputFormat, saveDirectory }: {
- id: string,
- filePath: string;
- outputFormat: string;
- saveDirectory: string;
- }
- ) => {
- return new Promise((resolve, reject) => {
- handleConversion(
- event,
- id,
- filePath,
- outputFormat,
- saveDirectory,
- resolve,
- reject
- );
- });
- });
-
- ipcMain.handle(IpcEvent.CANCEL_CONVERSION, (
- event: IpcMainInvokeEvent
- ) => {
- return handleConversionCancellation(event);
- });
-
- ipcMain.handle(IpcEvent.CANCEL_ITEM_CONVERSION, (
- event: IpcMainInvokeEvent,
- id: string
- ) => {
- return handleItemConversionCancellation(event, id);
- });
-}
diff --git a/src/lib/system/ipc-handlers.ts b/src/lib/system/ipc-handlers.ts
new file mode 100644
index 0000000..c7fd823
--- /dev/null
+++ b/src/lib/system/ipc-handlers.ts
@@ -0,0 +1,56 @@
+import { dialog, IpcMain, IpcMainInvokeEvent } from 'electron';
+import { getDesktopPath } from '@/lib/utils/desktop-path';
+import { IpcEvent } from '@/enum/ipc-event';
+import { ConversionHandler } from '@/lib/conversion/conversion-handler';
+import { VideoFormat } from '@/enum/video-format';
+import { AudioFormat } from '@/enum/audio-format';
+import { ImageFormat } from '@/enum/image-format';
+import { Media } from '@/types/media';
+
+// Create a single instance of ConversionHandler to handle all conversions
+export const conversionHandler = new ConversionHandler();
+
+/**
+ * Configure the IPC handlers
+ */
+export function configureIpcHandlers(ipcMain: IpcMain): void {
+ ipcMain.handle(IpcEvent.GET_DESKTOP_PATH, () => getDesktopPath());
+
+ ipcMain.handle(IpcEvent.DIALOG_SELECT_DIRECTORY, async () => {
+ const result = await dialog.showOpenDialog({
+ properties: ['openDirectory'],
+ });
+
+ return result.canceled ? null : result.filePaths[0];
+ });
+
+ ipcMain.handle(
+ IpcEvent.CONVERT_MEDIA,
+ async (
+ event: IpcMainInvokeEvent,
+ {
+ id,
+ filePath,
+ outputFormat,
+ saveDirectory,
+ mediaType,
+ }: {
+ id: string;
+ filePath: string;
+ outputFormat: VideoFormat | AudioFormat | ImageFormat;
+ saveDirectory: string;
+ mediaType: Media;
+ },
+ ) => {
+ return await conversionHandler.handle(id, filePath, outputFormat, saveDirectory, mediaType, event);
+ },
+ );
+
+ ipcMain.handle(IpcEvent.CANCEL_CONVERSION, () => {
+ return conversionHandler.cancelAll();
+ });
+
+ ipcMain.handle(IpcEvent.CANCEL_ITEM_CONVERSION, (_event: IpcMainInvokeEvent, id: string) => {
+ return conversionHandler.cancel(id);
+ });
+}
diff --git a/src/lib/squirrel.ts b/src/lib/system/squirrel.ts
similarity index 100%
rename from src/lib/squirrel.ts
rename to src/lib/system/squirrel.ts
diff --git a/src/lib/windows.ts b/src/lib/system/windows.ts
similarity index 69%
rename from src/lib/windows.ts
rename to src/lib/system/windows.ts
index a217adb..4d2851b 100644
--- a/src/lib/windows.ts
+++ b/src/lib/system/windows.ts
@@ -1,15 +1,13 @@
import { BrowserWindowConstructorOptions, BrowserWindow } from 'electron';
-import { browserWindowOptions } from '../options';
-import { isDevMode } from './devmode';
+import { browserWindowOptions } from '../../options';
+import { isDevMode } from '../utils/devmode';
// Keep a global reference of the window objects, if we don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
export let browserWindows: Array = [];
let mainIsReadyResolver: () => void;
-const mainIsReadyPromise = new Promise(
- (resolve) => (mainIsReadyResolver = resolve),
-);
+const mainIsReadyPromise = new Promise((resolve) => (mainIsReadyResolver = resolve));
/**
* Resolve the mainIsReadyPromise to indicate that the main window is ready.
@@ -20,11 +18,9 @@ export function mainIsReady() {
/**
* Get the main window options
- *
- * @returns {BrowserWindowConstructorOptions}
*/
export function getMainWindowOptions(
- overrides?: Partial
+ overrides?: Partial,
): BrowserWindowConstructorOptions {
return {
...browserWindowOptions,
@@ -34,16 +30,8 @@ export function getMainWindowOptions(
/**
* Create a new BrowserWindow instance
- *
- * @param {BrowserWindowConstructorOptions} options
- * @param {string} entryFilePath
- *
- * @returns {BrowserWindow}
*/
-export function createWindow(
- options: BrowserWindowConstructorOptions,
- entryFilePath: string
-): BrowserWindow {
+export function createWindow(options: BrowserWindowConstructorOptions, entryFilePath: string): BrowserWindow {
let mainWindow: BrowserWindow | null;
mainWindow = new BrowserWindow(options);
@@ -70,13 +58,8 @@ export function createWindow(
/**
* Load the entry point for the main window
- *
- * @param {BrowserWindow} window
- * @param {string} entryFilePath
- *
- * @returns {void}
*/
-function loadEntryPoint(window: BrowserWindow, entryFilePath: string) {
+function loadEntryPoint(window: BrowserWindow, entryFilePath: string): void {
if (process.env.JEST) {
window.loadFile('./fake/path');
@@ -92,20 +75,13 @@ function loadEntryPoint(window: BrowserWindow, entryFilePath: string) {
/**
* Gets or creates the main window, returning it in both cases.
- *
- * @returns {Promise}
*/
export async function getOrCreateMainWindow(
entryFilePath: string,
- options: BrowserWindowConstructorOptions = getMainWindowOptions()
+ options: BrowserWindowConstructorOptions = getMainWindowOptions(),
): Promise {
await mainIsReadyPromise;
return (
- BrowserWindow.getFocusedWindow()
- || browserWindows[0]
- || createWindow(
- getMainWindowOptions(options),
- entryFilePath
- )
+ BrowserWindow.getFocusedWindow() || browserWindows[0] || createWindow(getMainWindowOptions(options), entryFilePath)
);
}
diff --git a/src/lib/desktop-path.ts b/src/lib/utils/desktop-path.ts
similarity index 93%
rename from src/lib/desktop-path.ts
rename to src/lib/utils/desktop-path.ts
index 3680a8b..a171237 100644
--- a/src/lib/desktop-path.ts
+++ b/src/lib/utils/desktop-path.ts
@@ -4,8 +4,6 @@ import path from 'node:path';
/**
* Get the path to the desktop directory
- *
- * @returns {string}
*/
export function getDesktopPath(): string {
const homeDir = path.resolve(os.homedir());
diff --git a/src/lib/devmode.ts b/src/lib/utils/devmode.ts
similarity index 83%
rename from src/lib/devmode.ts
rename to src/lib/utils/devmode.ts
index e41ef3d..384cdfd 100644
--- a/src/lib/devmode.ts
+++ b/src/lib/utils/devmode.ts
@@ -1,7 +1,5 @@
/**
* Are we currently running in development mode?
- *
- * @returns {boolean}
*/
export function isDevMode(): boolean {
return !!process.defaultApp;
diff --git a/src/lib/devtools.ts b/src/lib/utils/devtools.ts
similarity index 94%
rename from src/lib/devtools.ts
rename to src/lib/utils/devtools.ts
index b3b81ea..d160568 100644
--- a/src/lib/devtools.ts
+++ b/src/lib/utils/devtools.ts
@@ -2,9 +2,6 @@ import { isDevMode } from './devmode';
/**
* Installs developer tools if we're in dev mode.
- *
- * @export
- * @returns {Promise}
*/
export async function setupDevTools(): Promise {
if (!isDevMode()) return;
diff --git a/src/lib/get-project-name.ts b/src/lib/utils/get-project-name.ts
similarity index 83%
rename from src/lib/get-project-name.ts
rename to src/lib/utils/get-project-name.ts
index d69f827..3b388e6 100644
--- a/src/lib/get-project-name.ts
+++ b/src/lib/utils/get-project-name.ts
@@ -4,9 +4,6 @@ import * as namor from 'namor';
/**
* Returns a name for this project
- *
- * @param {string} [localPath]
- * @returns {string}
*/
export function getProjectName(localPath?: string): string {
if (localPath) {
diff --git a/src/locales/messages.ts b/src/locales/messages.ts
index 4d979a1..269f424 100644
--- a/src/locales/messages.ts
+++ b/src/locales/messages.ts
@@ -5,6 +5,7 @@ export const messages = {
media: {
video: 'Video',
audio: 'Audio',
+ image: 'Image',
},
upload: {
title: 'Drag and drop your {type} files here',
@@ -33,6 +34,7 @@ export const messages = {
media: {
video: 'Vidéo',
audio: 'Audio',
+ image: 'Image',
},
upload: {
title: 'Glissez-déposez vos fichiers {type} ici',
@@ -61,6 +63,7 @@ export const messages = {
media: {
video: 'Vídeo',
audio: 'Audio',
+ image: 'Imagen',
},
upload: {
title: 'Arrastra y suelta tus archivos {type} aquí',
@@ -89,6 +92,7 @@ export const messages = {
media: {
video: 'Video',
audio: 'Audio',
+ image: 'Bild',
},
upload: {
title: 'Ziehen Sie Ihre {type}-Dateien hierher',
@@ -117,6 +121,7 @@ export const messages = {
media: {
video: 'Видео',
audio: 'Аудио',
+ image: 'Изображение',
},
upload: {
title: 'Перетащите ваши файлы {type} сюда',
diff --git a/src/main.ts b/src/main.ts
index 8f58bf4..4497a3c 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,27 +1,26 @@
-import {
- app,
- BrowserWindow,
- ipcMain,
- IpcMainEvent,
- nativeTheme,
- systemPreferences,
-} from 'electron';
-import {
- shouldQuit,
- isDevMode,
- setupDevTools,
- getOrCreateMainWindow,
- configureIpcHandlers,
- mainIsReady,
-} from './lib';
+import { app, BrowserWindow, ipcMain, IpcMainEvent, nativeTheme, systemPreferences } from 'electron';
+import { shouldQuit, isDevMode, getOrCreateMainWindow, configureIpcHandlers, mainIsReady } from './lib';
import path from 'node:path';
-import { IpcEvent } from './enum/ipc-event';
+import { IpcEvent } from '@/enum/ipc-event';
+import { APP_NAME } from '@/consts/app';
+
+/**
+ * Get the entry file path for the main window.
+ */
+function getEntryFilePath() {
+ const fakePath = '/fake/path';
+ const isJest = !!process.env.JEST;
+ const mainWindowViteNameExists = typeof MAIN_WINDOW_VITE_NAME !== 'undefined';
+
+ if (!mainWindowViteNameExists) {
+ return fakePath as string;
+ }
+
+ return isJest ? fakePath : (path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`) as string);
+}
// Path to the entry HTML file for the main window
-const entryFilePath = path.join(
- __dirname,
- `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`
-);
+const entryFilePath = getEntryFilePath();
/**
* Handle the app's "ready" event. This is essentially
@@ -32,11 +31,11 @@ export async function onReady() {
process.env.NODE_ENV = 'production';
}
+ setupIsDevMode();
setupShowWindow();
- setupDevTools();
setupTitleBarClickMac();
setupNativeTheme();
- setupIsDevMode();
+ setupGetSystemTheme();
// Do this after setting everything up to ensure that
// any IPC listeners are set up before they're used
@@ -67,10 +66,7 @@ export function setupTitleBarClickMac() {
}
ipcMain.on(IpcEvent.CLICK_TITLEBAR_MAC, (event: IpcMainEvent) => {
- const doubleClickAction = systemPreferences.getUserDefault(
- 'AppleActionOnDoubleClick',
- 'string',
- );
+ const doubleClickAction = systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');
const win = BrowserWindow.fromWebContents(event.sender);
if (win) {
if (doubleClickAction === 'Minimize') {
@@ -93,9 +89,7 @@ export function setupTitleBarClickMac() {
*
* @returns Whether the value is a valid native theme source
*/
-function isNativeThemeSource(
- val: unknown,
-): val is typeof nativeTheme.themeSource {
+function isNativeThemeSource(val: unknown): val is typeof nativeTheme.themeSource {
return typeof val === 'string' && ['dark', 'light', 'system'].includes(val);
}
@@ -103,11 +97,31 @@ function isNativeThemeSource(
* Handle theme changes.
*/
export function setupNativeTheme() {
- ipcMain.on(IpcEvent.SET_NATIVE_THEME, async (_, source: string) => {
+ ipcMain.on(IpcEvent.SET_NATIVE_THEME, (_event, source: string) => {
if (isNativeThemeSource(source)) {
nativeTheme.themeSource = source;
}
});
+
+ // Only notify renderer if the theme source is 'system'
+ if (nativeTheme) {
+ nativeTheme.on('updated', () => {
+ const currentTheme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
+ BrowserWindow.getAllWindows().forEach((win) => {
+ win.webContents.send(IpcEvent.NATIVE_THEME_UPDATED, currentTheme);
+ });
+ });
+ }
+}
+
+/**
+ * Handle getting the system theme.
+ */
+export function setupGetSystemTheme() {
+ ipcMain.on(IpcEvent.GET_SYSTEM_THEME, (event) => {
+ const currentTheme = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
+ event.returnValue = currentTheme;
+ });
}
/**
@@ -145,7 +159,7 @@ export function main() {
}
// Set the app's name
- app.name = 'Comet';
+ app.name = APP_NAME;
// Launch
app.whenReady().then(onReady);
@@ -155,7 +169,6 @@ export function main() {
await getOrCreateMainWindow(entryFilePath); // Create the main window if there are no open windows
});
});
-
}
// Run the main method
diff --git a/src/options.ts b/src/options.ts
index e0a3532..b2c9857 100644
--- a/src/options.ts
+++ b/src/options.ts
@@ -1,7 +1,7 @@
import type { BrowserWindowConstructorOptions } from 'electron';
import { Windows } from './enum/windows';
import path from 'node:path';
-import { isDevMode } from './lib/devmode';
+import { isDevMode } from './lib/utils/devmode';
import { Platform } from './enum/platform';
export const browserWindowOptions = {
diff --git a/src/preload.ts b/src/preload.ts
index 466de6b..f980bef 100644
--- a/src/preload.ts
+++ b/src/preload.ts
@@ -1,29 +1,30 @@
// See the Electron documentation for details on how to use preload scripts:
// https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts
-import {
- contextBridge,
- ipcRenderer,
- IpcRendererEvent,
- webUtils
-} from 'electron';
+import { contextBridge, ipcRenderer, IpcRendererEvent, webUtils } from 'electron';
import { IpcEvent } from './enum/ipc-event';
+import { VideoFormat } from '@/enum/video-format';
+import { AudioFormat } from '@/enum/audio-format';
+import { ImageFormat } from '@/enum/image-format';
+import { Media } from './types/media';
+import { ColorMode } from './types/theme';
-async function preload() {
+async function preload(): Promise {
await setupGlobals();
}
/**
* Expose Electron API in the main world
- *
- * @returns {Promise}
*/
-export async function setupGlobals() {
+export async function setupGlobals(): Promise {
contextBridge.exposeInMainWorld('electron', {
arch: process.arch,
platform: process.platform,
selectDirectory() {
return ipcRenderer.invoke(IpcEvent.DIALOG_SELECT_DIRECTORY);
},
+ getSystemTheme() {
+ return ipcRenderer.sendSync(IpcEvent.GET_SYSTEM_THEME) as ColorMode;
+ },
getDesktopPath() {
return ipcRenderer.invoke(IpcEvent.GET_DESKTOP_PATH);
},
@@ -36,26 +37,24 @@ export async function setupGlobals() {
cancelConversion() {
return ipcRenderer.invoke(IpcEvent.CANCEL_CONVERSION);
},
- convertVideo(
+ convertMedia(
id: string,
filePath: string,
- outputFormat: string,
- saveDirectory: string
- ) {
- return ipcRenderer.invoke(
- IpcEvent.CONVERT_VIDEO,
- { id, filePath, outputFormat, saveDirectory }
- );
- },
- on(channel: string, callback: (
- event: IpcRendererEvent,
- ...args: unknown[]) => void
+ outputFormat: VideoFormat | AudioFormat | ImageFormat,
+ saveDirectory: string,
+ mediaType: Media,
) {
+ return ipcRenderer.invoke(IpcEvent.CONVERT_MEDIA, { id, filePath, outputFormat, saveDirectory, mediaType });
+ },
+ send(channel: string, ...args: unknown[]) {
+ ipcRenderer.send(channel, ...args);
+ },
+ on(channel: string, callback: (event: IpcRendererEvent, ...args: unknown[]) => void) {
ipcRenderer.on(channel, callback);
},
removeAllListeners(channel: string) {
ipcRenderer.removeAllListeners(channel);
- }
+ },
});
}
diff --git a/src/types/adapter.ts b/src/types/adapter.ts
new file mode 100644
index 0000000..d8a482b
--- /dev/null
+++ b/src/types/adapter.ts
@@ -0,0 +1,17 @@
+export interface Adapter {
+ /**
+ * Converts the file at the given path to the specified output format.
+ */
+ convert(
+ id: string,
+ filePath: string,
+ outputFormat: string,
+ saveDirectory: string,
+ event: Electron.IpcMainInvokeEvent,
+ ): Promise;
+
+ /**
+ * Cancels the FFmpeg conversion process with the given ID.
+ */
+ cancel(id: string): boolean;
+}
diff --git a/src/types/item.ts b/src/types/item.ts
index 658115b..70cdcfb 100644
--- a/src/types/item.ts
+++ b/src/types/item.ts
@@ -1,5 +1,8 @@
+import { Media } from './media';
+
export interface Item extends File {
id: number | string;
+ type: Media;
path: string;
converted: boolean;
outputFormat?: string;
diff --git a/src/types/media.ts b/src/types/media.ts
new file mode 100644
index 0000000..e033f73
--- /dev/null
+++ b/src/types/media.ts
@@ -0,0 +1,3 @@
+import { Media as MediaType } from '../enum/media';
+
+export type Media = MediaType.VIDEO | MediaType.IMAGE | MediaType.AUDIO;
diff --git a/src/types/theme.ts b/src/types/theme.ts
new file mode 100644
index 0000000..57a9490
--- /dev/null
+++ b/src/types/theme.ts
@@ -0,0 +1 @@
+export type ColorMode = 'light' | 'dark' | 'system';
diff --git a/src/ui/app.vue b/src/ui/app.vue
index 896ce7a..f488514 100644
--- a/src/ui/app.vue
+++ b/src/ui/app.vue
@@ -1,9 +1,12 @@
-
+
-
+
-
+
+
+
+
diff --git a/src/ui/blocks/AudioConverter.vue b/src/ui/blocks/AudioConverter.vue
index 4bd96d7..53d7c40 100644
--- a/src/ui/blocks/AudioConverter.vue
+++ b/src/ui/blocks/AudioConverter.vue
@@ -1,29 +1,16 @@
@@ -48,8 +40,8 @@ onMounted(async () => {
@@ -82,22 +74,14 @@ onMounted(async () => {
-
-
+
{{ t('buttons.cancel') }}
diff --git a/src/ui/blocks/Controls.vue b/src/ui/blocks/Controls.vue
index 2171fba..d432d5f 100644
--- a/src/ui/blocks/Controls.vue
+++ b/src/ui/blocks/Controls.vue
@@ -8,9 +8,12 @@ const props = defineProps<{
-
+
-
diff --git a/src/ui/blocks/Dropfile.vue b/src/ui/blocks/Dropfile.vue
index e624d20..180687a 100644
--- a/src/ui/blocks/Dropfile.vue
+++ b/src/ui/blocks/Dropfile.vue
@@ -1,9 +1,7 @@
@@ -67,13 +70,27 @@ function sentenceCase(str: string) {
@dragover="handleDragOver"
@dragleave="handleDragLeave"
@drop="handleDrop"
+ role="button"
+ aria-label="Upload files"
+ tabindex="0"
+ @keydown.enter="triggerFileInput"
>
-
+
{{ text }}
{{ t('upload.message') }}
- {{ t('upload.select') }}
+ {{
+ t('upload.select')
+ }}
diff --git a/src/ui/blocks/FileItem.vue b/src/ui/blocks/FileItem.vue
index 6e312af..c7247f2 100644
--- a/src/ui/blocks/FileItem.vue
+++ b/src/ui/blocks/FileItem.vue
@@ -1,17 +1,8 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t('buttons.clear') }}
+
+
+
+
+
+
+ {{ t('buttons.cancel') }}
+
+
+
+ {{ t('buttons.convert') }}
+
+
+
+ {{ t('buttons.converting') }}
+
+
+
+
+
+
diff --git a/src/ui/blocks/LanguageSwitcher.vue b/src/ui/blocks/LanguageSwitcher.vue
index 4125a8e..9a0f4d8 100644
--- a/src/ui/blocks/LanguageSwitcher.vue
+++ b/src/ui/blocks/LanguageSwitcher.vue
@@ -1,9 +1,7 @@
-
+
-
diff --git a/src/ui/blocks/SaveDirectory.vue b/src/ui/blocks/SaveDirectory.vue
index df50be8..9086cc1 100644
--- a/src/ui/blocks/SaveDirectory.vue
+++ b/src/ui/blocks/SaveDirectory.vue
@@ -1,26 +1,23 @@
-
-
+
+
diff --git a/src/ui/blocks/ThemeSwitcher.vue b/src/ui/blocks/ThemeSwitcher.vue
index 25c073f..55e68cd 100644
--- a/src/ui/blocks/ThemeSwitcher.vue
+++ b/src/ui/blocks/ThemeSwitcher.vue
@@ -1,29 +1,27 @@
-
-
+
+
+
-
diff --git a/src/ui/blocks/VideoConverter.vue b/src/ui/blocks/VideoConverter.vue
index f23e169..b3cfb45 100644
--- a/src/ui/blocks/VideoConverter.vue
+++ b/src/ui/blocks/VideoConverter.vue
@@ -1,29 +1,16 @@
@@ -48,8 +40,8 @@ onMounted(async () => {
@@ -82,22 +74,14 @@ onMounted(async () => {
-
+
{{ t('buttons.clear') }}
-
+
{{ t('buttons.cancel') }}
diff --git a/src/ui/blocks/index.ts b/src/ui/blocks/index.ts
index b16c5fd..77331c0 100644
--- a/src/ui/blocks/index.ts
+++ b/src/ui/blocks/index.ts
@@ -1,4 +1,5 @@
import ThemeSwitcher from './ThemeSwitcher.vue';
+import LanguageSwitcher from './LanguageSwitcher.vue';
import Dropfile from './Dropfile.vue';
import SaveDirectory from './SaveDirectory.vue';
import Controls from './Controls.vue';
@@ -6,9 +7,11 @@ import Options from './Options.vue';
import FileItem from './FileItem.vue';
import VideoConverter from './VideoConverter.vue';
import AudioConverter from './AudioConverter.vue';
+import ImageConverter from './ImageConverter.vue';
export {
ThemeSwitcher,
+ LanguageSwitcher,
Dropfile,
SaveDirectory,
Controls,
@@ -16,4 +19,5 @@ export {
FileItem,
VideoConverter,
AudioConverter,
+ ImageConverter,
};
diff --git a/src/ui/components/badge/index.ts b/src/ui/components/badge/index.ts
index 76fb632..71964b2 100644
--- a/src/ui/components/badge/index.ts
+++ b/src/ui/components/badge/index.ts
@@ -7,12 +7,9 @@ export const badgeVariants = cva(
{
variants: {
variant: {
- default:
- 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
- secondary:
- 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
- destructive:
- 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
+ default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
+ secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
+ destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
outline: 'text-foreground',
},
},
diff --git a/src/ui/components/breadcrumb/Breadcrumb.vue b/src/ui/components/breadcrumb/Breadcrumb.vue
index 72ca143..6034230 100644
--- a/src/ui/components/breadcrumb/Breadcrumb.vue
+++ b/src/ui/components/breadcrumb/Breadcrumb.vue
@@ -1,9 +1,9 @@
diff --git a/src/ui/components/breadcrumb/BreadcrumbEllipsis.vue b/src/ui/components/breadcrumb/BreadcrumbEllipsis.vue
index e197f8a..6439f92 100644
--- a/src/ui/components/breadcrumb/BreadcrumbEllipsis.vue
+++ b/src/ui/components/breadcrumb/BreadcrumbEllipsis.vue
@@ -9,11 +9,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/breadcrumb/BreadcrumbItem.vue b/src/ui/components/breadcrumb/BreadcrumbItem.vue
index e95d815..47fbb0c 100644
--- a/src/ui/components/breadcrumb/BreadcrumbItem.vue
+++ b/src/ui/components/breadcrumb/BreadcrumbItem.vue
@@ -1,16 +1,14 @@
-
+
diff --git a/src/ui/components/breadcrumb/BreadcrumbLink.vue b/src/ui/components/breadcrumb/BreadcrumbLink.vue
index 3ef8c45..0ffeb9e 100644
--- a/src/ui/components/breadcrumb/BreadcrumbLink.vue
+++ b/src/ui/components/breadcrumb/BreadcrumbLink.vue
@@ -1,19 +1,15 @@
-
+
diff --git a/src/ui/components/breadcrumb/BreadcrumbPage.vue b/src/ui/components/breadcrumb/BreadcrumbPage.vue
index 9244597..17eba0f 100644
--- a/src/ui/components/breadcrumb/BreadcrumbPage.vue
+++ b/src/ui/components/breadcrumb/BreadcrumbPage.vue
@@ -8,12 +8,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/breadcrumb/BreadcrumbSeparator.vue b/src/ui/components/breadcrumb/BreadcrumbSeparator.vue
index a236332..fa79800 100644
--- a/src/ui/components/breadcrumb/BreadcrumbSeparator.vue
+++ b/src/ui/components/breadcrumb/BreadcrumbSeparator.vue
@@ -9,11 +9,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/button/Button.vue b/src/ui/components/button/Button.vue
index 95e983e..0100949 100644
--- a/src/ui/components/button/Button.vue
+++ b/src/ui/components/button/Button.vue
@@ -16,11 +16,7 @@ const props = withDefaults(defineProps(), {
-
+
diff --git a/src/ui/components/button/index.ts b/src/ui/components/button/index.ts
index cc68575..375d0e1 100644
--- a/src/ui/components/button/index.ts
+++ b/src/ui/components/button/index.ts
@@ -9,12 +9,9 @@ export const buttonVariants = cva(
variants: {
variant: {
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
- destructive:
- 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
- outline:
- 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
- secondary:
- 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
+ destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
+ outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
+ secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
diff --git a/src/ui/components/card/Card.vue b/src/ui/components/card/Card.vue
index 9688143..f07d9f5 100644
--- a/src/ui/components/card/Card.vue
+++ b/src/ui/components/card/Card.vue
@@ -8,13 +8,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/card/CardTitle.vue b/src/ui/components/card/CardTitle.vue
index 5e73a22..b696f6e 100644
--- a/src/ui/components/card/CardTitle.vue
+++ b/src/ui/components/card/CardTitle.vue
@@ -8,10 +8,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/combobox/Combobox.vue b/src/ui/components/combobox/Combobox.vue
index cd364d2..9265813 100644
--- a/src/ui/components/combobox/Combobox.vue
+++ b/src/ui/components/combobox/Combobox.vue
@@ -3,24 +3,14 @@ import { Check, ChevronsUpDown } from 'lucide-vue-next';
import { ref } from 'vue';
import { cn } from '@/ui/utils';
import { Button } from '@/ui/components/button';
-import {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList
-} from '@/ui/components/command';
-import {
- Popover,
- PopoverContent,
- PopoverTrigger,
-} from '@/ui/components/popover';
+import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/ui/components/command';
+import { Popover, PopoverContent, PopoverTrigger } from '@/ui/components/popover';
import { Badge } from '@/ui/components/badge';
import { useI18n } from 'vue-i18n';
const emit = defineEmits(['change']);
const open = ref(false);
+const listId = `combobox-list-${Math.random().toString(36).substr(2, 9)}`;
const { t } = useI18n();
@@ -48,7 +38,9 @@ function setOption(event: CustomEvent) {
variant="secondary"
role="combobox"
:aria-expanded="open"
- class="justify-between shadow-none">
+ :aria-controls="listId"
+ class="justify-between shadow-none"
+ >
{{ t('formats.convertsTo') }}:
{{ options.find((option: string) => option === value) }}
@@ -62,17 +54,10 @@ function setOption(event: CustomEvent) {
{{ t('formats.empty') }}
-
+
-
-
+
+
{{ option }}
diff --git a/src/ui/components/command/Command.vue b/src/ui/components/command/Command.vue
index e834bd3..5c676f1 100644
--- a/src/ui/components/command/Command.vue
+++ b/src/ui/components/command/Command.vue
@@ -4,7 +4,7 @@ import type { ComboboxRootEmits, ComboboxRootProps } from 'radix-vue';
import { ComboboxRoot, useForwardPropsEmits } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = withDefaults(defineProps(), {
+const props = withDefaults(defineProps(), {
open: true,
modelValue: '',
});
@@ -23,7 +23,9 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/command/CommandDialog.vue b/src/ui/components/command/CommandDialog.vue
index c4f8f2c..22634f3 100644
--- a/src/ui/components/command/CommandDialog.vue
+++ b/src/ui/components/command/CommandDialog.vue
@@ -13,7 +13,9 @@ const forwarded = useForwardPropsEmits(props, emits);
diff --git a/src/ui/components/command/CommandItem.vue b/src/ui/components/command/CommandItem.vue
index 59e2fb4..b26aec6 100644
--- a/src/ui/components/command/CommandItem.vue
+++ b/src/ui/components/command/CommandItem.vue
@@ -4,7 +4,7 @@ import type { ComboboxItemEmits, ComboboxItemProps } from 'radix-vue';
import { ComboboxItem, useForwardPropsEmits } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const emits = defineEmits();
const delegatedProps = computed(() => {
@@ -19,7 +19,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/command/CommandList.vue b/src/ui/components/command/CommandList.vue
index a51946b..b2f9d36 100644
--- a/src/ui/components/command/CommandList.vue
+++ b/src/ui/components/command/CommandList.vue
@@ -5,7 +5,7 @@ import { ComboboxContent, useForwardPropsEmits } from 'radix-vue';
import { cn } from '@/ui/utils';
import { ScrollArea } from '@/ui/components/scroll-area';
-const props = withDefaults(defineProps(), {
+const props = withDefaults(defineProps(), {
dismissable: false,
});
const emits = defineEmits();
diff --git a/src/ui/components/command/CommandSeparator.vue b/src/ui/components/command/CommandSeparator.vue
index 0597a7b..f4cddd5 100644
--- a/src/ui/components/command/CommandSeparator.vue
+++ b/src/ui/components/command/CommandSeparator.vue
@@ -4,7 +4,7 @@ import type { ComboboxSeparatorProps } from 'radix-vue';
import { ComboboxSeparator } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -14,10 +14,7 @@ const delegatedProps = computed(() => {
-
+
diff --git a/src/ui/components/dialog/DialogContent.vue b/src/ui/components/dialog/DialogContent.vue
index 797da7b..9c289a3 100644
--- a/src/ui/components/dialog/DialogContent.vue
+++ b/src/ui/components/dialog/DialogContent.vue
@@ -12,7 +12,7 @@ import {
import { X } from 'lucide-vue-next';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const emits = defineEmits();
const delegatedProps = computed(() => {
@@ -27,14 +27,16 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/dialog/DialogDescription.vue b/src/ui/components/dialog/DialogDescription.vue
index d9062ce..82b3b27 100644
--- a/src/ui/components/dialog/DialogDescription.vue
+++ b/src/ui/components/dialog/DialogDescription.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { DialogDescription, type DialogDescriptionProps, useForwardProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -15,10 +15,7 @@ const forwardedProps = useForwardProps(delegatedProps);
-
+
diff --git a/src/ui/components/dialog/DialogFooter.vue b/src/ui/components/dialog/DialogFooter.vue
index 3f49985..7d75a52 100644
--- a/src/ui/components/dialog/DialogFooter.vue
+++ b/src/ui/components/dialog/DialogFooter.vue
@@ -2,17 +2,11 @@
import type { HTMLAttributes } from 'vue';
import { cn } from '@/ui/utils';
-const props = defineProps<{ class?: HTMLAttributes['class']; }>();
+const props = defineProps<{ class?: HTMLAttributes['class'] }>();
-
+
diff --git a/src/ui/components/dialog/DialogHeader.vue b/src/ui/components/dialog/DialogHeader.vue
index 472d1ad..121e128 100644
--- a/src/ui/components/dialog/DialogHeader.vue
+++ b/src/ui/components/dialog/DialogHeader.vue
@@ -8,9 +8,7 @@ const props = defineProps<{
-
+
diff --git a/src/ui/components/dialog/DialogScrollContent.vue b/src/ui/components/dialog/DialogScrollContent.vue
index 6aa9005..a393c47 100644
--- a/src/ui/components/dialog/DialogScrollContent.vue
+++ b/src/ui/components/dialog/DialogScrollContent.vue
@@ -12,7 +12,7 @@ import {
import { X } from 'lucide-vue-next';
import { cn } from '@/ui/utils';
-const props = defineProps
();
+const props = defineProps();
const emits = defineEmits();
const delegatedProps = computed(() => {
@@ -27,28 +27,29 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
{
- const originalEvent = event.detail.originalEvent;
- const target = originalEvent.target as HTMLElement;
- if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
- event.preventDefault();
+ @pointer-down-outside="
+ (event) => {
+ const originalEvent = event.detail.originalEvent;
+ const target = originalEvent.target as HTMLElement;
+ if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
+ event.preventDefault();
+ }
}
- }"
+ "
>
-
+
Close
diff --git a/src/ui/components/dialog/DialogTitle.vue b/src/ui/components/dialog/DialogTitle.vue
index 47cc80b..cafdf4e 100644
--- a/src/ui/components/dialog/DialogTitle.vue
+++ b/src/ui/components/dialog/DialogTitle.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { DialogTitle, type DialogTitleProps, useForwardProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -15,14 +15,7 @@ const forwardedProps = useForwardProps(delegatedProps);
-
+
diff --git a/src/ui/components/dropdown-menu/DropdownMenu.vue b/src/ui/components/dropdown-menu/DropdownMenu.vue
index 5952c12..56a5575 100644
--- a/src/ui/components/dropdown-menu/DropdownMenu.vue
+++ b/src/ui/components/dropdown-menu/DropdownMenu.vue
@@ -1,5 +1,10 @@
diff --git a/src/ui/components/menubar/MenubarRadioItem.vue b/src/ui/components/menubar/MenubarRadioItem.vue
index fce8e41..18840fb 100644
--- a/src/ui/components/menubar/MenubarRadioItem.vue
+++ b/src/ui/components/menubar/MenubarRadioItem.vue
@@ -7,12 +7,10 @@ import {
type MenubarRadioItemProps,
useForwardPropsEmits,
} from 'radix-vue';
-import {
- Dot
-} from 'lucide-vue-next';
+import { Dot } from 'lucide-vue-next';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const emits = defineEmits();
const delegatedProps = computed(() => {
@@ -27,10 +25,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/menubar/MenubarSeparator.vue b/src/ui/components/menubar/MenubarSeparator.vue
index 0453a5a..c49459a 100644
--- a/src/ui/components/menubar/MenubarSeparator.vue
+++ b/src/ui/components/menubar/MenubarSeparator.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { MenubarSeparator, type MenubarSeparatorProps, useForwardProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
diff --git a/src/ui/components/menubar/MenubarSubContent.vue b/src/ui/components/menubar/MenubarSubContent.vue
index 8ea61dd..612091f 100644
--- a/src/ui/components/menubar/MenubarSubContent.vue
+++ b/src/ui/components/menubar/MenubarSubContent.vue
@@ -9,7 +9,7 @@ import {
} from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const emits = defineEmits();
@@ -26,11 +26,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/menubar/MenubarSubTrigger.vue b/src/ui/components/menubar/MenubarSubTrigger.vue
index 3fd7ca3..cfcd57a 100644
--- a/src/ui/components/menubar/MenubarSubTrigger.vue
+++ b/src/ui/components/menubar/MenubarSubTrigger.vue
@@ -4,7 +4,7 @@ import { MenubarSubTrigger, type MenubarSubTriggerProps, useForwardProps } from
import { ChevronRight } from 'lucide-vue-next';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -18,11 +18,13 @@ const forwardedProps = useForwardProps(delegatedProps);
diff --git a/src/ui/components/menubar/MenubarTrigger.vue b/src/ui/components/menubar/MenubarTrigger.vue
index 31f6236..14275d6 100644
--- a/src/ui/components/menubar/MenubarTrigger.vue
+++ b/src/ui/components/menubar/MenubarTrigger.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { MenubarTrigger, type MenubarTriggerProps, useForwardProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -17,11 +17,12 @@ const forwardedProps = useForwardProps(delegatedProps);
diff --git a/src/ui/components/popover/PopoverContent.vue b/src/ui/components/popover/PopoverContent.vue
index 4ea992b..6f4a0ba 100644
--- a/src/ui/components/popover/PopoverContent.vue
+++ b/src/ui/components/popover/PopoverContent.vue
@@ -13,13 +13,10 @@ defineOptions({
inheritAttrs: false,
});
-const props = withDefaults(
- defineProps(),
- {
- align: 'center',
- sideOffset: 4,
- },
-);
+const props = withDefaults(defineProps(), {
+ align: 'center',
+ sideOffset: 4,
+});
const emits = defineEmits();
const delegatedProps = computed(() => {
@@ -35,11 +32,12 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
diff --git a/src/ui/components/progress/Progress.vue b/src/ui/components/progress/Progress.vue
index de83ed4..4770149 100644
--- a/src/ui/components/progress/Progress.vue
+++ b/src/ui/components/progress/Progress.vue
@@ -1,18 +1,11 @@
+
+
+
+
diff --git a/src/ui/components/spinner/index.ts b/src/ui/components/spinner/index.ts
new file mode 100644
index 0000000..b2cd020
--- /dev/null
+++ b/src/ui/components/spinner/index.ts
@@ -0,0 +1 @@
+export { default as Spinner } from './Spinner.vue';
diff --git a/src/ui/components/tabs/TabsContent.vue b/src/ui/components/tabs/TabsContent.vue
index 07861d3..9c88770 100644
--- a/src/ui/components/tabs/TabsContent.vue
+++ b/src/ui/components/tabs/TabsContent.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { TabsContent, type TabsContentProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -14,7 +14,12 @@ const delegatedProps = computed(() => {
diff --git a/src/ui/components/tabs/TabsList.vue b/src/ui/components/tabs/TabsList.vue
index 68b72c1..24771ad 100644
--- a/src/ui/components/tabs/TabsList.vue
+++ b/src/ui/components/tabs/TabsList.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { TabsList, type TabsListProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -15,10 +15,7 @@ const delegatedProps = computed(() => {
diff --git a/src/ui/components/tabs/TabsTrigger.vue b/src/ui/components/tabs/TabsTrigger.vue
index 418a5e1..d160c08 100644
--- a/src/ui/components/tabs/TabsTrigger.vue
+++ b/src/ui/components/tabs/TabsTrigger.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { TabsTrigger, type TabsTriggerProps, useForwardProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -17,10 +17,12 @@ const forwardedProps = useForwardProps(delegatedProps);
diff --git a/src/ui/components/titlebar/Titlebar.vue b/src/ui/components/titlebar/Titlebar.vue
index 7a9a93f..d7ff791 100644
--- a/src/ui/components/titlebar/Titlebar.vue
+++ b/src/ui/components/titlebar/Titlebar.vue
@@ -1,6 +1,6 @@
diff --git a/src/ui/components/toast/Toast.vue b/src/ui/components/toast/Toast.vue
index b055d75..3cd91d3 100644
--- a/src/ui/components/toast/Toast.vue
+++ b/src/ui/components/toast/Toast.vue
@@ -18,11 +18,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits);
-
+
diff --git a/src/ui/components/toast/ToastAction.vue b/src/ui/components/toast/ToastAction.vue
index 7a417f2..b520d9d 100644
--- a/src/ui/components/toast/ToastAction.vue
+++ b/src/ui/components/toast/ToastAction.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { ToastAction, type ToastActionProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -13,7 +13,15 @@ const delegatedProps = computed(() => {
-
+
diff --git a/src/ui/components/toast/ToastClose.vue b/src/ui/components/toast/ToastClose.vue
index 824efd6..3130f00 100644
--- a/src/ui/components/toast/ToastClose.vue
+++ b/src/ui/components/toast/ToastClose.vue
@@ -4,9 +4,11 @@ import { ToastClose, type ToastCloseProps } from 'radix-vue';
import { X } from 'lucide-vue-next';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps<
+ ToastCloseProps & {
+ class?: HTMLAttributes['class'];
+ }
+>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -16,7 +18,15 @@ const delegatedProps = computed(() => {
-
+
diff --git a/src/ui/components/toast/ToastDescription.vue b/src/ui/components/toast/ToastDescription.vue
index 4eeda73..a4d93dd 100644
--- a/src/ui/components/toast/ToastDescription.vue
+++ b/src/ui/components/toast/ToastDescription.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { ToastDescription, type ToastDescriptionProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
diff --git a/src/ui/components/toast/ToastTitle.vue b/src/ui/components/toast/ToastTitle.vue
index 126438d..1734d0d 100644
--- a/src/ui/components/toast/ToastTitle.vue
+++ b/src/ui/components/toast/ToastTitle.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { ToastTitle, type ToastTitleProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
diff --git a/src/ui/components/toast/ToastViewport.vue b/src/ui/components/toast/ToastViewport.vue
index f5d6c95..5b98f75 100644
--- a/src/ui/components/toast/ToastViewport.vue
+++ b/src/ui/components/toast/ToastViewport.vue
@@ -3,7 +3,7 @@ import { type HTMLAttributes, computed } from 'vue';
import { ToastViewport, type ToastViewportProps } from 'radix-vue';
import { cn } from '@/ui/utils';
-const props = defineProps();
+const props = defineProps();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
@@ -13,5 +13,13 @@ const delegatedProps = computed(() => {
-
+
diff --git a/src/ui/components/toast/index.ts b/src/ui/components/toast/index.ts
index d0b7a48..aa6260a 100644
--- a/src/ui/components/toast/index.ts
+++ b/src/ui/components/toast/index.ts
@@ -19,8 +19,7 @@ export const toastVariants = cva(
variants: {
variant: {
default: 'border bg-background text-foreground',
- destructive:
- 'destructive group border-destructive bg-destructive text-destructive-foreground',
+ destructive: 'destructive group border-destructive bg-destructive text-destructive-foreground',
},
},
defaultVariants: {
diff --git a/src/ui/components/toast/use-toast.ts b/src/ui/components/toast/use-toast.ts
index 0cab6cb..8450ecb 100644
--- a/src/ui/components/toast/use-toast.ts
+++ b/src/ui/components/toast/use-toast.ts
@@ -5,10 +5,7 @@ import type { ToastProps } from '.';
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;
-export type StringOrVNode =
- | string
- | VNode
- | (() => VNode);
+export type StringOrVNode = string | VNode | (() => VNode);
type ToasterToast = ToastProps & {
id: string;
@@ -35,21 +32,21 @@ type ActionType = typeof actionTypes;
type Action =
| {
- type: ActionType['ADD_TOAST'];
- toast: ToasterToast;
- }
+ type: ActionType['ADD_TOAST'];
+ toast: ToasterToast;
+ }
| {
- type: ActionType['UPDATE_TOAST'];
- toast: Partial;
- }
+ type: ActionType['UPDATE_TOAST'];
+ toast: Partial;
+ }
| {
- type: ActionType['DISMISS_TOAST'];
- toastId?: ToasterToast['id'];
- }
+ type: ActionType['DISMISS_TOAST'];
+ toastId?: ToasterToast['id'];
+ }
| {
- type: ActionType['REMOVE_TOAST'];
- toastId?: ToasterToast['id'];
- };
+ type: ActionType['REMOVE_TOAST'];
+ toastId?: ToasterToast['id'];
+ };
interface State {
toasts: ToasterToast[];
@@ -58,8 +55,7 @@ interface State {
const toastTimeouts = new Map>();
function addToRemoveQueue(toastId: string) {
- if (toastTimeouts.has(toastId))
- return;
+ if (toastTimeouts.has(toastId)) return;
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId);
@@ -83,9 +79,7 @@ function dispatch(action: Action) {
break;
case actionTypes.UPDATE_TOAST:
- state.value.toasts = state.value.toasts.map(t =>
- t.id === action.toast.id ? { ...t, ...action.toast } : t,
- );
+ state.value.toasts = state.value.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t));
break;
case actionTypes.DISMISS_TOAST: {
@@ -93,29 +87,21 @@ function dispatch(action: Action) {
if (toastId) {
addToRemoveQueue(toastId);
- }
- else {
+ } else {
state.value.toasts.forEach((toast) => {
addToRemoveQueue(toast.id);
});
}
- state.value.toasts = state.value.toasts.map(t =>
- t.id === toastId || toastId === undefined
- ? {
- ...t,
- open: false,
- }
- : t,
+ state.value.toasts = state.value.toasts.map((t) =>
+ t.id === toastId || toastId === undefined ? { ...t, open: false } : t,
);
break;
}
case actionTypes.REMOVE_TOAST:
- if (action.toastId === undefined)
- state.value.toasts = [];
- else
- state.value.toasts = state.value.toasts.filter(t => t.id !== action.toastId);
+ if (action.toastId === undefined) state.value.toasts = [];
+ else state.value.toasts = state.value.toasts.filter((t) => t.id !== action.toastId);
break;
}
@@ -149,8 +135,7 @@ function toast(props: Toast) {
id,
open: true,
onOpenChange: (open: boolean) => {
- if (!open)
- dismiss();
+ if (!open) dismiss();
},
},
});
diff --git a/src/ui/components/tooltip/TooltipContent.vue b/src/ui/components/tooltip/TooltipContent.vue
index 16a14c3..562fc28 100644
--- a/src/ui/components/tooltip/TooltipContent.vue
+++ b/src/ui/components/tooltip/TooltipContent.vue
@@ -1,13 +1,19 @@