mirror of
https://github.com/C4illin/ConvertX.git
synced 2025-11-01 04:23:32 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b28977ffe2 | ||
|
|
a47bb682a5 | ||
|
|
a17eca0a09 | ||
|
|
ea9250543e | ||
|
|
317c932c2a | ||
|
|
5b1703db68 | ||
|
|
60ba7c93fb | ||
|
|
22227130dd | ||
|
|
5daf66f5d0 | ||
|
|
aee1962607 | ||
|
|
0d42762b36 | ||
|
|
b97b12b449 | ||
|
|
bdf651df82 | ||
|
|
267ef14789 | ||
|
|
905adc5e1c | ||
|
|
52ed7274e9 | ||
|
|
a29238c265 | ||
|
|
48c6fb79fc | ||
|
|
8358396656 | ||
|
|
b30e5800c3 | ||
|
|
21a1b50ed8 | ||
|
|
e6a94fb21d | ||
|
|
bef1710e33 | ||
|
|
16b322d4e6 | ||
|
|
9bf64e42d5 | ||
|
|
5988fe8212 | ||
|
|
5df9c0b751 | ||
|
|
136a8b2d74 | ||
|
|
ccfb574d5d | ||
|
|
ad6eedea69 |
7
.deepsource.toml
Normal file
7
.deepsource.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
version = 1
|
||||
|
||||
[[analyzers]]
|
||||
name = "javascript"
|
||||
|
||||
[analyzers.meta]
|
||||
environment = ["nodejs"]
|
||||
19
CHANGELOG.md
19
CHANGELOG.md
@@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## [0.5.0](https://github.com/C4illin/ConvertX/compare/v0.4.1...v0.5.0) (2024-09-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add option to customize how often files are automatically deleted ([317c932](https://github.com/C4illin/ConvertX/commit/317c932c2a26280bf37ed3d3bf9b879413590f5a))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* improve file name replacement logic ([60ba7c9](https://github.com/C4illin/ConvertX/commit/60ba7c93fbdc961f3569882fade7cc13dee7a7a5))
|
||||
|
||||
## [0.4.1](https://github.com/C4illin/ConvertX/compare/v0.4.0...v0.4.1) (2024-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow non lowercase true and false values, fixes [#122](https://github.com/C4illin/ConvertX/issues/122) ([bef1710](https://github.com/C4illin/ConvertX/commit/bef1710e3376baa7e25c107ded20a40d18b8c6b0))
|
||||
|
||||
## [0.4.0](https://github.com/C4illin/ConvertX/compare/v0.3.3...v0.4.0) (2024-08-26)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM oven/bun:1.1.26-alpine AS base
|
||||
FROM oven/bun:1.1.29-alpine AS base
|
||||
LABEL org.opencontainers.image.source="https://github.com/C4illin/ConvertX"
|
||||
WORKDIR /app
|
||||
|
||||
|
||||
11
README.md
11
README.md
@@ -47,6 +47,7 @@ services:
|
||||
- JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() by default
|
||||
- HTTP_ALLOWED=false # setting this to true is unsafe, only set this to true locally
|
||||
- ALLOW_UNAUTHENTICATED=false # allows anyone to use the service without logging in, only set this to true locally
|
||||
- AUTO_DELETE_EVERY_N_HOURS=24 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
|
||||
volumes:
|
||||
- convertx:/app/data
|
||||
```
|
||||
@@ -54,7 +55,7 @@ services:
|
||||
or
|
||||
|
||||
```bash
|
||||
docker run ghcr.io/c4illin/convertx -p 3000:3000 -v ./data:/app/data
|
||||
docker run -p 3000:3000 -v ./data:/app/data ghcr.io/c4illin/convertx
|
||||
```
|
||||
|
||||
Then visit `http://localhost:3000` in your browser and create your account. Don't leave it unconfigured and open, as anyone can register the first account.
|
||||
@@ -65,6 +66,10 @@ If you get unable to open database file run `chown -R $USER:$USER path` on the p
|
||||
|
||||
Tutorial in french: https://belginux.com/installer-convertx-avec-docker/
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||
## Development
|
||||
|
||||
0. Install [Bun](https://bun.sh/) and Git
|
||||
@@ -76,12 +81,12 @@ Pull requests are welcome! See below and open issues for the list of todos.
|
||||
|
||||
## Todo
|
||||
- [x] Add messages for errors in converters
|
||||
- [x] Add searchable list of formats
|
||||
- [ ] Add options for converters
|
||||
- [ ] Add more converters
|
||||
- [ ] Divide index.tsx into smaller components
|
||||
- [ ] Add tests
|
||||
- [ ] Add searchable list of formats
|
||||
- [ ] Make the upload button nicer and more easy to drop files on. Support copy paste as well if possible.
|
||||
- [ ] Make errors logs visible from the web ui
|
||||
- [ ] Add more converters:
|
||||
- [ ] [deark](https://github.com/jsummers/deark)
|
||||
- [ ] LibreOffice
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"attributePosition": "auto"
|
||||
},
|
||||
"files": {
|
||||
"ignore": ["**/node_modules/**"]
|
||||
"ignore": ["**/node_modules/**", "**/pico.lime.min.css"]
|
||||
},
|
||||
"organizeImports": { "enabled": true },
|
||||
"linter": {
|
||||
|
||||
BIN
images/preview.png
Normal file
BIN
images/preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
32
package.json
32
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "convertx-frontend",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"scripts": {
|
||||
"dev": "bun run --watch src/index.tsx",
|
||||
"hot": "bun run --hot src/index.tsx",
|
||||
@@ -14,9 +14,9 @@
|
||||
"dependencies": {
|
||||
"@elysiajs/cookie": "^0.8.0",
|
||||
"@elysiajs/html": "1.0.2",
|
||||
"@elysiajs/jwt": "^1.1.0",
|
||||
"@elysiajs/jwt": "^1.1.1",
|
||||
"@elysiajs/static": "1.0.3",
|
||||
"elysia": "^1.1.7"
|
||||
"elysia": "^1.1.12"
|
||||
},
|
||||
"module": "src/index.tsx",
|
||||
"type": "module",
|
||||
@@ -24,32 +24,32 @@
|
||||
"start": "bun run src/index.tsx"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.8.3",
|
||||
"@biomejs/biome": "1.9.2",
|
||||
"@eslint/compat": "^1.1.1",
|
||||
"@eslint/js": "^9.9.0",
|
||||
"@eslint/js": "^9.9.1",
|
||||
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
|
||||
"@kitajs/ts-html-plugin": "^4.0.2",
|
||||
"@picocss/pico": "^2.0.6",
|
||||
"@total-typescript/ts-reset": "^0.6.0",
|
||||
"@types/bun": "^1.1.6",
|
||||
"@types/eslint": "^9.6.0",
|
||||
"@types/node": "^22.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.2.0",
|
||||
"@typescript-eslint/parser": "^8.2.0",
|
||||
"@total-typescript/ts-reset": "^0.6.1",
|
||||
"@types/bun": "^1.1.8",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/node": "^22.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.4.0",
|
||||
"@typescript-eslint/parser": "^8.4.0",
|
||||
"cpy-cli": "^5.0.0",
|
||||
"eslint": "^9.9.0",
|
||||
"eslint": "^9.9.1",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-deprecation": "^3.0.0",
|
||||
"eslint-plugin-eslint-comments": "^3.2.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-isaacscript": "^3.12.2",
|
||||
"eslint-plugin-import": "^2.30.0",
|
||||
"eslint-plugin-isaacscript": "^4.0.0",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
||||
"knip": "^5.27.3",
|
||||
"knip": "^5.29.2",
|
||||
"npm-run-all2": "^6.2.2",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "^5.5.4",
|
||||
"typescript-eslint": "^8.2.0"
|
||||
"typescript-eslint": "^8.4.0"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"@biomejs/biome"
|
||||
|
||||
@@ -9,7 +9,6 @@ export const properties = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
export function convert(
|
||||
filePath: string,
|
||||
fileType: string,
|
||||
@@ -19,23 +18,20 @@ export function convert(
|
||||
options?: any,
|
||||
): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(
|
||||
`resvg "${filePath}" "${targetPath}"`,
|
||||
(error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`error: ${error}`);
|
||||
}
|
||||
exec(`resvg "${filePath}" "${targetPath}"`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`error: ${error}`);
|
||||
}
|
||||
|
||||
if (stdout) {
|
||||
console.log(`stdout: ${stdout}`);
|
||||
}
|
||||
if (stdout) {
|
||||
console.log(`stdout: ${stdout}`);
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(`stderr: ${stderr}`);
|
||||
}
|
||||
if (stderr) {
|
||||
console.error(`stderr: ${stderr}`);
|
||||
}
|
||||
|
||||
resolve("success");
|
||||
},
|
||||
);
|
||||
resolve("success");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,11 +27,15 @@ const uploadsDir = "./data/uploads/";
|
||||
const outputDir = "./data/output/";
|
||||
|
||||
const ACCOUNT_REGISTRATION =
|
||||
process.env.ACCOUNT_REGISTRATION === "true" || false;
|
||||
process.env.ACCOUNT_REGISTRATION?.toLowerCase() === "true" || false;
|
||||
|
||||
const HTTP_ALLOWED = process.env.HTTP_ALLOWED === "true" || false;
|
||||
const HTTP_ALLOWED =
|
||||
process.env.HTTP_ALLOWED?.toLowerCase() === "true" || false;
|
||||
const ALLOW_UNAUTHENTICATED =
|
||||
process.env.ALLOW_UNAUTHENTICATED === "true" || false;
|
||||
process.env.ALLOW_UNAUTHENTICATED?.toLowerCase() === "true" || false;
|
||||
const AUTO_DELETE_EVERY_N_HOURS = process.env.AUTO_DELETE_EVERY_N_HOURS
|
||||
? Number(process.env.AUTO_DELETE_EVERY_N_HOURS)
|
||||
: 24;
|
||||
|
||||
// fileNames: fileNames,
|
||||
// filesToConvert: fileNames.length,
|
||||
@@ -542,9 +546,11 @@ const app = new Elysia({
|
||||
style={{
|
||||
borderColor: "gray",
|
||||
padding: "2px",
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
<header
|
||||
style={{ fontSize: "20px", fontWeight: "bold" }}>
|
||||
style={{ fontSize: "20px", fontWeight: "bold" }}
|
||||
safe>
|
||||
{converter}
|
||||
</header>
|
||||
|
||||
@@ -566,7 +572,9 @@ const app = new Elysia({
|
||||
data-target={target}
|
||||
data-converter={converter}
|
||||
style={{ fontSize: "15px", padding: "5px" }}
|
||||
type="button">
|
||||
type="button"
|
||||
safe
|
||||
>
|
||||
{target}
|
||||
</button>
|
||||
))}
|
||||
@@ -637,8 +645,9 @@ const app = new Elysia({
|
||||
style={{
|
||||
borderColor: "gray",
|
||||
padding: "2px",
|
||||
}}>
|
||||
<header style={{ fontSize: "20px", fontWeight: "bold" }}>
|
||||
}}
|
||||
>
|
||||
<header style={{ fontSize: "20px", fontWeight: "bold" }} safe>
|
||||
{converter}
|
||||
</header>
|
||||
|
||||
@@ -660,7 +669,9 @@ const app = new Elysia({
|
||||
data-target={target}
|
||||
data-converter={converter}
|
||||
style={{ fontSize: "15px", padding: "5px" }}
|
||||
type="button">
|
||||
type="button"
|
||||
safe
|
||||
>
|
||||
{target}
|
||||
</button>
|
||||
))}
|
||||
@@ -827,7 +838,10 @@ const app = new Elysia({
|
||||
const fileTypeOrig = fileName.split(".").pop() ?? "";
|
||||
const fileType = normalizeFiletype(fileTypeOrig);
|
||||
const newFileExt = normalizeOutputFiletype(convertTo);
|
||||
const newFileName = fileName.replace(fileTypeOrig, newFileExt);
|
||||
const newFileName = fileName.replace(
|
||||
new RegExp(`${fileTypeOrig}(?!.*${fileTypeOrig})`),
|
||||
newFileExt,
|
||||
);
|
||||
const targetPath = `${userOutputDir}${newFileName}`;
|
||||
|
||||
const result = await mainConverter(
|
||||
@@ -1252,12 +1266,14 @@ console.log(
|
||||
);
|
||||
|
||||
const clearJobs = () => {
|
||||
// clear all jobs older than 24 hours
|
||||
// get all files older than 24 hours
|
||||
const jobs = db
|
||||
.query("SELECT * FROM jobs WHERE date_created < ?")
|
||||
.as(Jobs)
|
||||
.all(new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString());
|
||||
.all(
|
||||
new Date(
|
||||
Date.now() - AUTO_DELETE_EVERY_N_HOURS * 60 * 60 * 1000,
|
||||
).toISOString(),
|
||||
);
|
||||
|
||||
for (const job of jobs) {
|
||||
// delete the directories
|
||||
@@ -1268,7 +1284,9 @@ const clearJobs = () => {
|
||||
db.query("DELETE FROM jobs WHERE id = ?").run(job.id);
|
||||
}
|
||||
|
||||
// run every 24 hours
|
||||
setTimeout(clearJobs, 24 * 60 * 60 * 1000);
|
||||
setTimeout(clearJobs, AUTO_DELETE_EVERY_N_HOURS * 60 * 60 * 1000);
|
||||
};
|
||||
clearJobs();
|
||||
|
||||
if (AUTO_DELETE_EVERY_N_HOURS > 0) {
|
||||
clearJobs();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ div.icon {
|
||||
}
|
||||
|
||||
button[type="submit"] {
|
||||
width: 50%
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div.center {
|
||||
|
||||
Reference in New Issue
Block a user