diff --git a/.husky/pre-commit b/.husky/pre-commit index 3867a0f..a845b85 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -npm run lint +npm run lint \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push index 25f5fe3..8c0a93a 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,2 +1,3 @@ npm run lint npm run typecheck +npm run git-image \ No newline at end of file diff --git a/README.md b/README.md index e1ee109..a00bf17 100644 --- a/README.md +++ b/README.md @@ -28,28 +28,27 @@ npm install npm run dev ``` -### Public images and image compression +### Image compression -Place public images in `public_images` folder. +There are 2 ways to compress image images -For compressing image, +- Double click on `image-compression.bat` or `image-compression.sh` to run image compression app. You can drag and drop files to convert images. + You can also run image compression app with: `npm run image` +- Commiting will compress image and delete origin source on pre-commit with husky. But this won't be converted until you commit. And it creates extra commit. -``` -npm run compress-image -``` +## Publishing Articles -⚠️ Most of time you wouldn't need to run this. This is going to remove old images and create new compressed images. +1. There are 2 ways to add an image and the added image will turn into a `.avif` file (used for SEO). Optimal dimensions are 1280x720. -## Publishing Articles +- Double click on image-compression.bat or image-compression.sh to run image compression app. You can drag and drop files to convert images. You can also run image compression app with: `npm run image` +- Add an image inside the `public/img/news` folder. Commiting will compress image and delete origin source on pre-commit with husky. But this won't be converted until you commit. And it creates extra commit. -1. Add an image inside the `public_images/news` folder. Optimal dimensions are 1280x720. -2. Run `npm run compress-image`. This will compress your png image into a `.avif` file (used for SEO). -3. Create a new markdown file inside `content/news` folder. The file name must follow the guidelines for optimal SEO results: +2. Create a new markdown file inside `content/news` folder. The file name must follow the guidelines for optimal SEO results: - File name must be kebab case. - File name must all be lowercase -4. Paste the article template (see below) inside the file -5. Write your content -6. Create a pull request and get it merged +3. Paste the article template (see below) inside the file +4. Write your content +5. Create a pull request and get it merged ```shell --- @@ -72,7 +71,7 @@ Your content here... ### Adding author images -Follow steps 1 - 2 in the instructions above but place your avatar inside the `public_images/authors` folder. +Follow steps 1 in the instructions above but place your avatar inside the `public_images/authors` folder. ### Mirrorlist Automation diff --git a/git-image-compression.js b/git-image-compression.js new file mode 100644 index 0000000..1014443 --- /dev/null +++ b/git-image-compression.js @@ -0,0 +1,138 @@ +import { exec } from "child_process"; +import sharp from "sharp"; +import fs from "fs"; +import path from "path"; + +const supportedFormats = [".png", ".jpg", ".jpeg", ".webp", ".tiff", ".bmp"]; + +function getGitChanges() +{ + return new Promise((resolve, reject) => + { + exec("git status --porcelain", (err, stdout, stderr) => + { + if (err) + { + return reject(`Error getting git status: ${ stderr }`); + } + + const files = stdout.split("\n") + .filter(line => + { + const fileStatus = line.trim().split(" ")[0]; + const filePath = line.slice(3).trim().replace(/['"]/g, ""); + const ext = path.extname(filePath).toLowerCase(); + + return (fileStatus === "M" || fileStatus === "A" || fileStatus === "??") && supportedFormats.includes(ext); + }) + .map(line => line.slice(3).trim().replace(/['"]/g, "")); + + resolve(files); + }); + }); +} + +async function convertImageToAvif(inputPath) +{ + try + { + const outputPath = path.format({ + dir: path.dirname(inputPath), + name: path.parse(inputPath).name, + ext: ".avif", + }); + + await sharp(inputPath) + .toFormat("avif", { quality: 70 }) + .toFile(outputPath); + + console.log(`Converted ${ inputPath } to ${ outputPath }`); + + fs.unlinkSync(inputPath); + console.log(`Removed original image: ${ inputPath }`); + } + catch (err) + { + console.error(`Error converting ${ inputPath }: ${ err.message }`); + } +} + +async function processGitChanges() +{ + try + { + const changes = await getGitChanges(); + console.log("Images to process:", changes); + + for (const file of changes) + { + const ext = path.extname(file).toLowerCase(); + + if (supportedFormats.includes(ext)) + { + const filePath = path.resolve(file); + + if (fs.existsSync(filePath)) + { + await convertImageToAvif(filePath); + } else + { + console.error(`File not found: ${ filePath }`); + } + } + } + + await new Promise((resolve, reject) => + { + exec("git add .", (err, stdout, stderr) => + { + if (err) + { + return reject(`Error staging changes: ${ stderr }`); + } + console.log("Staged converted files."); + resolve(stdout); + }); + }); + + const hasChanges = await new Promise((resolve) => + { + exec("git diff --cached --quiet", (err) => + { + if (err) + { + resolve(true); + } + else + { + resolve(false); + } + }); + }); + + if (hasChanges) + { + await new Promise((resolve, reject) => + { + exec("git commit -m \"Convert images to AVIF\"", (err, stdout, stderr) => + { + if (err) + { + return reject(`Error committing changes: ${ stderr }`); + } + console.log("Committed converted files."); + resolve(stdout); + }); + }); + } else + { + console.log("No changes to commit."); + } + } catch (err) + { + console.error("Error processing git changes:", err.message); + process.exit(1); + } +} + +processGitChanges(); \ No newline at end of file diff --git a/image-compression.bat b/image-compression.bat new file mode 100644 index 0000000..959cd07 --- /dev/null +++ b/image-compression.bat @@ -0,0 +1,4 @@ +@echo off +echo Running image-compression.js... +node image-compression.js +pause \ No newline at end of file diff --git a/image-compression.html b/image-compression.html new file mode 100644 index 0000000..33e26dd --- /dev/null +++ b/image-compression.html @@ -0,0 +1,238 @@ + + + + + + Image Converter + + + +

Image Compressor

+
+ +
+ +
+ + +
+ +
+
Drag and drop images here or click to upload
+ + + + +
+ +
+ + + + diff --git a/image-compression.js b/image-compression.js index a35c27b..7d8e198 100644 --- a/image-compression.js +++ b/image-compression.js @@ -1,72 +1,85 @@ +import express from "express"; +import multer from "multer"; import sharp from "sharp"; -import fs from "fs-extra"; import path from "path"; +import fs from "fs"; +import { exec } from "child_process"; +import { fileURLToPath } from "url"; +import { dirname } from "path"; -const sourceDir = process.argv[2]; -const targetDir = process.argv[3]; -const ExpectedQuality = Number(process.argv[4]); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const app = express(); +const port = 3100; -if (isNaN(ExpectedQuality)) -{ - console.error("Please provide a valid quality for the image."); - process.exit(1); -} - -if (!sourceDir || !targetDir) -{ - console.error("Please provide both source and target directories as arguments."); - process.exit(1); -} +app.use(express.json()); -if (fs.existsSync(targetDir)) +app.get("/", (req, res) => { - fs.removeSync(targetDir); - console.log(`Old directory removed: ${ targetDir }`); -} + res.sendFile(path.join(__dirname, "image-compression.html")); +}); -const allowedFormats = [".png", ".jpg", ".jpeg", ".webp", ".tiff", ".bmp"]; +const storage = multer.memoryStorage(); +const upload = multer({ storage }); -async function convertAndCopyImage(imagePath, targetPath) +app.post("/convert", upload.array("images"), async (req, res) => { - const ext = path.extname(imagePath).toLowerCase(); + let { outputDir, quality } = req.body; - if (ext === ".avif" || ext === ".svg" || ext === ".gif" || ext === ".ico") + if (!outputDir) { - await fs.copy(imagePath, targetPath); - console.log(`Copied: ${ targetPath }`); + return res.status(400).json({ error: "Output directory is required." }); } - else if (allowedFormats.includes(ext)) + + const isRelative = !path.isAbsolute(outputDir); + if (isRelative) { - await sharp(imagePath) - .toFormat("avif", { quality: ExpectedQuality }) - .toFile(targetPath.replace(path.extname(targetPath), ".avif")); - console.log(`Converted and copied: ${ targetPath.replace(path.extname(targetPath), ".avif") }`); + outputDir = path.resolve(__dirname, outputDir); } -} -async function processDirectory(dir) -{ - const files = fs.readdirSync(dir); + if (!fs.existsSync(outputDir)) + { + return res.status(400).json({ error: "Invalid output directory." }); + } - for (const file of files) + const qualityInt = parseInt(quality, 10); + if (isNaN(qualityInt) || qualityInt < 0 || qualityInt > 100) { - const fullPath = path.join(dir, file); - const targetPath = path.join(targetDir, path.relative(sourceDir, fullPath)); + return res.status(400).json({ error: "Quality must be an integer between 0 and 100." }); + } - if (fs.lstatSync(fullPath).isDirectory()) - { - await processDirectory(fullPath); - } else + try + { + const convertedFiles = []; + for (const file of req.files) { - const targetDirName = path.dirname(targetPath); - if (!fs.existsSync(targetDirName)) - { - fs.mkdirSync(targetDirName, { recursive: true }); - } + const avifTargetPath = path.join(outputDir, `${ path.parse(file.originalname).name }.avif`); - await convertAndCopyImage(fullPath, targetPath); + await sharp(file.buffer) + .toFormat("avif", { quality: qualityInt }) + .toFile(avifTargetPath); + + convertedFiles.push(avifTargetPath); } + + res.status(200).json({ message: "Images converted successfully.", files: convertedFiles }); + } catch (err) + { + res.status(500).json({ error: "Image conversion failed.", details: err.message }); } +}); + +app.listen(port, () => +{ + console.log(`Server running on http://localhost:${ port }`); + console.log("Turn off this window if you are done"); +}); + +function openBrowser(url) +{ + if (process.platform === "darwin") exec(`open ${ url }`); + else if (process.platform === "win32") exec(`start ${ url }`); + else exec(`xdg-open ${ url }`); } -processDirectory(sourceDir).catch(console.error); \ No newline at end of file +openBrowser(`http://localhost:${ port }`); \ No newline at end of file diff --git a/image-compression.sh b/image-compression.sh new file mode 100644 index 0000000..b0281fc --- /dev/null +++ b/image-compression.sh @@ -0,0 +1,3 @@ +#!/bin/bash +echo "Running image-compression.js..." +node image-compression.js \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index dee3f7c..a0e37f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,9 +21,11 @@ "@eslint/js": "^9.12.0", "eslint": "^9.12.0", "eslint-plugin-vue": "^9.28.0", + "express": "^4.21.1", "fs-extra": "^11.2.0", "globals": "^15.10.0", "husky": "^9.1.6", + "multer": "^1.4.5-lts.1", "sass": "^1.79.4", "sharp": "^0.33.5", "typescript": "^5.6.3", @@ -1502,10 +1504,11 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", - "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.3.tgz", + "integrity": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==", "devOptional": true, + "license": "Apache-2.0", "dependencies": { "levn": "^0.4.1" }, @@ -4300,6 +4303,20 @@ "node": ">=6.5" } }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", @@ -4422,6 +4439,13 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "dev": true, + "license": "MIT" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -4552,6 +4576,13 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -4711,6 +4742,48 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -4817,6 +4890,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/c12": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/c12/-/c12-1.11.2.tgz", @@ -4852,6 +4947,26 @@ "node": ">=8" } }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5223,6 +5338,55 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/confbox": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", @@ -5241,6 +5405,29 @@ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -5304,11 +5491,28 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-es": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==" }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true, + "license": "MIT" + }, "node_modules/copy-anything": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", @@ -5418,9 +5622,10 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -5748,6 +5953,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -6081,6 +6304,29 @@ "resolved": "https://registry.npmjs.org/errx/-/errx-0.1.0.tgz", "integrity": "sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==" }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", @@ -6403,6 +6649,66 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -6508,6 +6814,42 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6568,6 +6910,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -6696,6 +7048,26 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-port-please": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", @@ -6885,6 +7257,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -6958,6 +7343,45 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", @@ -7264,6 +7688,19 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -7407,6 +7844,16 @@ "url": "https://opencollective.com/ioredis" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/iron-webcrypto": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", @@ -8408,6 +8855,16 @@ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==" }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/meow": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", @@ -8461,6 +8918,16 @@ "node": ">=10" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -8474,6 +8941,16 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micromark": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", @@ -9035,6 +9512,29 @@ "node": ">=16" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -9194,6 +9694,38 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/nanoid": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", @@ -9222,6 +9754,16 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "devOptional": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nitropack": { "version": "2.9.7", "resolved": "https://registry.npmjs.org/nitropack/-/nitropack-2.9.7.tgz", @@ -10075,6 +10617,19 @@ "node": ">=0.10.0" } }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ofetch": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", @@ -10427,6 +10982,13 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, + "node_modules/path-to-regexp": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "dev": true, + "license": "MIT" + }, "node_modules/path-type": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", @@ -10978,6 +11540,20 @@ "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==" }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -10987,6 +11563,22 @@ "node": ">=6" } }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -11043,6 +11635,22 @@ "node": ">= 0.6" } }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/rc9": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", @@ -11674,6 +12282,13 @@ } ] }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, "node_modules/sass": { "version": "1.79.4", "resolved": "https://registry.npmjs.org/sass/-/sass-1.79.4.tgz", @@ -11825,6 +12440,24 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -11920,6 +12553,25 @@ "@types/hast": "^3.0.4" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -12167,6 +12819,15 @@ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==" }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/streamx": { "version": "2.20.1", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", @@ -12647,6 +13308,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true, + "license": "MIT" + }, "node_modules/typescript": { "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", @@ -12930,6 +13612,16 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unplugin": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz", @@ -13161,6 +13853,16 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -13173,6 +13875,16 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", @@ -14150,6 +14862,16 @@ "node": ">=0.4.0" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 1373f89..20f0d2f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "lint": "eslint --fix \"./**/*.{js,vue}\"", "format-check": "eslint \"./**/*.{js,vue}\"", "typecheck": "tsc --noEmit -p tsconfig.json --composite false", - "compress-image": "node image-compression ./public_images ./public/img 70", + "image": "node image-compression.js", + "git-image": "node git-image-compression.js", "prepare": "husky" }, "dependencies": { @@ -29,9 +30,11 @@ "@eslint/js": "^9.12.0", "eslint": "^9.12.0", "eslint-plugin-vue": "^9.28.0", + "express": "^4.21.1", "fs-extra": "^11.2.0", "globals": "^15.10.0", "husky": "^9.1.6", + "multer": "^1.4.5-lts.1", "sass": "^1.79.4", "sharp": "^0.33.5", "typescript": "^5.6.3", diff --git a/public_images/authors/andevrs.png b/public_images/authors/andevrs.png deleted file mode 100644 index 8d09bb1..0000000 Binary files a/public_images/authors/andevrs.png and /dev/null differ diff --git a/public_images/authors/arjan.png b/public_images/authors/arjan.png deleted file mode 100644 index 0118797..0000000 Binary files a/public_images/authors/arjan.png and /dev/null differ diff --git a/public_images/authors/nicholai.png b/public_images/authors/nicholai.png deleted file mode 100644 index 827a73b..0000000 Binary files a/public_images/authors/nicholai.png and /dev/null differ diff --git a/public_images/authors/red-otter.png b/public_images/authors/red-otter.png deleted file mode 100644 index 6a911c3..0000000 Binary files a/public_images/authors/red-otter.png and /dev/null differ diff --git a/public_images/authors/redot.png b/public_images/authors/redot.png deleted file mode 100644 index ffcd6a5..0000000 Binary files a/public_images/authors/redot.png and /dev/null differ diff --git a/public_images/download/android.svg b/public_images/download/android.svg deleted file mode 100644 index 774f0b6..0000000 --- a/public_images/download/android.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public_images/download/apple.svg b/public_images/download/apple.svg deleted file mode 100644 index 38a03c6..0000000 --- a/public_images/download/apple.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public_images/download/background-hero.webp b/public_images/download/background-hero.webp deleted file mode 100644 index 62c64e2..0000000 Binary files a/public_images/download/background-hero.webp and /dev/null differ diff --git a/public_images/download/linux.svg b/public_images/download/linux.svg deleted file mode 100644 index 0309039..0000000 --- a/public_images/download/linux.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public_images/download/requirements.webp b/public_images/download/requirements.webp deleted file mode 100644 index 848d4a3..0000000 Binary files a/public_images/download/requirements.webp and /dev/null differ diff --git a/public_images/download/web-editor.svg b/public_images/download/web-editor.svg deleted file mode 100644 index 6dd476c..0000000 --- a/public_images/download/web-editor.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public_images/download/windows.svg b/public_images/download/windows.svg deleted file mode 100644 index 6bb70a3..0000000 --- a/public_images/download/windows.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public_images/game_preview/game_preview_01.avif b/public_images/game_preview/game_preview_01.avif deleted file mode 100644 index 8d896d8..0000000 Binary files a/public_images/game_preview/game_preview_01.avif and /dev/null differ diff --git a/public_images/game_preview/game_preview_02.avif b/public_images/game_preview/game_preview_02.avif deleted file mode 100644 index d36a089..0000000 Binary files a/public_images/game_preview/game_preview_02.avif and /dev/null differ diff --git a/public_images/game_preview/game_preview_03.avif b/public_images/game_preview/game_preview_03.avif deleted file mode 100644 index ac5fcd4..0000000 Binary files a/public_images/game_preview/game_preview_03.avif and /dev/null differ diff --git a/public_images/game_preview/game_preview_05.png b/public_images/game_preview/game_preview_05.png deleted file mode 100644 index 96322a2..0000000 Binary files a/public_images/game_preview/game_preview_05.png and /dev/null differ diff --git a/public_images/game_preview/game_preview_06.png b/public_images/game_preview/game_preview_06.png deleted file mode 100644 index 06b4d56..0000000 Binary files a/public_images/game_preview/game_preview_06.png and /dev/null differ diff --git a/public_images/game_preview/game_preview_07.png b/public_images/game_preview/game_preview_07.png deleted file mode 100644 index 182b996..0000000 Binary files a/public_images/game_preview/game_preview_07.png and /dev/null differ diff --git a/public_images/mascott/Rune_Expression_2.webp b/public_images/mascott/Rune_Expression_2.webp deleted file mode 100644 index eba6a60..0000000 Binary files a/public_images/mascott/Rune_Expression_2.webp and /dev/null differ diff --git a/public_images/news/and-then-there-were-many.png b/public_images/news/and-then-there-were-many.png deleted file mode 100644 index 63f5df9..0000000 Binary files a/public_images/news/and-then-there-were-many.png and /dev/null differ diff --git a/public_images/news/mascot-contest.png b/public_images/news/mascot-contest.png deleted file mode 100644 index 47cb24e..0000000 Binary files a/public_images/news/mascot-contest.png and /dev/null differ diff --git a/public_images/news/redot-engine-grid.png b/public_images/news/redot-engine-grid.png deleted file mode 100644 index 913ba5f..0000000 Binary files a/public_images/news/redot-engine-grid.png and /dev/null differ diff --git a/public_images/news/redot-gamejam.png b/public_images/news/redot-gamejam.png deleted file mode 100644 index cd494a5..0000000 Binary files a/public_images/news/redot-gamejam.png and /dev/null differ diff --git a/public_images/news/redot-news.png b/public_images/news/redot-news.png deleted file mode 100644 index cfd5dfb..0000000 Binary files a/public_images/news/redot-news.png and /dev/null differ diff --git a/public_images/news/redot-roadmap-cover.png b/public_images/news/redot-roadmap-cover.png deleted file mode 100644 index e3032c5..0000000 Binary files a/public_images/news/redot-roadmap-cover.png and /dev/null differ diff --git a/public_images/news/redot-roadmap.png b/public_images/news/redot-roadmap.png deleted file mode 100644 index 14f01fa..0000000 Binary files a/public_images/news/redot-roadmap.png and /dev/null differ diff --git a/public_images/news/release-4-3-rc1.png b/public_images/news/release-4-3-rc1.png deleted file mode 100644 index 0baf991..0000000 Binary files a/public_images/news/release-4-3-rc1.png and /dev/null differ diff --git a/public_images/news/release-4-3-rc2.png b/public_images/news/release-4-3-rc2.png deleted file mode 100644 index f04f6b6..0000000 Binary files a/public_images/news/release-4-3-rc2.png and /dev/null differ diff --git a/public_images/news/release-4-3-rc3.png b/public_images/news/release-4-3-rc3.png deleted file mode 100644 index bd6623f..0000000 Binary files a/public_images/news/release-4-3-rc3.png and /dev/null differ diff --git a/public_images/news/release-4-3-rc4.png b/public_images/news/release-4-3-rc4.png deleted file mode 100644 index 674a802..0000000 Binary files a/public_images/news/release-4-3-rc4.png and /dev/null differ diff --git a/public_images/news/release-4-4-alpha-1.png b/public_images/news/release-4-4-alpha-1.png deleted file mode 100644 index 4b6499a..0000000 Binary files a/public_images/news/release-4-4-alpha-1.png and /dev/null differ diff --git a/public_images/news/release-4.3-beta-1.png b/public_images/news/release-4.3-beta-1.png deleted file mode 100644 index 734d1e7..0000000 Binary files a/public_images/news/release-4.3-beta-1.png and /dev/null differ diff --git a/public_images/news/release-4.3-beta-2.png b/public_images/news/release-4.3-beta-2.png deleted file mode 100644 index 53d490e..0000000 Binary files a/public_images/news/release-4.3-beta-2.png and /dev/null differ diff --git a/public_images/news/release-4.3-beta-3.png b/public_images/news/release-4.3-beta-3.png deleted file mode 100644 index bde6754..0000000 Binary files a/public_images/news/release-4.3-beta-3.png and /dev/null differ diff --git a/public_images/news/the-journey.png b/public_images/news/the-journey.png deleted file mode 100644 index 554c535..0000000 Binary files a/public_images/news/the-journey.png and /dev/null differ diff --git a/public_images/news/the-web-side-of-things.png b/public_images/news/the-web-side-of-things.png deleted file mode 100644 index 47eedc3..0000000 Binary files a/public_images/news/the-web-side-of-things.png and /dev/null differ diff --git a/public_images/news/welcome-to-our-site.png b/public_images/news/welcome-to-our-site.png deleted file mode 100644 index f43414b..0000000 Binary files a/public_images/news/welcome-to-our-site.png and /dev/null differ diff --git a/public_images/news/x-account-hacked.png b/public_images/news/x-account-hacked.png deleted file mode 100644 index 93409b5..0000000 Binary files a/public_images/news/x-account-hacked.png and /dev/null differ diff --git a/public_images/pages/and-then-there-were-many.png b/public_images/pages/and-then-there-were-many.png deleted file mode 100644 index 63f5df9..0000000 Binary files a/public_images/pages/and-then-there-were-many.png and /dev/null differ diff --git a/public_images/pages/redot-roadmap.png b/public_images/pages/redot-roadmap.png deleted file mode 100644 index 14f01fa..0000000 Binary files a/public_images/pages/redot-roadmap.png and /dev/null differ diff --git a/public_images/seo/banner.png b/public_images/seo/banner.png deleted file mode 100644 index 21eecb2..0000000 Binary files a/public_images/seo/banner.png and /dev/null differ