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
+
+
+
+
+
+
+
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