diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
index 880958a..ece66dd 100644
--- a/.github/workflows/docker-publish.yml
+++ b/.github/workflows/docker-publish.yml
@@ -1,164 +1,164 @@
-name: Docker
-
-# thanks to https://github.com/sredevopsorg/multi-arch-docker-github-workflow
-
-on:
- push:
- branches: ["main"]
- tags: ["v*.*.*"]
- pull_request:
- branches: ["main"]
- workflow_dispatch:
-env:
- GHCR_IMAGE: ghcr.io/c4illin/convertx
- IMAGE_NAME: ${{ github.repository }}
- DOCKERHUB_USERNAME: c4illin
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- # The build job builds the Docker image for each platform specified in the matrix.
- build:
- strategy:
- fail-fast: false
- matrix:
- platform:
- - linux/amd64
- - linux/arm64
-
- permissions:
- contents: write
- packages: write
- attestations: write
- checks: write
- actions: read
-
- runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-24.04' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' }}
-
- name: Build Docker image for ${{ matrix.platform }}
-
- steps:
- - name: Prepare environment for current platform
- # This step sets up the environment for the current platform being built.
- # It replaces the '/' character in the platform name with '-' and sets it as an environment variable.
- # This is useful for naming artifacts and other resources that cannot contain '/'.
- # The environment variable PLATFORMS_PAIR will be used later in the workflow.
- id: prepare
- run: |
- platform=${{ matrix.platform }}
- echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
-
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Docker meta default
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: ${{ env.GHCR_IMAGE }}
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3.10.0
- with:
- platforms: ${{ matrix.platform }}
-
- - name: Login to GitHub Container Registry
- # here we only login to ghcr.io since the this only pushes internal images
- uses: docker/login-action@v3.4.0
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build and push by digest
- id: build
- uses: docker/build-push-action@v6.18.0
- env:
- DOCKER_BUILDKIT: 1
- with:
- context: .
- platforms: ${{ matrix.platform }}
- labels: ${{ steps.meta.outputs.labels }}
- annotations: ${{ steps.meta.outputs.annotations }}
- outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true
- cache-from: type=gha,scope=${{ matrix.platform }}
- cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
-
- - name: Export digest
- run: |
- mkdir -p /tmp/digests
- digest="${{ steps.build.outputs.digest }}"
- touch "/tmp/digests/${digest#sha256:}"
-
- - name: Upload digest
- uses: actions/upload-artifact@v4
- with:
- name: digests-${{ env.PLATFORM_PAIR }}
- path: /tmp/digests/*
- if-no-files-found: error
- retention-days: 1
-
- merge:
- name: Merge Docker manifests
- runs-on: ubuntu-latest
-
- permissions:
- attestations: write
- contents: read
- packages: write
-
- needs:
- - build
- steps:
- - name: Download digests
- uses: actions/download-artifact@v4
- with:
- path: /tmp/digests
- pattern: digests-*
- merge-multiple: true
-
- - name: Extract Docker metadata
- id: meta
- uses: docker/metadata-action@v5
- with:
- images: |
- ${{ env.GHCR_IMAGE }}
- ${{ env.IMAGE_NAME }}
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ env.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
-
- - name: Get execution timestamp with RFC3339 format
- id: timestamp
- run: |
- echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
-
- - name: Create manifest list and push
- working-directory: /tmp/digests
- run: |
- docker buildx imagetools create \
- $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
- --annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
- --annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
- --annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
- --annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
- $(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
-
- - name: Inspect image
- run: |
- docker buildx imagetools inspect '${{ env.GHCR_IMAGE }}:${{ steps.meta.outputs.version }}'
+name: Docker
+
+# thanks to https://github.com/sredevopsorg/multi-arch-docker-github-workflow
+
+on:
+ push:
+ branches: ["main"]
+ tags: ["v*.*.*"]
+ pull_request:
+ branches: ["main"]
+ workflow_dispatch:
+env:
+ GHCR_IMAGE: ghcr.io/c4illin/convertx
+ IMAGE_NAME: ${{ github.repository }}
+ DOCKERHUB_USERNAME: c4illin
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ # The build job builds the Docker image for each platform specified in the matrix.
+ build:
+ strategy:
+ fail-fast: false
+ matrix:
+ platform:
+ - linux/amd64
+ - linux/arm64
+
+ permissions:
+ contents: write
+ packages: write
+ attestations: write
+ checks: write
+ actions: read
+
+ runs-on: ${{ matrix.platform == 'linux/amd64' && 'ubuntu-24.04' || matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' }}
+
+ name: Build Docker image for ${{ matrix.platform }}
+
+ steps:
+ - name: Prepare environment for current platform
+ # This step sets up the environment for the current platform being built.
+ # It replaces the '/' character in the platform name with '-' and sets it as an environment variable.
+ # This is useful for naming artifacts and other resources that cannot contain '/'.
+ # The environment variable PLATFORMS_PAIR will be used later in the workflow.
+ id: prepare
+ run: |
+ platform=${{ matrix.platform }}
+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
+
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Docker meta default
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.GHCR_IMAGE }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3.10.0
+ with:
+ platforms: ${{ matrix.platform }}
+
+ - name: Login to GitHub Container Registry
+ # here we only login to ghcr.io since the this only pushes internal images
+ uses: docker/login-action@v3.4.0
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Build and push by digest
+ id: build
+ uses: docker/build-push-action@v6.18.0
+ env:
+ DOCKER_BUILDKIT: 1
+ with:
+ context: .
+ platforms: ${{ matrix.platform }}
+ labels: ${{ steps.meta.outputs.labels }}
+ annotations: ${{ steps.meta.outputs.annotations }}
+ outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true,oci-mediatypes=true
+ cache-from: type=gha,scope=${{ matrix.platform }}
+ cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
+
+ - name: Export digest
+ run: |
+ mkdir -p /tmp/digests
+ digest="${{ steps.build.outputs.digest }}"
+ touch "/tmp/digests/${digest#sha256:}"
+
+ - name: Upload digest
+ uses: actions/upload-artifact@v4
+ with:
+ name: digests-${{ env.PLATFORM_PAIR }}
+ path: /tmp/digests/*
+ if-no-files-found: error
+ retention-days: 1
+
+ merge:
+ name: Merge Docker manifests
+ runs-on: ubuntu-latest
+
+ permissions:
+ attestations: write
+ contents: read
+ packages: write
+
+ needs:
+ - build
+ steps:
+ - name: Download digests
+ uses: actions/download-artifact@v4
+ with:
+ path: /tmp/digests
+ pattern: digests-*
+ merge-multiple: true
+
+ - name: Extract Docker metadata
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: |
+ ${{ env.GHCR_IMAGE }}
+ ${{ env.IMAGE_NAME }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to GitHub Container Registry
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to Docker Hub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ env.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Get execution timestamp with RFC3339 format
+ id: timestamp
+ run: |
+ echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
+
+ - name: Create manifest list and push
+ working-directory: /tmp/digests
+ run: |
+ docker buildx imagetools create \
+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+ --annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
+ --annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
+ --annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
+ --annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
+ $(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
+
+ - name: Inspect image
+ run: |
+ docker buildx imagetools inspect '${{ env.GHCR_IMAGE }}:${{ steps.meta.outputs.version }}'
diff --git a/.github/workflows/dockerhub-description.yml b/.github/workflows/dockerhub-description.yml
index cf84217..cb860a3 100644
--- a/.github/workflows/dockerhub-description.yml
+++ b/.github/workflows/dockerhub-description.yml
@@ -15,13 +15,13 @@ jobs:
dockerHubDescription:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
- - name: Docker Hub Description
- uses: peter-evans/dockerhub-description@v4
- with:
- username: ${{ env.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- repository: ${{ env.IMAGE_NAME }}
- short-description: ${{ github.event.repository.description }}
- enable-url-completion: true
+ - name: Docker Hub Description
+ uses: peter-evans/dockerhub-description@v4
+ with:
+ username: ${{ env.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ repository: ${{ env.IMAGE_NAME }}
+ short-description: ${{ github.event.repository.description }}
+ enable-url-completion: true
diff --git a/.github/workflows/remove-docker-tag.yml b/.github/workflows/remove-docker-tag.yml
index cc81527..ea8f3a9 100644
--- a/.github/workflows/remove-docker-tag.yml
+++ b/.github/workflows/remove-docker-tag.yml
@@ -14,8 +14,8 @@ jobs:
packages: write
steps:
- - name: Remove Docker Tag
- uses: ArchieAtkinson/remove-dockertag-action@v0.0
- with:
- tag_name: master
- github_token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
+ - name: Remove Docker Tag
+ uses: ArchieAtkinson/remove-dockertag-action@v0.0
+ with:
+ tag_name: master
+ github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d067910..fae8e3d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,4 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
-}
\ No newline at end of file
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3256468..f3f57f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,243 +2,209 @@
## [0.13.0](https://github.com/C4illin/ConvertX/compare/v0.12.1...v0.13.0) (2025-05-14)
-
### Features
-* add HIDE_HISTORY option to control visibility of history page ([9d1c931](https://github.com/C4illin/ConvertX/commit/9d1c93155cc33ed6c83f9e5122afff8f28d0e4bf))
-* add potrace converter ([bdbd4a1](https://github.com/C4illin/ConvertX/commit/bdbd4a122c09559b089b985ea12c5f3e085107da))
-* Add support for .HIF files ([70705c1](https://github.com/C4illin/ConvertX/commit/70705c1850d470296df85958c02a01fb5bc3a25f))
-* add support for drag/drop of images ([ff2ef74](https://github.com/C4illin/ConvertX/commit/ff2ef7413542cf10ba7a6e246763bcecd6829ec1))
-
+- add HIDE_HISTORY option to control visibility of history page ([9d1c931](https://github.com/C4illin/ConvertX/commit/9d1c93155cc33ed6c83f9e5122afff8f28d0e4bf))
+- add potrace converter ([bdbd4a1](https://github.com/C4illin/ConvertX/commit/bdbd4a122c09559b089b985ea12c5f3e085107da))
+- Add support for .HIF files ([70705c1](https://github.com/C4illin/ConvertX/commit/70705c1850d470296df85958c02a01fb5bc3a25f))
+- add support for drag/drop of images ([ff2ef74](https://github.com/C4illin/ConvertX/commit/ff2ef7413542cf10ba7a6e246763bcecd6829ec1))
### Bug Fixes
-* add timezone support ([4b5c732](https://github.com/C4illin/ConvertX/commit/4b5c732380bc844dccf340ea1eb4f8bfe3bb44a5)), closes [#258](https://github.com/C4illin/ConvertX/issues/258)
+- add timezone support ([4b5c732](https://github.com/C4illin/ConvertX/commit/4b5c732380bc844dccf340ea1eb4f8bfe3bb44a5)), closes [#258](https://github.com/C4illin/ConvertX/issues/258)
## [0.12.1](https://github.com/C4illin/ConvertX/compare/v0.12.0...v0.12.1) (2025-03-20)
-
### Bug Fixes
-* rollback to bun 1.2.2 ([cdae798](https://github.com/C4illin/ConvertX/commit/cdae798fcf5879e4adea87386a38748b9a1e1ddc))
+- rollback to bun 1.2.2 ([cdae798](https://github.com/C4illin/ConvertX/commit/cdae798fcf5879e4adea87386a38748b9a1e1ddc))
## [0.12.0](https://github.com/C4illin/ConvertX/compare/v0.11.1...v0.12.0) (2025-03-06)
-
### Features
-* added progress bar for file upload ([db60f35](https://github.com/C4illin/ConvertX/commit/db60f355b2973f43f8e5990e6fe4e351b959b659))
-* made every upload file independent ([cc54bdc](https://github.com/C4illin/ConvertX/commit/cc54bdcbe764c41cc3273485d072fd3178ad2dca))
-* replace exec with execFile ([9263d17](https://github.com/C4illin/ConvertX/commit/9263d17609dc4b2b367eb7fee67b3182e283b3a3))
-
+- added progress bar for file upload ([db60f35](https://github.com/C4illin/ConvertX/commit/db60f355b2973f43f8e5990e6fe4e351b959b659))
+- made every upload file independent ([cc54bdc](https://github.com/C4illin/ConvertX/commit/cc54bdcbe764c41cc3273485d072fd3178ad2dca))
+- replace exec with execFile ([9263d17](https://github.com/C4illin/ConvertX/commit/9263d17609dc4b2b367eb7fee67b3182e283b3a3))
### Bug Fixes
-* add libheif ([6b92540](https://github.com/C4illin/ConvertX/commit/6b9254047c0598963aee1d99e20ba1650a0368bf))
-* add libheif ([decfea5](https://github.com/C4illin/ConvertX/commit/decfea5dc9627b216bb276a9e1578c32cfa1deb6)), closes [#202](https://github.com/C4illin/ConvertX/issues/202)
-* added onerror log ([ae4bbc8](https://github.com/C4illin/ConvertX/commit/ae4bbc8baacbaf67763c62ea44140bb21cc17230))
-* refactored uploadFile to only accept a single file instead of multiple ([dc82a43](https://github.com/C4illin/ConvertX/commit/dc82a438d4104b79ff423d502a6779a43928968a))
-* update libheif to 1.19.5 ([fba5e21](https://github.com/C4illin/ConvertX/commit/fba5e212e8d0eaba8971e239e35aeb521f3cd813)), closes [#202](https://github.com/C4illin/ConvertX/issues/202)
+- add libheif ([6b92540](https://github.com/C4illin/ConvertX/commit/6b9254047c0598963aee1d99e20ba1650a0368bf))
+- add libheif ([decfea5](https://github.com/C4illin/ConvertX/commit/decfea5dc9627b216bb276a9e1578c32cfa1deb6)), closes [#202](https://github.com/C4illin/ConvertX/issues/202)
+- added onerror log ([ae4bbc8](https://github.com/C4illin/ConvertX/commit/ae4bbc8baacbaf67763c62ea44140bb21cc17230))
+- refactored uploadFile to only accept a single file instead of multiple ([dc82a43](https://github.com/C4illin/ConvertX/commit/dc82a438d4104b79ff423d502a6779a43928968a))
+- update libheif to 1.19.5 ([fba5e21](https://github.com/C4illin/ConvertX/commit/fba5e212e8d0eaba8971e239e35aeb521f3cd813)), closes [#202](https://github.com/C4illin/ConvertX/issues/202)
## [0.11.1](https://github.com/C4illin/ConvertX/compare/v0.11.0...v0.11.1) (2025-02-07)
-
### Bug Fixes
-* mobile view overflow ([bec58ac](https://github.com/C4illin/ConvertX/commit/bec58ac59f9600e35385b9e21d174f3ab1b42b1d))
+- mobile view overflow ([bec58ac](https://github.com/C4illin/ConvertX/commit/bec58ac59f9600e35385b9e21d174f3ab1b42b1d))
## [0.11.0](https://github.com/C4illin/ConvertX/compare/v0.10.1...v0.11.0) (2025-02-05)
-
### Features
-* add deps for vaapi ([2bbbd03](https://github.com/C4illin/ConvertX/commit/2bbbd03554d384a4488143f29e5fc863cfdf333b)), closes [#192](https://github.com/C4illin/ConvertX/issues/192)
-
+- add deps for vaapi ([2bbbd03](https://github.com/C4illin/ConvertX/commit/2bbbd03554d384a4488143f29e5fc863cfdf333b)), closes [#192](https://github.com/C4illin/ConvertX/issues/192)
### Bug Fixes
-* don't crash if file is not found ([16f27c1](https://github.com/C4illin/ConvertX/commit/16f27c13bbc1c0e5fa2316f3db11d0918524053b))
-* install numpy for inkscape ([0e61051](https://github.com/C4illin/ConvertX/commit/0e61051fc6be188164c3865b4fb579c140859fdc))
+- don't crash if file is not found ([16f27c1](https://github.com/C4illin/ConvertX/commit/16f27c13bbc1c0e5fa2316f3db11d0918524053b))
+- install numpy for inkscape ([0e61051](https://github.com/C4illin/ConvertX/commit/0e61051fc6be188164c3865b4fb579c140859fdc))
## [0.10.1](https://github.com/C4illin/ConvertX/compare/v0.10.0...v0.10.1) (2025-01-21)
-
### Bug Fixes
-* ffmpeg works without ffmpeg_args ([3b7ea88](https://github.com/C4illin/ConvertX/commit/3b7ea88b7382f7c21b120bdc9bda5bb10547f55d)), closes [#212](https://github.com/C4illin/ConvertX/issues/212)
+- ffmpeg works without ffmpeg_args ([3b7ea88](https://github.com/C4illin/ConvertX/commit/3b7ea88b7382f7c21b120bdc9bda5bb10547f55d)), closes [#212](https://github.com/C4illin/ConvertX/issues/212)
## [0.10.0](https://github.com/C4illin/ConvertX/compare/v0.9.0...v0.10.0) (2025-01-18)
-
### Features
-* add calibre ([03d3edf](https://github.com/C4illin/ConvertX/commit/03d3edfff65c252dd4b8922fc98257c089c1ff74)), closes [#191](https://github.com/C4illin/ConvertX/issues/191)
-
+- add calibre ([03d3edf](https://github.com/C4illin/ConvertX/commit/03d3edfff65c252dd4b8922fc98257c089c1ff74)), closes [#191](https://github.com/C4illin/ConvertX/issues/191)
### Bug Fixes
-* add FFMPEG_ARGS env variable ([f537c81](https://github.com/C4illin/ConvertX/commit/f537c81db7815df8017f834e3162291197e1c40f)), closes [#190](https://github.com/C4illin/ConvertX/issues/190)
-* add qt6-qtbase-private-dev from community repo ([95dbc9f](https://github.com/C4illin/ConvertX/commit/95dbc9f678bec7e6e2c03587e1473fb8ff708ea3))
-* skip account setup when ALLOW_UNAUTHENTICATED is true ([538c5b6](https://github.com/C4illin/ConvertX/commit/538c5b60c9e27a8184740305475245da79bae143))
+- add FFMPEG_ARGS env variable ([f537c81](https://github.com/C4illin/ConvertX/commit/f537c81db7815df8017f834e3162291197e1c40f)), closes [#190](https://github.com/C4illin/ConvertX/issues/190)
+- add qt6-qtbase-private-dev from community repo ([95dbc9f](https://github.com/C4illin/ConvertX/commit/95dbc9f678bec7e6e2c03587e1473fb8ff708ea3))
+- skip account setup when ALLOW_UNAUTHENTICATED is true ([538c5b6](https://github.com/C4illin/ConvertX/commit/538c5b60c9e27a8184740305475245da79bae143))
## [0.9.0](https://github.com/C4illin/ConvertX/compare/v0.8.1...v0.9.0) (2024-11-21)
-
### Features
-* add inkscape for vector images ([f3740e9](https://github.com/C4illin/ConvertX/commit/f3740e9ded100b8500f3613517960248bbd3c210))
-* Allow to chose webroot ([36cb6cc](https://github.com/C4illin/ConvertX/commit/36cb6cc589d80d0a87fa8dbe605db71a9a2570f9)), closes [#180](https://github.com/C4illin/ConvertX/issues/180)
-* disable convert when uploading ([58e220e](https://github.com/C4illin/ConvertX/commit/58e220e82d7f9c163d6ea4dc31092c08a3e254f4)), closes [#177](https://github.com/C4illin/ConvertX/issues/177)
-
+- add inkscape for vector images ([f3740e9](https://github.com/C4illin/ConvertX/commit/f3740e9ded100b8500f3613517960248bbd3c210))
+- Allow to chose webroot ([36cb6cc](https://github.com/C4illin/ConvertX/commit/36cb6cc589d80d0a87fa8dbe605db71a9a2570f9)), closes [#180](https://github.com/C4illin/ConvertX/issues/180)
+- disable convert when uploading ([58e220e](https://github.com/C4illin/ConvertX/commit/58e220e82d7f9c163d6ea4dc31092c08a3e254f4)), closes [#177](https://github.com/C4illin/ConvertX/issues/177)
### Bug Fixes
-* treat unknown as m4a ([1a442d6](https://github.com/C4illin/ConvertX/commit/1a442d6e69606afef63b1e7df36aa83d111fa23d)), closes [#178](https://github.com/C4illin/ConvertX/issues/178)
-* wait for both upload and selection ([4c05fd7](https://github.com/C4illin/ConvertX/commit/4c05fd72bbbf91ee02327f6fcbf749b78272376b)), closes [#177](https://github.com/C4illin/ConvertX/issues/177)
+- treat unknown as m4a ([1a442d6](https://github.com/C4illin/ConvertX/commit/1a442d6e69606afef63b1e7df36aa83d111fa23d)), closes [#178](https://github.com/C4illin/ConvertX/issues/178)
+- wait for both upload and selection ([4c05fd7](https://github.com/C4illin/ConvertX/commit/4c05fd72bbbf91ee02327f6fcbf749b78272376b)), closes [#177](https://github.com/C4illin/ConvertX/issues/177)
## [0.8.1](https://github.com/C4illin/ConvertX/compare/v0.8.0...v0.8.1) (2024-10-05)
-
### Bug Fixes
-* disable convert button when input is empty ([78844d7](https://github.com/C4illin/ConvertX/commit/78844d7bd55990789ed07c81e49043e688cbe656)), closes [#151](https://github.com/C4illin/ConvertX/issues/151)
-* resize to fit for ico ([b4e53db](https://github.com/C4illin/ConvertX/commit/b4e53dbb8e70b3a95b44e5b756759d16117a87e1)), closes [#157](https://github.com/C4illin/ConvertX/issues/157)
-* treat jfif as jpeg ([339b79f](https://github.com/C4illin/ConvertX/commit/339b79f786131deb93f0d5683e03178fdcab1ef5)), closes [#163](https://github.com/C4illin/ConvertX/issues/163)
+- disable convert button when input is empty ([78844d7](https://github.com/C4illin/ConvertX/commit/78844d7bd55990789ed07c81e49043e688cbe656)), closes [#151](https://github.com/C4illin/ConvertX/issues/151)
+- resize to fit for ico ([b4e53db](https://github.com/C4illin/ConvertX/commit/b4e53dbb8e70b3a95b44e5b756759d16117a87e1)), closes [#157](https://github.com/C4illin/ConvertX/issues/157)
+- treat jfif as jpeg ([339b79f](https://github.com/C4illin/ConvertX/commit/339b79f786131deb93f0d5683e03178fdcab1ef5)), closes [#163](https://github.com/C4illin/ConvertX/issues/163)
## [0.8.0](https://github.com/C4illin/ConvertX/compare/v0.7.0...v0.8.0) (2024-09-30)
-
### Features
-* add light theme, fixes [#156](https://github.com/C4illin/ConvertX/issues/156) ([72636c5](https://github.com/C4illin/ConvertX/commit/72636c5059ebf09c8fece2e268293650b2f8ccf6))
-
+- add light theme, fixes [#156](https://github.com/C4illin/ConvertX/issues/156) ([72636c5](https://github.com/C4illin/ConvertX/commit/72636c5059ebf09c8fece2e268293650b2f8ccf6))
### Bug Fixes
-* add support for usd for assimp, [#144](https://github.com/C4illin/ConvertX/issues/144) ([2057167](https://github.com/C4illin/ConvertX/commit/20571675766209ad1251f07e687d29a6791afc8b))
-* cleanup formats and add opus, fixes [#159](https://github.com/C4illin/ConvertX/issues/159) ([ae1dfaf](https://github.com/C4illin/ConvertX/commit/ae1dfafc9d9116a57b08c2f7fc326990e00824b0))
-* support .awb and clean up, fixes [#153](https://github.com/C4illin/ConvertX/issues/153), [#92](https://github.com/C4illin/ConvertX/issues/92) ([1c9e67f](https://github.com/C4illin/ConvertX/commit/1c9e67fc3201e0e5dee91e8981adf34daaabf33a))
+- add support for usd for assimp, [#144](https://github.com/C4illin/ConvertX/issues/144) ([2057167](https://github.com/C4illin/ConvertX/commit/20571675766209ad1251f07e687d29a6791afc8b))
+- cleanup formats and add opus, fixes [#159](https://github.com/C4illin/ConvertX/issues/159) ([ae1dfaf](https://github.com/C4illin/ConvertX/commit/ae1dfafc9d9116a57b08c2f7fc326990e00824b0))
+- support .awb and clean up, fixes [#153](https://github.com/C4illin/ConvertX/issues/153), [#92](https://github.com/C4illin/ConvertX/issues/92) ([1c9e67f](https://github.com/C4illin/ConvertX/commit/1c9e67fc3201e0e5dee91e8981adf34daaabf33a))
## [0.7.0](https://github.com/C4illin/ConvertX/compare/v0.6.0...v0.7.0) (2024-09-26)
-
### Features
-* Add support for 3d assets through assimp converter ([63a4328](https://github.com/C4illin/ConvertX/commit/63a4328d4a1e01df3e0ec4a877bad8c8ffe71129))
-
+- Add support for 3d assets through assimp converter ([63a4328](https://github.com/C4illin/ConvertX/commit/63a4328d4a1e01df3e0ec4a877bad8c8ffe71129))
### Bug Fixes
-* wrong layout on search with few options ([8817389](https://github.com/C4illin/ConvertX/commit/88173891ba2d69da46eda46f3f598a9b54f26f96))
+- wrong layout on search with few options ([8817389](https://github.com/C4illin/ConvertX/commit/88173891ba2d69da46eda46f3f598a9b54f26f96))
## [0.6.0](https://github.com/C4illin/ConvertX/compare/v0.5.0...v0.6.0) (2024-09-25)
-
### Features
-* ui remake with tailwind ([22f823c](https://github.com/C4illin/ConvertX/commit/22f823c535b20382981f86a13616b830a1f3392f))
-
+- ui remake with tailwind ([22f823c](https://github.com/C4illin/ConvertX/commit/22f823c535b20382981f86a13616b830a1f3392f))
### Bug Fixes
-* rename css file to force update cache, fixes [#141](https://github.com/C4illin/ConvertX/issues/141) ([47139a5](https://github.com/C4illin/ConvertX/commit/47139a550bd3d847da288c61bf8f88953b79c673))
+- rename css file to force update cache, fixes [#141](https://github.com/C4illin/ConvertX/issues/141) ([47139a5](https://github.com/C4illin/ConvertX/commit/47139a550bd3d847da288c61bf8f88953b79c673))
## [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))
-
+- 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))
+- 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))
+- 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)
-
### Features
-* add option for unauthenticated file conversions [#114](https://github.com/C4illin/ConvertX/issues/114) ([f0d0e43](https://github.com/C4illin/ConvertX/commit/f0d0e4392983c3e4c530304ea88e023fda9bcac0))
-* add resvg converter ([d5eeef9](https://github.com/C4illin/ConvertX/commit/d5eeef9f6884b2bb878508bed97ea9ceaa662995))
-* add robots.txt ([6597c1d](https://github.com/C4illin/ConvertX/commit/6597c1d7caeb4dfb6bc47b442e4dfc9840ad12b7))
-* Add search bar for formats ([53fff59](https://github.com/C4illin/ConvertX/commit/53fff594fc4d69306abcb2a5cad890fcd0953a58))
-
+- add option for unauthenticated file conversions [#114](https://github.com/C4illin/ConvertX/issues/114) ([f0d0e43](https://github.com/C4illin/ConvertX/commit/f0d0e4392983c3e4c530304ea88e023fda9bcac0))
+- add resvg converter ([d5eeef9](https://github.com/C4illin/ConvertX/commit/d5eeef9f6884b2bb878508bed97ea9ceaa662995))
+- add robots.txt ([6597c1d](https://github.com/C4illin/ConvertX/commit/6597c1d7caeb4dfb6bc47b442e4dfc9840ad12b7))
+- Add search bar for formats ([53fff59](https://github.com/C4illin/ConvertX/commit/53fff594fc4d69306abcb2a5cad890fcd0953a58))
### Bug Fixes
-* keep unauthenticated user logged in if allowed [#114](https://github.com/C4illin/ConvertX/issues/114) ([bc4ad49](https://github.com/C4illin/ConvertX/commit/bc4ad492852fad8cb832a0c03485cccdd7f7b117))
-* pdf support in vips ([8ca4f15](https://github.com/C4illin/ConvertX/commit/8ca4f1587df7f358893941c656d78d75f04dac93))
-* Slow click on conversion popup does not work ([4d9c4d6](https://github.com/C4illin/ConvertX/commit/4d9c4d64aa0266f3928935ada68d91ac81f638aa))
+- keep unauthenticated user logged in if allowed [#114](https://github.com/C4illin/ConvertX/issues/114) ([bc4ad49](https://github.com/C4illin/ConvertX/commit/bc4ad492852fad8cb832a0c03485cccdd7f7b117))
+- pdf support in vips ([8ca4f15](https://github.com/C4illin/ConvertX/commit/8ca4f1587df7f358893941c656d78d75f04dac93))
+- Slow click on conversion popup does not work ([4d9c4d6](https://github.com/C4illin/ConvertX/commit/4d9c4d64aa0266f3928935ada68d91ac81f638aa))
## [0.3.3](https://github.com/C4illin/ConvertX/compare/v0.3.2...v0.3.3) (2024-07-30)
-
### Bug Fixes
-* downgrade @elysiajs/html dependency to version 1.0.2 ([c714ade](https://github.com/C4illin/ConvertX/commit/c714ade3e23865ba6cfaf76c9e7259df1cda222c))
+- downgrade @elysiajs/html dependency to version 1.0.2 ([c714ade](https://github.com/C4illin/ConvertX/commit/c714ade3e23865ba6cfaf76c9e7259df1cda222c))
## [0.3.2](https://github.com/C4illin/ConvertX/compare/v0.3.1...v0.3.2) (2024-07-09)
-
### Bug Fixes
-* increase max request body to support large uploads ([3ae2db5](https://github.com/C4illin/ConvertX/commit/3ae2db5d9b36fe3dcd4372ddcd32aa573ea59aa6)), closes [#64](https://github.com/C4illin/ConvertX/issues/64)
+- increase max request body to support large uploads ([3ae2db5](https://github.com/C4illin/ConvertX/commit/3ae2db5d9b36fe3dcd4372ddcd32aa573ea59aa6)), closes [#64](https://github.com/C4illin/ConvertX/issues/64)
## [0.3.1](https://github.com/C4illin/ConvertX/compare/v0.3.0...v0.3.1) (2024-06-27)
-
### Bug Fixes
-* release releases ([4d4c13a](https://github.com/C4illin/ConvertX/commit/4d4c13a8d85ec7c9209ad41cdbea7d4380b0edbf))
+- release releases ([4d4c13a](https://github.com/C4illin/ConvertX/commit/4d4c13a8d85ec7c9209ad41cdbea7d4380b0edbf))
## [0.3.0](https://github.com/C4illin/ConvertX/compare/v0.2.0...v0.3.0) (2024-06-27)
-
### Features
-* add version number to log ([4dcb796](https://github.com/C4illin/ConvertX/commit/4dcb796e1bd27badc078d0638076cd9f1e81c4a4)), closes [#44](https://github.com/C4illin/ConvertX/issues/44)
-* change to xelatex ([fae2ba9](https://github.com/C4illin/ConvertX/commit/fae2ba9c54461dccdccd1bfb5e76398540d11d0b))
-* print version of installed converters to log ([801cf28](https://github.com/C4illin/ConvertX/commit/801cf28d1e5edac9353b0b16be75a4fb48470b8a))
+- add version number to log ([4dcb796](https://github.com/C4illin/ConvertX/commit/4dcb796e1bd27badc078d0638076cd9f1e81c4a4)), closes [#44](https://github.com/C4illin/ConvertX/issues/44)
+- change to xelatex ([fae2ba9](https://github.com/C4illin/ConvertX/commit/fae2ba9c54461dccdccd1bfb5e76398540d11d0b))
+- print version of installed converters to log ([801cf28](https://github.com/C4illin/ConvertX/commit/801cf28d1e5edac9353b0b16be75a4fb48470b8a))
## [0.2.0](https://github.com/C4illin/ConvertX/compare/v0.1.2...v0.2.0) (2024-06-20)
-
### Features
-* add libjxl for jpegxl conversion ([ff680cb](https://github.com/C4illin/ConvertX/commit/ff680cb29534a25c3148a90fd064bb86c71fb482))
-* change from debian to alpine ([1316957](https://github.com/C4illin/ConvertX/commit/13169574f0134ae236f8d41287bb73930b575e82)), closes [#34](https://github.com/C4illin/ConvertX/issues/34)
+- add libjxl for jpegxl conversion ([ff680cb](https://github.com/C4illin/ConvertX/commit/ff680cb29534a25c3148a90fd064bb86c71fb482))
+- change from debian to alpine ([1316957](https://github.com/C4illin/ConvertX/commit/13169574f0134ae236f8d41287bb73930b575e82)), closes [#34](https://github.com/C4illin/ConvertX/issues/34)
## [0.1.2](https://github.com/C4illin/ConvertX/compare/v0.1.1...v0.1.2) (2024-06-10)
-
### Bug Fixes
-* fix incorrect redirect ([25df58b](https://github.com/C4illin/ConvertX/commit/25df58ba82321aaa6617811a6995cb96c2a00a40)), closes [#23](https://github.com/C4illin/ConvertX/issues/23)
+- fix incorrect redirect ([25df58b](https://github.com/C4illin/ConvertX/commit/25df58ba82321aaa6617811a6995cb96c2a00a40)), closes [#23](https://github.com/C4illin/ConvertX/issues/23)
## [0.1.1](https://github.com/C4illin/ConvertX/compare/v0.1.0...v0.1.1) (2024-05-30)
-
### Bug Fixes
-* :bug: make sure all redirects are 302 ([9970fd3](https://github.com/C4illin/ConvertX/commit/9970fd3f89190af96f8762edc3817d1e03082b3a)), closes [#12](https://github.com/C4illin/ConvertX/issues/12)
+- :bug: make sure all redirects are 302 ([9970fd3](https://github.com/C4illin/ConvertX/commit/9970fd3f89190af96f8762edc3817d1e03082b3a)), closes [#12](https://github.com/C4illin/ConvertX/issues/12)
## 0.1.0 (2024-05-30)
-
### Features
-* remove file from file list in index.html ([787ff97](https://github.com/C4illin/ConvertX/commit/787ff9741ecbbf4fb4c02b43bd22a214a173fd7b))
-
+- remove file from file list in index.html ([787ff97](https://github.com/C4illin/ConvertX/commit/787ff9741ecbbf4fb4c02b43bd22a214a173fd7b))
### Miscellaneous Chores
-* release 0.1.0 ([54d9aec](https://github.com/C4illin/ConvertX/commit/54d9aecbf949689b12aa7e5e8e9be7b9032f4431))
+- release 0.1.0 ([54d9aec](https://github.com/C4illin/ConvertX/commit/54d9aecbf949689b12aa7e5e8e9be7b9032f4431))
diff --git a/README.md b/README.md
index 8920cea..ffba8c2 100644
--- a/README.md
+++ b/README.md
@@ -1,158 +1,159 @@
-
-
-# ConvertX
-
-[](https://github.com/C4illin/ConvertX/actions/workflows/docker-publish.yml)
-[](https://github.com/C4illin/ConvertX/pkgs/container/ConvertX)
-[](https://hub.docker.com/r/c4illin/convertx)
-[](https://github.com/C4illin/ConvertX/pkgs/container/convertx)
-
-
-
-
-
-
-
-A self-hosted online file converter. Supports over a thousand different formats. Written with TypeScript, Bun and Elysia.
-
-## Features
-
-- Convert files to different formats
-- Process multiple files at once
-- Password protection
-- Multiple accounts
-
-## Converters supported
-
-| Converter | Use case | Converts from | Converts to |
-|------------------------------------------------------------------------------|---------------|---------------|-------------|
-| [libjxl](https://github.com/libjxl/libjxl) | JPEG XL | 11 | 11 |
-| [resvg](https://github.com/RazrFalcon/resvg) | SVG | 1 | 1 |
-| [Vips](https://github.com/libvips/libvips) | Images | 45 | 23 |
-| [libheif](https://github.com/strukturag/libheif) | HEIF | 2 | 4 |
-| [XeLaTeX](https://tug.org/xetex/) | LaTeX | 1 | 1 |
-| [Calibre](https://calibre-ebook.com/) | E-books | 26 | 19 |
-| [Pandoc](https://pandoc.org/) | Documents | 43 | 65 |
-| [dvisvgm](https://dvisvgm.de/) | Vector images | 4 | 2 |
-| [ImageMagick](https://imagemagick.org/) | Images | 245 | 183 |
-| [GraphicsMagick](http://www.graphicsmagick.org/) | Images | 167 | 130 |
-| [Inkscape](https://inkscape.org/) | Vector images | 7 | 17 |
-| [Assimp](https://github.com/assimp/assimp) | 3D Assets | 77 | 23 |
-| [FFmpeg](https://ffmpeg.org/) | Video | ~472 | ~199 |
-| [Potrace](https://potrace.sourceforge.net/) | Raster to vector | 4 | 11 |
-
-
-
-
-Any missing converter? Open an issue or pull request!
-
-## Deployment
-
-> [!WARNING]
-> If you can't login, make sure you are accessing the service over localhost or https otherwise set HTTP_ALLOWED=true
-
-```yml
-# docker-compose.yml
-services:
- convertx:
- image: ghcr.io/c4illin/convertx
- container_name: convertx
- restart: unless-stopped
- ports:
- - "3000:3000"
- environment:
- - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() if unset
- volumes:
- - ./data:/app/data
-```
-
-or
-
-```bash
-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.
-
-If you get unable to open database file run `chown -R $USER:$USER path` on the path you choose.
-
-### Environment variables
-
-All are optional, JWT_SECRET is recommended to be set.
-
-| Name | Default | Description |
-|---------------------------|---------|-------------|
-| JWT_SECRET | when unset it will use the value from randomUUID() | A long and secret string used to sign the JSON Web Token |
-| ACCOUNT_REGISTRATION | false | Allow users to register accounts |
-| HTTP_ALLOWED | false | Allow HTTP connections, only set this to true locally |
-| ALLOW_UNAUTHENTICATED | false | Allow unauthenticated users to use the service, 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 |
-| WEBROOT | | The address to the root path setting this to "/convert" will serve the website on "example.com/convert/" |
-| FFMPEG_ARGS | | Arguments to pass to ffmpeg, e.g. `-preset veryfast` |
-| HIDE_HISTORY | false | Hide the history page |
-
-### Docker images
-
-There is a `:latest` tag that is updated with every release and a `:main` tag that is updated with every push to the main branch. `:latest` is recommended for normal use.
-
-The image is available on [GitHub Container Registry](https://github.com/C4illin/ConvertX/pkgs/container/ConvertX) and [Docker Hub](https://hub.docker.com/r/c4illin/convertx).
-
-| Image | What it is |
-|-------|------------|
-| `image: ghcr.io/c4illin/convertx` | The latest release on ghcr |
-| `image: ghcr.io/c4illin/convertx:main` | The latest commit on ghcr |
-| `image: c4illin/convertx` | The latest release on docker hub |
-| `image: c4illin/convertx:main` | The latest commit on docker hub |
-
-
-
-
-
-### Tutorial
-
-> [!NOTE]
-> These are written by other people, and may be outdated, incorrect or wrong.
-
-Tutorial in french:
-
-Tutorial in chinese:
-
-## Screenshots
-
-
-
-## Development
-
-0. Install [Bun](https://bun.sh/) and Git
-1. Clone the repository
-2. `bun install`
-3. `bun run dev`
-
-Pull requests are welcome! See below and open issues for the list of todos.
-
-Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) for commit messages.
-
-## Todo
-
-- [ ] Add options for converters
-- [ ] Add tests
-- [ ] Make errors logs visible from the web ui
-- [ ] Add more converters:
- - [ ] [deark](https://github.com/jsummers/deark)
- - [ ] LibreOffice
-
-## Contributors
-
-
-
-
-
-## Star History
-
-
-
-
-
-
-
-
+
+
+# ConvertX
+
+[](https://github.com/C4illin/ConvertX/actions/workflows/docker-publish.yml)
+[](https://github.com/C4illin/ConvertX/pkgs/container/ConvertX)
+[](https://hub.docker.com/r/c4illin/convertx)
+[](https://github.com/C4illin/ConvertX/pkgs/container/convertx)
+
+
+
+
+
+
+
+
+A self-hosted online file converter. Supports over a thousand different formats. Written with TypeScript, Bun and Elysia.
+
+## Features
+
+- Convert files to different formats
+- Process multiple files at once
+- Password protection
+- Multiple accounts
+
+## Converters supported
+
+| Converter | Use case | Converts from | Converts to |
+| ------------------------------------------------ | ---------------- | ------------- | ----------- |
+| [libjxl](https://github.com/libjxl/libjxl) | JPEG XL | 11 | 11 |
+| [resvg](https://github.com/RazrFalcon/resvg) | SVG | 1 | 1 |
+| [Vips](https://github.com/libvips/libvips) | Images | 45 | 23 |
+| [libheif](https://github.com/strukturag/libheif) | HEIF | 2 | 4 |
+| [XeLaTeX](https://tug.org/xetex/) | LaTeX | 1 | 1 |
+| [Calibre](https://calibre-ebook.com/) | E-books | 26 | 19 |
+| [Pandoc](https://pandoc.org/) | Documents | 43 | 65 |
+| [dvisvgm](https://dvisvgm.de/) | Vector images | 4 | 2 |
+| [ImageMagick](https://imagemagick.org/) | Images | 245 | 183 |
+| [GraphicsMagick](http://www.graphicsmagick.org/) | Images | 167 | 130 |
+| [Inkscape](https://inkscape.org/) | Vector images | 7 | 17 |
+| [Assimp](https://github.com/assimp/assimp) | 3D Assets | 77 | 23 |
+| [FFmpeg](https://ffmpeg.org/) | Video | ~472 | ~199 |
+| [Potrace](https://potrace.sourceforge.net/) | Raster to vector | 4 | 11 |
+
+
+
+Any missing converter? Open an issue or pull request!
+
+## Deployment
+
+> [!WARNING]
+> If you can't login, make sure you are accessing the service over localhost or https otherwise set HTTP_ALLOWED=true
+
+```yml
+# docker-compose.yml
+services:
+ convertx:
+ image: ghcr.io/c4illin/convertx
+ container_name: convertx
+ restart: unless-stopped
+ ports:
+ - "3000:3000"
+ environment:
+ - JWT_SECRET=aLongAndSecretStringUsedToSignTheJSONWebToken1234 # will use randomUUID() if unset
+ volumes:
+ - ./data:/app/data
+```
+
+or
+
+```bash
+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.
+
+If you get unable to open database file run `chown -R $USER:$USER path` on the path you choose.
+
+### Environment variables
+
+All are optional, JWT_SECRET is recommended to be set.
+
+| Name | Default | Description |
+| ------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
+| JWT_SECRET | when unset it will use the value from randomUUID() | A long and secret string used to sign the JSON Web Token |
+| ACCOUNT_REGISTRATION | false | Allow users to register accounts |
+| HTTP_ALLOWED | false | Allow HTTP connections, only set this to true locally |
+| ALLOW_UNAUTHENTICATED | false | Allow unauthenticated users to use the service, 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 |
+| WEBROOT | | The address to the root path setting this to "/convert" will serve the website on "example.com/convert/" |
+| FFMPEG_ARGS | | Arguments to pass to ffmpeg, e.g. `-preset veryfast` |
+| HIDE_HISTORY | false | Hide the history page |
+
+### Docker images
+
+There is a `:latest` tag that is updated with every release and a `:main` tag that is updated with every push to the main branch. `:latest` is recommended for normal use.
+
+The image is available on [GitHub Container Registry](https://github.com/C4illin/ConvertX/pkgs/container/ConvertX) and [Docker Hub](https://hub.docker.com/r/c4illin/convertx).
+
+| Image | What it is |
+| -------------------------------------- | -------------------------------- |
+| `image: ghcr.io/c4illin/convertx` | The latest release on ghcr |
+| `image: ghcr.io/c4illin/convertx:main` | The latest commit on ghcr |
+| `image: c4illin/convertx` | The latest release on docker hub |
+| `image: c4illin/convertx:main` | The latest commit on docker hub |
+
+
+
+
+
+
+### Tutorial
+
+> [!NOTE]
+> These are written by other people, and may be outdated, incorrect or wrong.
+
+Tutorial in french:
+
+Tutorial in chinese:
+
+## Screenshots
+
+
+
+## Development
+
+0. Install [Bun](https://bun.sh/) and Git
+1. Clone the repository
+2. `bun install`
+3. `bun run dev`
+
+Pull requests are welcome! See below and open issues for the list of todos.
+
+Use [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/#summary) for commit messages.
+
+## Todo
+
+- [ ] Add options for converters
+- [ ] Add tests
+- [ ] Make errors logs visible from the web ui
+- [ ] Add more converters:
+ - [ ] [deark](https://github.com/jsummers/deark)
+ - [ ] LibreOffice
+
+## Contributors
+
+
+
+
+
+## Star History
+
+
+
+
+
+
+
+
diff --git a/biome.json b/biome.json
index e14b242..b49e76e 100644
--- a/biome.json
+++ b/biome.json
@@ -10,10 +10,7 @@
"attributePosition": "auto"
},
"files": {
- "ignore": [
- "**/node_modules/**",
- "**/pico.lime.min.css"
- ]
+ "ignore": ["**/node_modules/**", "**/pico.lime.min.css"]
},
"organizeImports": {
"enabled": true
@@ -72,4 +69,4 @@
"attributePosition": "auto"
}
}
-}
\ No newline at end of file
+}
diff --git a/compose.yaml b/compose.yaml
index 183fd6b..e129451 100644
--- a/compose.yaml
+++ b/compose.yaml
@@ -1,19 +1,19 @@
-services:
- convertx:
- build:
- context: .
- # dockerfile: Debian.Dockerfile
- volumes:
- - ./data:/app/data
- environment: # Defaults are listed below. All are optional.
- - ACCOUNT_REGISTRATION=true # true or false, doesn't matter for the first account (e.g. keep this to false if you only want one account)
- - 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=1 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
- # - FFMPEG_ARGS=-hwaccel vulkan # additional arguments to pass to ffmpeg
- # - WEBROOT=/convertx # the root path of the web interface, leave empty to disable
- # - HIDE_HISTORY=true # hides the history tab in the web interface, defaults to false
- - TZ=Europe/Stockholm # set your timezone, defaults to UTC
- ports:
- - 3000:3000
+services:
+ convertx:
+ build:
+ context: .
+ # dockerfile: Debian.Dockerfile
+ volumes:
+ - ./data:/app/data
+ environment: # Defaults are listed below. All are optional.
+ - ACCOUNT_REGISTRATION=true # true or false, doesn't matter for the first account (e.g. keep this to false if you only want one account)
+ - 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=1 # checks every n hours for files older then n hours and deletes them, set to 0 to disable
+ # - FFMPEG_ARGS=-hwaccel vulkan # additional arguments to pass to ffmpeg
+ # - WEBROOT=/convertx # the root path of the web interface, leave empty to disable
+ # - HIDE_HISTORY=true # hides the history tab in the web interface, defaults to false
+ - TZ=Europe/Stockholm # set your timezone, defaults to UTC
+ ports:
+ - 3000:3000
diff --git a/eslint.config.ts b/eslint.config.ts
index f237f31..6bf8f24 100644
--- a/eslint.config.ts
+++ b/eslint.config.ts
@@ -1,66 +1,66 @@
-import js from "@eslint/js";
-import eslintParserTypeScript from "@typescript-eslint/parser";
-import type { Linter } from "eslint";
-import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
-import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
-import globals from "globals";
-import tseslint from "typescript-eslint";
-
-export default [
- js.configs.recommended,
- ...tseslint.configs.recommended,
- // ...tailwind.configs["flat/recommended"],
- {
- plugins: {
- "simple-import-sort": simpleImportSortPlugin,
- "better-tailwindcss": eslintPluginBetterTailwindcss,
- },
- ignores: ["**/node_modules/**"],
- languageOptions: {
- parser: eslintParserTypeScript,
- parserOptions: {
- project: true,
- ecmaFeatures: {
- jsx: true,
- },
- },
- globals: {
- ...globals.node,
- ...globals.browser,
- },
- },
- files: ["**/*.{js,mjs,cjs,jsx,tsx,ts}"],
- settings: {
- "better-tailwindcss": {
- entryPoint: "src/main.css",
- },
- },
- rules: {
- ...eslintPluginBetterTailwindcss.configs["recommended-warn"]?.rules,
- ...eslintPluginBetterTailwindcss.configs["stylistic-warn"]?.rules,
- // "tailwindcss/classnames-order": "off",
- "better-tailwindcss/multiline": [
- "warn",
- {
- group: "newLine",
- printWidth: 100,
- },
- ],
- "better-tailwindcss/no-unregistered-classes": [
- "warn",
- {
- ignore: [
- "^group(?:\\/(\\S*))?$",
- "^peer(?:\\/(\\S*))?$",
- "select_container",
- "convert_to_popup",
- "convert_to_group",
- "target",
- "convert_to_target",
- "job-details-toggle",
- ],
- },
- ],
- },
- },
-] as Linter.Config[];
+import js from "@eslint/js";
+import eslintParserTypeScript from "@typescript-eslint/parser";
+import type { Linter } from "eslint";
+import eslintPluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
+import simpleImportSortPlugin from "eslint-plugin-simple-import-sort";
+import globals from "globals";
+import tseslint from "typescript-eslint";
+
+export default [
+ js.configs.recommended,
+ ...tseslint.configs.recommended,
+ // ...tailwind.configs["flat/recommended"],
+ {
+ plugins: {
+ "simple-import-sort": simpleImportSortPlugin,
+ "better-tailwindcss": eslintPluginBetterTailwindcss,
+ },
+ ignores: ["**/node_modules/**"],
+ languageOptions: {
+ parser: eslintParserTypeScript,
+ parserOptions: {
+ project: true,
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+ globals: {
+ ...globals.node,
+ ...globals.browser,
+ },
+ },
+ files: ["**/*.{js,mjs,cjs,jsx,tsx,ts}"],
+ settings: {
+ "better-tailwindcss": {
+ entryPoint: "src/main.css",
+ },
+ },
+ rules: {
+ ...(eslintPluginBetterTailwindcss.configs["recommended-warn"] ?? {}).rules,
+ ...(eslintPluginBetterTailwindcss.configs["stylistic-warn"] ?? {}).rules,
+ // "tailwindcss/classnames-order": "off",
+ "better-tailwindcss/multiline": [
+ "warn",
+ {
+ group: "newLine",
+ printWidth: 100,
+ },
+ ],
+ "better-tailwindcss/no-unregistered-classes": [
+ "warn",
+ {
+ ignore: [
+ "^group(?:\\/(\\S*))?$",
+ "^peer(?:\\/(\\S*))?$",
+ "select_container",
+ "convert_to_popup",
+ "convert_to_group",
+ "target",
+ "convert_to_target",
+ "job-details-toggle",
+ ],
+ },
+ ],
+ },
+ },
+] as Linter.Config[];
diff --git a/package.json b/package.json
index 6ecfac1..5f6ba95 100644
--- a/package.json
+++ b/package.json
@@ -4,12 +4,15 @@
"scripts": {
"dev": "bun run --watch src/index.tsx",
"hot": "bun run --hot src/index.tsx",
- "format": "eslint --fix .",
+ "format": "run-p 'format:*'",
+ "format:eslint": "eslint --fix .",
+ "format:prettier": "prettier --write .",
"build": "bunx @tailwindcss/cli -i ./src/main.css -o ./public/generated.css",
"lint": "run-p 'lint:*'",
"lint:tsc": "tsc --noEmit",
"lint:knip": "knip",
- "lint:eslint": "eslint ."
+ "lint:eslint": "eslint .",
+ "lint:prettier": "prettier --check ."
},
"dependencies": {
"@elysiajs/html": "^1.3.0",
diff --git a/postcss.config.js b/postcss.config.js
index 5ba0f7a..c2ddf74 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,5 +1,5 @@
-export default {
- plugins: {
- "@tailwindcss/postcss": {},
- },
-};
\ No newline at end of file
+export default {
+ plugins: {
+ "@tailwindcss/postcss": {},
+ },
+};
diff --git a/prettier.config.js b/prettier.config.js
index 561cb0c..df16566 100644
--- a/prettier.config.js
+++ b/prettier.config.js
@@ -3,7 +3,7 @@
*/
const config = {
arrowParens: "always",
- printWidth: 80,
+ printWidth: 100,
singleQuote: false,
semi: true,
tabWidth: 2,
diff --git a/public/script.js b/public/script.js
index 81caee2..8b89194 100644
--- a/public/script.js
+++ b/public/script.js
@@ -72,9 +72,7 @@ function handleFile(file) {
const selectContainer = document.querySelector("form .select_container");
const updateSearchBar = () => {
- const convertToInput = document.querySelector(
- "input[name='convert_to_search']",
- );
+ const convertToInput = document.querySelector("input[name='convert_to_search']");
const convertToPopup = document.querySelector(".convert_to_popup");
const convertToGroupElements = document.querySelectorAll(".convert_to_group");
const convertToGroups = {};
@@ -195,8 +193,7 @@ const deleteRow = (target) => {
headers: {
"Content-Type": "application/json",
},
- })
- .catch((err) => console.log(err));
+ }).catch((err) => console.log(err));
};
const uploadFile = (file) => {
@@ -234,7 +231,7 @@ const uploadFile = (file) => {
console.log(`upload progress (${file.name}):`, (100 * sent) / total);
let progressbar = file.htmlRow.getElementsByTagName("progress");
- progressbar[0].value = ((100 * sent) / total);
+ progressbar[0].value = (100 * sent) / total;
};
xhr.onerror = (e) => {
diff --git a/renovate.json b/renovate.json
index 2d3f60e..3418a44 100644
--- a/renovate.json
+++ b/renovate.json
@@ -1,11 +1,8 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": [
- "config:recommended",
- ":disableDependencyDashboard"
- ],
+ "extends": ["config:recommended", ":disableDependencyDashboard"],
"lockFileMaintenance": {
"enabled": true,
"automerge": true
}
-}
\ No newline at end of file
+}
diff --git a/reset.d.ts b/reset.d.ts
index e186b1f..a3d4a03 100644
--- a/reset.d.ts
+++ b/reset.d.ts
@@ -1 +1 @@
-import "@total-typescript/ts-reset";
\ No newline at end of file
+import "@total-typescript/ts-reset";
diff --git a/src/components/base.tsx b/src/components/base.tsx
index 3c84b75..06b6c7b 100644
--- a/src/components/base.tsx
+++ b/src/components/base.tsx
@@ -17,23 +17,9 @@ export const BaseHtml = ({
{title}
-
-
-
+
+
+
diff --git a/src/converters/assimp.ts b/src/converters/assimp.ts
index 76085e6..cac4f9f 100644
--- a/src/converters/assimp.ts
+++ b/src/converters/assimp.ts
@@ -1,139 +1,139 @@
-import { execFile } from "node:child_process";
-
-export const properties = {
- from: {
- object: [
- "3d",
- "3ds",
- "3mf",
- "ac",
- "ac3d",
- "acc",
- "amf",
- "amj",
- "ase",
- "ask",
- "assbin",
- "b3d",
- "blend",
- "bsp",
- "bvh",
- "cob",
- "csm",
- "dae",
- "dxf",
- "enff",
- "fbx",
- "glb",
- "gltf",
- "hmb",
- "hmp",
- "ifc",
- "ifczip",
- "iqm",
- "irr",
- "irrmesh",
- "lwo",
- "lws",
- "lxo",
- "m3d",
- "md2",
- "md3",
- "md5anim",
- "md5camera",
- "md5mesh",
- "mdc",
- "mdl",
- "mesh.xml",
- "mesh",
- "mot",
- "ms3d",
- "ndo",
- "nff",
- "obj",
- "off",
- "ogex",
- "pk3",
- "ply",
- "pmx",
- "prj",
- "q3o",
- "q3s",
- "raw",
- "scn",
- "sib",
- "smd",
- "step",
- "stl",
- "stp",
- "ter",
- "uc",
- "usd",
- "usda",
- "usdc",
- "usdz",
- "vta",
- "x",
- "x3d",
- "x3db",
- "xgl",
- "xml",
- "zae",
- "zgl",
- ],
- },
- to: {
- object: [
- "3ds",
- "3mf",
- "assbin",
- "assjson",
- "assxml",
- "collada",
- "dae",
- "fbx",
- "fbxa",
- "glb",
- "glb2",
- "gltf",
- "gltf2",
- "json",
- "obj",
- "objnomtl",
- "pbrt",
- "ply",
- "plyb",
- "stl",
- "stlb",
- "stp",
- "x",
- ],
- },
-};
-
-export async function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- return new Promise((resolve, reject) => {
- execFile("assimp", ["export", filePath, targetPath], (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- });
- });
-}
+import { execFile } from "node:child_process";
+
+export const properties = {
+ from: {
+ object: [
+ "3d",
+ "3ds",
+ "3mf",
+ "ac",
+ "ac3d",
+ "acc",
+ "amf",
+ "amj",
+ "ase",
+ "ask",
+ "assbin",
+ "b3d",
+ "blend",
+ "bsp",
+ "bvh",
+ "cob",
+ "csm",
+ "dae",
+ "dxf",
+ "enff",
+ "fbx",
+ "glb",
+ "gltf",
+ "hmb",
+ "hmp",
+ "ifc",
+ "ifczip",
+ "iqm",
+ "irr",
+ "irrmesh",
+ "lwo",
+ "lws",
+ "lxo",
+ "m3d",
+ "md2",
+ "md3",
+ "md5anim",
+ "md5camera",
+ "md5mesh",
+ "mdc",
+ "mdl",
+ "mesh.xml",
+ "mesh",
+ "mot",
+ "ms3d",
+ "ndo",
+ "nff",
+ "obj",
+ "off",
+ "ogex",
+ "pk3",
+ "ply",
+ "pmx",
+ "prj",
+ "q3o",
+ "q3s",
+ "raw",
+ "scn",
+ "sib",
+ "smd",
+ "step",
+ "stl",
+ "stp",
+ "ter",
+ "uc",
+ "usd",
+ "usda",
+ "usdc",
+ "usdz",
+ "vta",
+ "x",
+ "x3d",
+ "x3db",
+ "xgl",
+ "xml",
+ "zae",
+ "zgl",
+ ],
+ },
+ to: {
+ object: [
+ "3ds",
+ "3mf",
+ "assbin",
+ "assjson",
+ "assxml",
+ "collada",
+ "dae",
+ "fbx",
+ "fbxa",
+ "glb",
+ "glb2",
+ "gltf",
+ "gltf2",
+ "json",
+ "obj",
+ "objnomtl",
+ "pbrt",
+ "ply",
+ "plyb",
+ "stl",
+ "stlb",
+ "stp",
+ "x",
+ ],
+ },
+};
+
+export async function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ return new Promise((resolve, reject) => {
+ execFile("assimp", ["export", filePath, targetPath], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/dvisvgm.ts b/src/converters/dvisvgm.ts
index ef58c81..a9ce593 100644
--- a/src/converters/dvisvgm.ts
+++ b/src/converters/dvisvgm.ts
@@ -29,24 +29,20 @@ export function convert(
}
return new Promise((resolve, reject) => {
- execFile(
- "dvisvgm",
- [...inputArgs, filePath, "-o", targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
+ execFile("dvisvgm", [...inputArgs, filePath, "-o", 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("Done");
- },
- );
+ resolve("Done");
+ });
});
}
diff --git a/src/converters/ffmpeg.ts b/src/converters/ffmpeg.ts
index feb6a66..b8bc796 100644
--- a/src/converters/ffmpeg.ts
+++ b/src/converters/ffmpeg.ts
@@ -1,756 +1,754 @@
-import { execFile } from "node:child_process";
-
-// This could be done dynamically by running `ffmpeg -formats` and parsing the output
-export const properties = {
- from: {
- muxer: [
- "264",
- "265",
- "266",
- "302",
- "3dostr",
- "3g2",
- "3gp",
- "4xm",
- "669",
- "722",
- "aa",
- "aa3",
- "aac",
- "aax",
- "ac3",
- "ac4",
- "ace",
- "acm",
- "act",
- "adf",
- "adp",
- "ads",
- "adx",
- "aea",
- "afc",
- "aiff",
- "aix",
- "al",
- "alaw",
- "alias_pix",
- "alp",
- "alsa",
- "amf",
- "amr",
- "amrnb",
- "amrwb",
- "ams",
- "anm",
- "ans",
- "apc",
- "ape",
- "apl",
- "apm",
- "apng",
- "aptx",
- "aptxhd",
- "aqt",
- "aqtitle",
- "argo_asf",
- "argo_brp",
- "art",
- "asc",
- "asf",
- "asf_o",
- "ass",
- "ast",
- "au",
- "av1",
- "avc",
- "avi",
- "avif",
- "avr",
- "avs",
- "avs2",
- "avs3",
- "awb",
- "bcstm",
- "bethsoftvid",
- "bfi",
- "bfstm",
- "bin",
- "bink",
- "binka",
- "bit",
- "bitpacked",
- "bmv",
- "bmp",
- "bonk",
- "boa",
- "brender_pix",
- "brstm",
- "c2",
- "c93",
- "caf",
- "cavsvideo",
- "cdata",
- "cdg",
- "cdxl",
- "cgi",
- "cif",
- "cine",
- "codec2",
- "codec2raw",
- "concat",
- "cri",
- "dash",
- "dat",
- "data",
- "daud",
- "dav",
- "dbm",
- "dcstr",
- "dds",
- "derf",
- "dfpwm",
- "dfa",
- "dhav",
- "dif",
- "digi",
- "dirac",
- "diz",
- "dmf",
- "dnxhd",
- "dpx_pipe",
- "dsf",
- "dsicin",
- "dsm",
- "dss",
- "dtk",
- "dtm",
- "dts",
- "dtshd",
- "dv",
- "dvbsub",
- "dvbtxt",
- "dxa",
- "ea",
- "eac3",
- "ea_cdata",
- "epaf",
- "exr_pipe",
- "f32be",
- "f32le",
- "ec3",
- "evc",
- "f4v",
- "f64be",
- "f64le",
- "fap",
- "far",
- "fbdev",
- "ffmetadata",
- "filmstrip",
- "film_cpk",
- "fits",
- "flac",
- "flic",
- "flm",
- "flv",
- "frm",
- "fsb",
- "fwse",
- "g722",
- "g723_1",
- "g726",
- "g726le",
- "g729",
- "gdm",
- "gdv",
- "genh",
- "gif",
- "gsm",
- "gxf",
- "h261",
- "h263",
- "h264",
- "h265",
- "h266",
- "h26l",
- "hca",
- "hcom",
- "hevc",
- "hls",
- "hnm",
- "ice",
- "ico",
- "idcin",
- "idf",
- "idx",
- "iec61883",
- "iff",
- "ifv",
- "ilbc",
- "image2",
- "imf",
- "imx",
- "ingenient",
- "ipmovie",
- "ipu",
- "ircam",
- "ism",
- "isma",
- "ismv",
- "iss",
- "it",
- "iv8",
- "ivf",
- "ivr",
- "j2b",
- "j2k",
- "jack",
- "jacosub",
- "jv",
- "jpegls",
- "jpeg",
- "jxl",
- "kmsgrab",
- "kux",
- "kvag",
- "lavfi",
- "laf",
- "lmlm4",
- "loas",
- "lrc",
- "luodat",
- "lvf",
- "lxf",
- "m15",
- "m2a",
- "m4a",
- "m4b",
- "m4v",
- "mac",
- "mca",
- "mcc",
- "mdl",
- "med",
- "microdvd",
- "mj2",
- "mjpeg",
- "mjpg",
- "mk3d",
- "mka",
- "mks",
- "mkv",
- "mlp",
- "mlv",
- "mm",
- "mmcmp",
- "mmf",
- "mms",
- "mo3",
- "mod",
- "mods",
- "moflex",
- "mov",
- "mp2",
- "mp3",
- "mp4",
- "mpa",
- "mpc",
- "mpc8",
- "mpeg",
- "mpg",
- "mpjpeg",
- "mpl2",
- "mpo",
- "mpsub",
- "mptm",
- "msbc",
- "msf",
- "msnwctcp",
- "msp",
- "mt2",
- "mtaf",
- "mtm",
- "mtv",
- "mulaw",
- "musx",
- "mv",
- "mvi",
- "mxf",
- "mxg",
- "nc",
- "nfo",
- "nist",
- "nistsphere",
- "nsp",
- "nst",
- "nsv",
- "nut",
- "nuv",
- "obu",
- "ogg",
- "okt",
- "oma",
- "omg",
- "opus",
- "openal",
- "oss",
- "osq",
- "paf",
- "pdv",
- "pam",
- "pbm",
- "pcx",
- "pgmyuv",
- "pgm",
- "pgx",
- "photocd",
- "pictor",
- "pjs",
- "plm",
- "pmp",
- "png",
- "ppm",
- "pp",
- "psd",
- "psm",
- "psp",
- "psxstr",
- "pt36",
- "ptm",
- "pulse",
- "pva",
- "pvf",
- "qcif",
- "qcp",
- "qdraw",
- "r3d",
- "rawvideo",
- "rco",
- "rcv",
- "realtext",
- "redspark",
- "rgb",
- "rl2",
- "rm",
- "roq",
- "rpl",
- "rka",
- "rsd",
- "rso",
- "rt",
- "rtp",
- "rtsp",
- "s16be",
- "s16le",
- "s24be",
- "s24le",
- "s32be",
- "s32le",
- "s337m",
- "s3m",
- "s8",
- "sami",
- "sap",
- "sb",
- "sbc",
- "sbg",
- "scc",
- "sdns",
- "sdp",
- "sdr2",
- "sds",
- "sdx",
- "ser",
- "sf",
- "sfx",
- "sfx2",
- "sga",
- "sgi",
- "shn",
- "siff",
- "sln",
- "smi",
- "smjpeg",
- "smk",
- "smush",
- "sndio",
- "sol",
- "son",
- "sox",
- "spdif",
- "sph",
- "srt",
- "ss2",
- "ssa",
- "st26",
- "stk",
- "stl",
- "stm",
- "stp",
- "str",
- "sub",
- "sup",
- "svag",
- "svg",
- "svs",
- "sw",
- "swf",
- "tak",
- "tco",
- "tedcaptions",
- "thd",
- "thp",
- "tiertexseq",
- "tif",
- "tiff",
- "tmv",
- "truehd",
- "tta",
- "tty",
- "txd",
- "txt",
- "ty",
- "ty+",
- "u16be",
- "u16le",
- "u24be",
- "u24le",
- "u32be",
- "u32le",
- "u8",
- "ub",
- "ul",
- "ult",
- "umx",
- "usm",
- "uw",
- "v",
- "v210",
- "v210x",
- "vag",
- "vb",
- "vc1",
- "vc1test",
- "vidc",
- "video4linux2",
- "viv",
- "vividas",
- "vivo",
- "vmd",
- "vobsub",
- "voc",
- "vpk",
- "vplayer",
- "vqe",
- "vqf",
- "vql",
- "vt",
- "vtt",
- "vvc",
- "w64",
- "wa",
- "wav",
- "way",
- "wc3movie",
- "webm",
- "webp",
- "webvtt",
- "wow",
- "wsaud",
- "wsd",
- "wsvqa",
- "wtv",
- "wv",
- "wve",
- "x11grab",
- "xa",
- "xbin",
- "xl",
- "xm",
- "xmd",
- "xmv",
- "xpk",
- "xvag",
- "xwma",
- "y4m",
- "yop",
- "yuv",
- "yuv10",
- ],
- },
- to: {
- muxer: [
- "264",
- "265",
- "266",
- "302",
- "3g2",
- "3gp",
- "a64",
- "aac",
- "ac3",
- "ac4",
- "adts",
- "adx",
- "afc",
- "aif",
- "aifc",
- "aiff",
- "al",
- "amr",
- "amv",
- "apm",
- "apng",
- "aptx",
- "aptxhd",
- "asf",
- "ass",
- "ast",
- "au",
- "aud",
- "av1.mkv",
- "av1.mp4",
- "avi",
- "avif",
- "avs",
- "avs2",
- "avs3",
- "bit",
- "bmp",
- "c2",
- "caf",
- "cavs",
- "chk",
- "cpk",
- "cvg",
- "dfpwm",
- "dnxhd",
- "dnxhr",
- "dpx",
- "drc",
- "dts",
- "dv",
- "dvd",
- "eac3",
- "ec3",
- "evc",
- "exr",
- "f4v",
- "ffmeta",
- "fits",
- "flac",
- "flm",
- "flv",
- "g722",
- "gif",
- "gsm",
- "gxf",
- "h261",
- "h263",
- "h264.mkv",
- "h264.mp4",
- "h265.mkv",
- "h265.mp4",
- "h266.mkv",
- "hdr",
- "hevc",
- "ico",
- "im1",
- "im24",
- "im8",
- "ircam",
- "isma",
- "ismv",
- "ivf",
- "j2c",
- "j2k",
- "jls",
- "jp2",
- "jpeg",
- "jpg",
- "js",
- "jss",
- "jxl",
- "latm",
- "lbc",
- "ljpg",
- "loas",
- "lrc",
- "m1v",
- "m2a",
- "m2t",
- "m2ts",
- "m2v",
- "m3u8",
- "m4a",
- "m4b",
- "m4v",
- "mjpeg",
- "mjpg",
- "mkv",
- "mlp",
- "mmf",
- "mov",
- "mp2",
- "mp3",
- "mp4",
- "mpa",
- "mpd",
- "mpeg",
- "mpg",
- "msbc",
- "mts",
- "mxf",
- "nut",
- "obu",
- "oga",
- "ogg",
- "ogv",
- "oma",
- "opus",
- "pam",
- "pbm",
- "pcm",
- "pcx",
- "pfm",
- "pgm",
- "pgmyuv",
- "phm",
- "pix",
- "png",
- "ppm",
- "psp",
- "qoi",
- "ra",
- "ras",
- "rco",
- "rcv",
- "rgb",
- "rm",
- "roq",
- "rs",
- "rso",
- "sb",
- "sbc",
- "scc",
- "sf",
- "sgi",
- "sox",
- "spdif",
- "spx",
- "srt",
- "ssa",
- "sub",
- "sun",
- "sunras",
- "sup",
- "sw",
- "swf",
- "tco",
- "tga",
- "thd",
- "tif",
- "tiff",
- "ts",
- "tta",
- "ttml",
- "tun",
- "ub",
- "ul",
- "uw",
- "vag",
- "vbn",
- "vc1",
- "vc2",
- "vob",
- "voc",
- "vtt",
- "vvc",
- "w64",
- "wav",
- "wbmp",
- "webm",
- "webp",
- "wma",
- "wmv",
- "wtv",
- "wv",
- "xbm",
- "xface",
- "xml",
- "xwd",
- "y",
- "y4m",
- "yuv",
- ],
- },
-};
-
-export async function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- let extraArgs: string[] = [];
- let message = "Done";
-
- if (convertTo === "ico") {
- // make sure image is 256x256 or smaller
- extraArgs = [
- "-filter:v",
- "scale='min(256,iw)':min'(256,ih)':force_original_aspect_ratio=decrease",
- ];
- message = "Done: resized to 256x256";
- }
-
- if (convertTo.split(".").length > 1) {
- // support av1.mkv and av1.mp4 and h265.mp4 etc.
- const split = convertTo.split(".");
- const codec_short = split[0];
-
- switch (codec_short) {
- case "av1":
- extraArgs.push("-c:v", "libaom-av1");
- break;
- case "h264":
- extraArgs.push("-c:v", "libx264");
- break;
- case "h265":
- extraArgs.push("-c:v", "libx265");
- break;
- case "h266":
- extraArgs.push("-c:v", "libx266");
- break;
- }
- }
-
- // Parse FFMPEG_ARGS environment variable into array
- const ffmpegArgs = process.env.FFMPEG_ARGS
- ? process.env.FFMPEG_ARGS.split(/\s+/)
- : [];
-
- return new Promise((resolve, reject) => {
- execFile(
- "ffmpeg",
- [...ffmpegArgs, "-i", filePath, ...extraArgs, targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve(message);
- },
- );
- });
-}
+import { execFile } from "node:child_process";
+
+// This could be done dynamically by running `ffmpeg -formats` and parsing the output
+export const properties = {
+ from: {
+ muxer: [
+ "264",
+ "265",
+ "266",
+ "302",
+ "3dostr",
+ "3g2",
+ "3gp",
+ "4xm",
+ "669",
+ "722",
+ "aa",
+ "aa3",
+ "aac",
+ "aax",
+ "ac3",
+ "ac4",
+ "ace",
+ "acm",
+ "act",
+ "adf",
+ "adp",
+ "ads",
+ "adx",
+ "aea",
+ "afc",
+ "aiff",
+ "aix",
+ "al",
+ "alaw",
+ "alias_pix",
+ "alp",
+ "alsa",
+ "amf",
+ "amr",
+ "amrnb",
+ "amrwb",
+ "ams",
+ "anm",
+ "ans",
+ "apc",
+ "ape",
+ "apl",
+ "apm",
+ "apng",
+ "aptx",
+ "aptxhd",
+ "aqt",
+ "aqtitle",
+ "argo_asf",
+ "argo_brp",
+ "art",
+ "asc",
+ "asf",
+ "asf_o",
+ "ass",
+ "ast",
+ "au",
+ "av1",
+ "avc",
+ "avi",
+ "avif",
+ "avr",
+ "avs",
+ "avs2",
+ "avs3",
+ "awb",
+ "bcstm",
+ "bethsoftvid",
+ "bfi",
+ "bfstm",
+ "bin",
+ "bink",
+ "binka",
+ "bit",
+ "bitpacked",
+ "bmv",
+ "bmp",
+ "bonk",
+ "boa",
+ "brender_pix",
+ "brstm",
+ "c2",
+ "c93",
+ "caf",
+ "cavsvideo",
+ "cdata",
+ "cdg",
+ "cdxl",
+ "cgi",
+ "cif",
+ "cine",
+ "codec2",
+ "codec2raw",
+ "concat",
+ "cri",
+ "dash",
+ "dat",
+ "data",
+ "daud",
+ "dav",
+ "dbm",
+ "dcstr",
+ "dds",
+ "derf",
+ "dfpwm",
+ "dfa",
+ "dhav",
+ "dif",
+ "digi",
+ "dirac",
+ "diz",
+ "dmf",
+ "dnxhd",
+ "dpx_pipe",
+ "dsf",
+ "dsicin",
+ "dsm",
+ "dss",
+ "dtk",
+ "dtm",
+ "dts",
+ "dtshd",
+ "dv",
+ "dvbsub",
+ "dvbtxt",
+ "dxa",
+ "ea",
+ "eac3",
+ "ea_cdata",
+ "epaf",
+ "exr_pipe",
+ "f32be",
+ "f32le",
+ "ec3",
+ "evc",
+ "f4v",
+ "f64be",
+ "f64le",
+ "fap",
+ "far",
+ "fbdev",
+ "ffmetadata",
+ "filmstrip",
+ "film_cpk",
+ "fits",
+ "flac",
+ "flic",
+ "flm",
+ "flv",
+ "frm",
+ "fsb",
+ "fwse",
+ "g722",
+ "g723_1",
+ "g726",
+ "g726le",
+ "g729",
+ "gdm",
+ "gdv",
+ "genh",
+ "gif",
+ "gsm",
+ "gxf",
+ "h261",
+ "h263",
+ "h264",
+ "h265",
+ "h266",
+ "h26l",
+ "hca",
+ "hcom",
+ "hevc",
+ "hls",
+ "hnm",
+ "ice",
+ "ico",
+ "idcin",
+ "idf",
+ "idx",
+ "iec61883",
+ "iff",
+ "ifv",
+ "ilbc",
+ "image2",
+ "imf",
+ "imx",
+ "ingenient",
+ "ipmovie",
+ "ipu",
+ "ircam",
+ "ism",
+ "isma",
+ "ismv",
+ "iss",
+ "it",
+ "iv8",
+ "ivf",
+ "ivr",
+ "j2b",
+ "j2k",
+ "jack",
+ "jacosub",
+ "jv",
+ "jpegls",
+ "jpeg",
+ "jxl",
+ "kmsgrab",
+ "kux",
+ "kvag",
+ "lavfi",
+ "laf",
+ "lmlm4",
+ "loas",
+ "lrc",
+ "luodat",
+ "lvf",
+ "lxf",
+ "m15",
+ "m2a",
+ "m4a",
+ "m4b",
+ "m4v",
+ "mac",
+ "mca",
+ "mcc",
+ "mdl",
+ "med",
+ "microdvd",
+ "mj2",
+ "mjpeg",
+ "mjpg",
+ "mk3d",
+ "mka",
+ "mks",
+ "mkv",
+ "mlp",
+ "mlv",
+ "mm",
+ "mmcmp",
+ "mmf",
+ "mms",
+ "mo3",
+ "mod",
+ "mods",
+ "moflex",
+ "mov",
+ "mp2",
+ "mp3",
+ "mp4",
+ "mpa",
+ "mpc",
+ "mpc8",
+ "mpeg",
+ "mpg",
+ "mpjpeg",
+ "mpl2",
+ "mpo",
+ "mpsub",
+ "mptm",
+ "msbc",
+ "msf",
+ "msnwctcp",
+ "msp",
+ "mt2",
+ "mtaf",
+ "mtm",
+ "mtv",
+ "mulaw",
+ "musx",
+ "mv",
+ "mvi",
+ "mxf",
+ "mxg",
+ "nc",
+ "nfo",
+ "nist",
+ "nistsphere",
+ "nsp",
+ "nst",
+ "nsv",
+ "nut",
+ "nuv",
+ "obu",
+ "ogg",
+ "okt",
+ "oma",
+ "omg",
+ "opus",
+ "openal",
+ "oss",
+ "osq",
+ "paf",
+ "pdv",
+ "pam",
+ "pbm",
+ "pcx",
+ "pgmyuv",
+ "pgm",
+ "pgx",
+ "photocd",
+ "pictor",
+ "pjs",
+ "plm",
+ "pmp",
+ "png",
+ "ppm",
+ "pp",
+ "psd",
+ "psm",
+ "psp",
+ "psxstr",
+ "pt36",
+ "ptm",
+ "pulse",
+ "pva",
+ "pvf",
+ "qcif",
+ "qcp",
+ "qdraw",
+ "r3d",
+ "rawvideo",
+ "rco",
+ "rcv",
+ "realtext",
+ "redspark",
+ "rgb",
+ "rl2",
+ "rm",
+ "roq",
+ "rpl",
+ "rka",
+ "rsd",
+ "rso",
+ "rt",
+ "rtp",
+ "rtsp",
+ "s16be",
+ "s16le",
+ "s24be",
+ "s24le",
+ "s32be",
+ "s32le",
+ "s337m",
+ "s3m",
+ "s8",
+ "sami",
+ "sap",
+ "sb",
+ "sbc",
+ "sbg",
+ "scc",
+ "sdns",
+ "sdp",
+ "sdr2",
+ "sds",
+ "sdx",
+ "ser",
+ "sf",
+ "sfx",
+ "sfx2",
+ "sga",
+ "sgi",
+ "shn",
+ "siff",
+ "sln",
+ "smi",
+ "smjpeg",
+ "smk",
+ "smush",
+ "sndio",
+ "sol",
+ "son",
+ "sox",
+ "spdif",
+ "sph",
+ "srt",
+ "ss2",
+ "ssa",
+ "st26",
+ "stk",
+ "stl",
+ "stm",
+ "stp",
+ "str",
+ "sub",
+ "sup",
+ "svag",
+ "svg",
+ "svs",
+ "sw",
+ "swf",
+ "tak",
+ "tco",
+ "tedcaptions",
+ "thd",
+ "thp",
+ "tiertexseq",
+ "tif",
+ "tiff",
+ "tmv",
+ "truehd",
+ "tta",
+ "tty",
+ "txd",
+ "txt",
+ "ty",
+ "ty+",
+ "u16be",
+ "u16le",
+ "u24be",
+ "u24le",
+ "u32be",
+ "u32le",
+ "u8",
+ "ub",
+ "ul",
+ "ult",
+ "umx",
+ "usm",
+ "uw",
+ "v",
+ "v210",
+ "v210x",
+ "vag",
+ "vb",
+ "vc1",
+ "vc1test",
+ "vidc",
+ "video4linux2",
+ "viv",
+ "vividas",
+ "vivo",
+ "vmd",
+ "vobsub",
+ "voc",
+ "vpk",
+ "vplayer",
+ "vqe",
+ "vqf",
+ "vql",
+ "vt",
+ "vtt",
+ "vvc",
+ "w64",
+ "wa",
+ "wav",
+ "way",
+ "wc3movie",
+ "webm",
+ "webp",
+ "webvtt",
+ "wow",
+ "wsaud",
+ "wsd",
+ "wsvqa",
+ "wtv",
+ "wv",
+ "wve",
+ "x11grab",
+ "xa",
+ "xbin",
+ "xl",
+ "xm",
+ "xmd",
+ "xmv",
+ "xpk",
+ "xvag",
+ "xwma",
+ "y4m",
+ "yop",
+ "yuv",
+ "yuv10",
+ ],
+ },
+ to: {
+ muxer: [
+ "264",
+ "265",
+ "266",
+ "302",
+ "3g2",
+ "3gp",
+ "a64",
+ "aac",
+ "ac3",
+ "ac4",
+ "adts",
+ "adx",
+ "afc",
+ "aif",
+ "aifc",
+ "aiff",
+ "al",
+ "amr",
+ "amv",
+ "apm",
+ "apng",
+ "aptx",
+ "aptxhd",
+ "asf",
+ "ass",
+ "ast",
+ "au",
+ "aud",
+ "av1.mkv",
+ "av1.mp4",
+ "avi",
+ "avif",
+ "avs",
+ "avs2",
+ "avs3",
+ "bit",
+ "bmp",
+ "c2",
+ "caf",
+ "cavs",
+ "chk",
+ "cpk",
+ "cvg",
+ "dfpwm",
+ "dnxhd",
+ "dnxhr",
+ "dpx",
+ "drc",
+ "dts",
+ "dv",
+ "dvd",
+ "eac3",
+ "ec3",
+ "evc",
+ "exr",
+ "f4v",
+ "ffmeta",
+ "fits",
+ "flac",
+ "flm",
+ "flv",
+ "g722",
+ "gif",
+ "gsm",
+ "gxf",
+ "h261",
+ "h263",
+ "h264.mkv",
+ "h264.mp4",
+ "h265.mkv",
+ "h265.mp4",
+ "h266.mkv",
+ "hdr",
+ "hevc",
+ "ico",
+ "im1",
+ "im24",
+ "im8",
+ "ircam",
+ "isma",
+ "ismv",
+ "ivf",
+ "j2c",
+ "j2k",
+ "jls",
+ "jp2",
+ "jpeg",
+ "jpg",
+ "js",
+ "jss",
+ "jxl",
+ "latm",
+ "lbc",
+ "ljpg",
+ "loas",
+ "lrc",
+ "m1v",
+ "m2a",
+ "m2t",
+ "m2ts",
+ "m2v",
+ "m3u8",
+ "m4a",
+ "m4b",
+ "m4v",
+ "mjpeg",
+ "mjpg",
+ "mkv",
+ "mlp",
+ "mmf",
+ "mov",
+ "mp2",
+ "mp3",
+ "mp4",
+ "mpa",
+ "mpd",
+ "mpeg",
+ "mpg",
+ "msbc",
+ "mts",
+ "mxf",
+ "nut",
+ "obu",
+ "oga",
+ "ogg",
+ "ogv",
+ "oma",
+ "opus",
+ "pam",
+ "pbm",
+ "pcm",
+ "pcx",
+ "pfm",
+ "pgm",
+ "pgmyuv",
+ "phm",
+ "pix",
+ "png",
+ "ppm",
+ "psp",
+ "qoi",
+ "ra",
+ "ras",
+ "rco",
+ "rcv",
+ "rgb",
+ "rm",
+ "roq",
+ "rs",
+ "rso",
+ "sb",
+ "sbc",
+ "scc",
+ "sf",
+ "sgi",
+ "sox",
+ "spdif",
+ "spx",
+ "srt",
+ "ssa",
+ "sub",
+ "sun",
+ "sunras",
+ "sup",
+ "sw",
+ "swf",
+ "tco",
+ "tga",
+ "thd",
+ "tif",
+ "tiff",
+ "ts",
+ "tta",
+ "ttml",
+ "tun",
+ "ub",
+ "ul",
+ "uw",
+ "vag",
+ "vbn",
+ "vc1",
+ "vc2",
+ "vob",
+ "voc",
+ "vtt",
+ "vvc",
+ "w64",
+ "wav",
+ "wbmp",
+ "webm",
+ "webp",
+ "wma",
+ "wmv",
+ "wtv",
+ "wv",
+ "xbm",
+ "xface",
+ "xml",
+ "xwd",
+ "y",
+ "y4m",
+ "yuv",
+ ],
+ },
+};
+
+export async function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ let extraArgs: string[] = [];
+ let message = "Done";
+
+ if (convertTo === "ico") {
+ // make sure image is 256x256 or smaller
+ extraArgs = [
+ "-filter:v",
+ "scale='min(256,iw)':min'(256,ih)':force_original_aspect_ratio=decrease",
+ ];
+ message = "Done: resized to 256x256";
+ }
+
+ if (convertTo.split(".").length > 1) {
+ // support av1.mkv and av1.mp4 and h265.mp4 etc.
+ const split = convertTo.split(".");
+ const codec_short = split[0];
+
+ switch (codec_short) {
+ case "av1":
+ extraArgs.push("-c:v", "libaom-av1");
+ break;
+ case "h264":
+ extraArgs.push("-c:v", "libx264");
+ break;
+ case "h265":
+ extraArgs.push("-c:v", "libx265");
+ break;
+ case "h266":
+ extraArgs.push("-c:v", "libx266");
+ break;
+ }
+ }
+
+ // Parse FFMPEG_ARGS environment variable into array
+ const ffmpegArgs = process.env.FFMPEG_ARGS ? process.env.FFMPEG_ARGS.split(/\s+/) : [];
+
+ return new Promise((resolve, reject) => {
+ execFile(
+ "ffmpeg",
+ [...ffmpegArgs, "-i", filePath, ...extraArgs, targetPath],
+ (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve(message);
+ },
+ );
+ });
+}
diff --git a/src/converters/graphicsmagick.ts b/src/converters/graphicsmagick.ts
index 3186668..dbd8996 100644
--- a/src/converters/graphicsmagick.ts
+++ b/src/converters/graphicsmagick.ts
@@ -1,340 +1,336 @@
-import { execFile } from "node:child_process";
-
-export const properties = {
- from: {
- image: [
- "3fr",
- "8bim",
- "8bimtext",
- "8bimwtext",
- "app1",
- "app1jpeg",
- "art",
- "arw",
- "avs",
- "b",
- "bie",
- "bigtiff",
- "bmp",
- "c",
- "cals",
- "caption",
- "cin",
- "cmyk",
- "cmyka",
- "cr2",
- "crw",
- "cur",
- "cut",
- "dcm",
- "dcr",
- "dcx",
- "dng",
- "dpx",
- "epdf",
- "epi",
- "eps",
- "epsf",
- "epsi",
- "ept",
- "ept2",
- "ept3",
- "erf",
- "exif",
- "fax",
- "file",
- "fits",
- "fractal",
- "ftp",
- "g",
- "gif",
- "gif87",
- "gradient",
- "gray",
- "graya",
- "heic",
- "heif",
- "hrz",
- "http",
- "icb",
- "icc",
- "icm",
- "ico",
- "icon",
- "identity",
- "image",
- "iptc",
- "iptctext",
- "iptcwtext",
- "jbg",
- "jbig",
- "jng",
- "jnx",
- "jpeg",
- "jpg",
- "k",
- "k25",
- "kdc",
- "label",
- "m",
- "mac",
- "map",
- "mat",
- "mef",
- "miff",
- "mng",
- "mono",
- "mpc",
- "mrw",
- "msl",
- "mtv",
- "mvg",
- "nef",
- "null",
- "o",
- "orf",
- "otb",
- "p7",
- "pal",
- "palm",
- "pam",
- "pbm",
- "pcd",
- "pcds",
- "pct",
- "pcx",
- "pdb",
- "pdf",
- "pef",
- "pfa",
- "pfb",
- "pgm",
- "picon",
- "pict",
- "pix",
- "plasma",
- "png",
- "png00",
- "png24",
- "png32",
- "png48",
- "png64",
- "png8",
- "pnm",
- "ppm",
- "ps",
- "ptif",
- "pwp",
- "r",
- "raf",
- "ras",
- "rgb",
- "rgba",
- "rla",
- "rle",
- "sct",
- "sfw",
- "sgi",
- "sr2",
- "srf",
- "stegano",
- "sun",
- "svg",
- "svgz",
- "text",
- "tga",
- "tif",
- "tiff",
- "tile",
- "tim",
- "topol",
- "ttf",
- "txt",
- "uyvy",
- "vda",
- "vicar",
- "vid",
- "viff",
- "vst",
- "wbmp",
- "webp",
- "wmf",
- "wpg",
- "x3f",
- "xbm",
- "xc",
- "xcf",
- "xmp",
- "xpm",
- "xv",
- "xwd",
- "y",
- "yuv",
- ],
- },
- to: {
- image: [
- "8bim",
- "8bimtext",
- "8bimwtext",
- "app1",
- "app1jpeg",
- "art",
- "avs",
- "b",
- "bie",
- "bigtiff",
- "bmp",
- "bmp2",
- "bmp3",
- "brf",
- "c",
- "cals",
- "cin",
- "cmyk",
- "cmyka",
- "dcx",
- "dpx",
- "epdf",
- "epi",
- "eps",
- "eps2",
- "eps3",
- "epsf",
- "epsi",
- "ept",
- "ept2",
- "ept3",
- "exif",
- "fax",
- "fits",
- "g",
- "gif",
- "gif87",
- "gray",
- "graya",
- "histogram",
- "html",
- "icb",
- "icc",
- "icm",
- "info",
- "iptc",
- "iptctext",
- "iptcwtext",
- "isobrl",
- "isobrl6",
- "jbg",
- "jbig",
- "jng",
- "jpeg",
- "k",
- "m",
- "m2v",
- "map",
- "mat",
- "matte",
- "miff",
- "mng",
- "mono",
- "mpc",
- "mpeg",
- "mpg",
- "msl",
- "mtv",
- "mvg",
- "null",
- "o",
- "otb",
- "p7",
- "pal",
- "pam",
- "pbm",
- "pcd",
- "pcds",
- "pcl",
- "pct",
- "pcx",
- "pdb",
- "pdf",
- "pgm",
- "picon",
- "pict",
- "png",
- "png00",
- "png24",
- "png32",
- "png48",
- "png64",
- "png8",
- "pnm",
- "ppm",
- "preview",
- "ps",
- "ps2",
- "ps3",
- "ptif",
- "r",
- "ras",
- "rgb",
- "rgba",
- "sgi",
- "shtml",
- "sun",
- "text",
- "tga",
- "tiff",
- "txt",
- "ubrl",
- "ubrl6",
- "uil",
- "uyvy",
- "vda",
- "vicar",
- "vid",
- "viff",
- "vst",
- "wbmp",
- "webp",
- "x",
- "xbm",
- "xmp",
- "xpm",
- "xv",
- "xwd",
- "y",
- "yuv",
- ],
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- return new Promise((resolve, reject) => {
- execFile(
- "gm",
- ["convert", filePath, targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- },
- );
- });
-}
+import { execFile } from "node:child_process";
+
+export const properties = {
+ from: {
+ image: [
+ "3fr",
+ "8bim",
+ "8bimtext",
+ "8bimwtext",
+ "app1",
+ "app1jpeg",
+ "art",
+ "arw",
+ "avs",
+ "b",
+ "bie",
+ "bigtiff",
+ "bmp",
+ "c",
+ "cals",
+ "caption",
+ "cin",
+ "cmyk",
+ "cmyka",
+ "cr2",
+ "crw",
+ "cur",
+ "cut",
+ "dcm",
+ "dcr",
+ "dcx",
+ "dng",
+ "dpx",
+ "epdf",
+ "epi",
+ "eps",
+ "epsf",
+ "epsi",
+ "ept",
+ "ept2",
+ "ept3",
+ "erf",
+ "exif",
+ "fax",
+ "file",
+ "fits",
+ "fractal",
+ "ftp",
+ "g",
+ "gif",
+ "gif87",
+ "gradient",
+ "gray",
+ "graya",
+ "heic",
+ "heif",
+ "hrz",
+ "http",
+ "icb",
+ "icc",
+ "icm",
+ "ico",
+ "icon",
+ "identity",
+ "image",
+ "iptc",
+ "iptctext",
+ "iptcwtext",
+ "jbg",
+ "jbig",
+ "jng",
+ "jnx",
+ "jpeg",
+ "jpg",
+ "k",
+ "k25",
+ "kdc",
+ "label",
+ "m",
+ "mac",
+ "map",
+ "mat",
+ "mef",
+ "miff",
+ "mng",
+ "mono",
+ "mpc",
+ "mrw",
+ "msl",
+ "mtv",
+ "mvg",
+ "nef",
+ "null",
+ "o",
+ "orf",
+ "otb",
+ "p7",
+ "pal",
+ "palm",
+ "pam",
+ "pbm",
+ "pcd",
+ "pcds",
+ "pct",
+ "pcx",
+ "pdb",
+ "pdf",
+ "pef",
+ "pfa",
+ "pfb",
+ "pgm",
+ "picon",
+ "pict",
+ "pix",
+ "plasma",
+ "png",
+ "png00",
+ "png24",
+ "png32",
+ "png48",
+ "png64",
+ "png8",
+ "pnm",
+ "ppm",
+ "ps",
+ "ptif",
+ "pwp",
+ "r",
+ "raf",
+ "ras",
+ "rgb",
+ "rgba",
+ "rla",
+ "rle",
+ "sct",
+ "sfw",
+ "sgi",
+ "sr2",
+ "srf",
+ "stegano",
+ "sun",
+ "svg",
+ "svgz",
+ "text",
+ "tga",
+ "tif",
+ "tiff",
+ "tile",
+ "tim",
+ "topol",
+ "ttf",
+ "txt",
+ "uyvy",
+ "vda",
+ "vicar",
+ "vid",
+ "viff",
+ "vst",
+ "wbmp",
+ "webp",
+ "wmf",
+ "wpg",
+ "x3f",
+ "xbm",
+ "xc",
+ "xcf",
+ "xmp",
+ "xpm",
+ "xv",
+ "xwd",
+ "y",
+ "yuv",
+ ],
+ },
+ to: {
+ image: [
+ "8bim",
+ "8bimtext",
+ "8bimwtext",
+ "app1",
+ "app1jpeg",
+ "art",
+ "avs",
+ "b",
+ "bie",
+ "bigtiff",
+ "bmp",
+ "bmp2",
+ "bmp3",
+ "brf",
+ "c",
+ "cals",
+ "cin",
+ "cmyk",
+ "cmyka",
+ "dcx",
+ "dpx",
+ "epdf",
+ "epi",
+ "eps",
+ "eps2",
+ "eps3",
+ "epsf",
+ "epsi",
+ "ept",
+ "ept2",
+ "ept3",
+ "exif",
+ "fax",
+ "fits",
+ "g",
+ "gif",
+ "gif87",
+ "gray",
+ "graya",
+ "histogram",
+ "html",
+ "icb",
+ "icc",
+ "icm",
+ "info",
+ "iptc",
+ "iptctext",
+ "iptcwtext",
+ "isobrl",
+ "isobrl6",
+ "jbg",
+ "jbig",
+ "jng",
+ "jpeg",
+ "k",
+ "m",
+ "m2v",
+ "map",
+ "mat",
+ "matte",
+ "miff",
+ "mng",
+ "mono",
+ "mpc",
+ "mpeg",
+ "mpg",
+ "msl",
+ "mtv",
+ "mvg",
+ "null",
+ "o",
+ "otb",
+ "p7",
+ "pal",
+ "pam",
+ "pbm",
+ "pcd",
+ "pcds",
+ "pcl",
+ "pct",
+ "pcx",
+ "pdb",
+ "pdf",
+ "pgm",
+ "picon",
+ "pict",
+ "png",
+ "png00",
+ "png24",
+ "png32",
+ "png48",
+ "png64",
+ "png8",
+ "pnm",
+ "ppm",
+ "preview",
+ "ps",
+ "ps2",
+ "ps3",
+ "ptif",
+ "r",
+ "ras",
+ "rgb",
+ "rgba",
+ "sgi",
+ "shtml",
+ "sun",
+ "text",
+ "tga",
+ "tiff",
+ "txt",
+ "ubrl",
+ "ubrl6",
+ "uil",
+ "uyvy",
+ "vda",
+ "vicar",
+ "vid",
+ "viff",
+ "vst",
+ "wbmp",
+ "webp",
+ "x",
+ "xbm",
+ "xmp",
+ "xpm",
+ "xv",
+ "xwd",
+ "y",
+ "yuv",
+ ],
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ return new Promise((resolve, reject) => {
+ execFile("gm", ["convert", filePath, targetPath], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/imagemagick.ts b/src/converters/imagemagick.ts
index f4fc234..4122a24 100644
--- a/src/converters/imagemagick.ts
+++ b/src/converters/imagemagick.ts
@@ -452,12 +452,7 @@ export function convert(
let inputArgs: string[] = [];
if (convertTo === "ico") {
- outputArgs = [
- "-define",
- "icon:auto-resize=256,128,64,48,32,16",
- "-background",
- "none",
- ];
+ outputArgs = ["-define", "icon:auto-resize=256,128,64,48,32,16", "-background", "none"];
if (fileType === "svg") {
// this might be a bit too much, but it works
diff --git a/src/converters/inkscape.ts b/src/converters/inkscape.ts
index 7af7163..9e13fb0 100644
--- a/src/converters/inkscape.ts
+++ b/src/converters/inkscape.ts
@@ -36,24 +36,20 @@ export function convert(
options?: unknown,
): Promise {
return new Promise((resolve, reject) => {
- execFile(
- "inkscape",
- [filePath, "-o", targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
+ execFile("inkscape", [filePath, "-o", 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("Done");
- },
- );
+ resolve("Done");
+ });
});
}
diff --git a/src/converters/libheif.ts b/src/converters/libheif.ts
index 4935683..38ac949 100644
--- a/src/converters/libheif.ts
+++ b/src/converters/libheif.ts
@@ -2,19 +2,7 @@ import { execFile } from "child_process";
export const properties = {
from: {
- images: [
- "avci",
- "avcs",
- "avif",
- "h264",
- "heic",
- "heics",
- "heif",
- "heifs",
- "hif",
- "mkv",
- "mp4",
- ],
+ images: ["avci", "avcs", "avif", "h264", "heic", "heics", "heif", "heifs", "hif", "mkv", "mp4"],
},
to: {
images: ["jpeg", "png", "y4m"],
@@ -30,24 +18,20 @@ export function convert(
options?: unknown,
): Promise {
return new Promise((resolve, reject) => {
- execFile(
- "heif-convert",
- [filePath, targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
+ execFile("heif-convert", [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("Done");
- },
- );
+ resolve("Done");
+ });
});
}
diff --git a/src/converters/libjxl.ts b/src/converters/libjxl.ts
index d08d6fd..0ef11a8 100644
--- a/src/converters/libjxl.ts
+++ b/src/converters/libjxl.ts
@@ -1,71 +1,49 @@
-import { execFile } from "node:child_process";
-
-// declare possible conversions
-export const properties = {
- from: {
- jxl: ["jxl"],
- images: [
- "apng",
- "exr",
- "gif",
- "jpeg",
- "pam",
- "pfm",
- "pgm",
- "pgx",
- "png",
- "ppm",
- ],
- },
- to: {
- jxl: [
- "apng",
- "exr",
- "gif",
- "jpeg",
- "pam",
- "pfm",
- "pgm",
- "pgx",
- "png",
- "ppm",
- ],
- images: ["jxl"],
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- let tool = "";
- if (fileType === "jxl") {
- tool = "djxl";
- }
-
- if (convertTo === "jxl") {
- tool = "cjxl";
- }
-
- return new Promise((resolve, reject) => {
- execFile(tool, [filePath, targetPath], (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- });
- });
-}
+import { execFile } from "node:child_process";
+
+// declare possible conversions
+export const properties = {
+ from: {
+ jxl: ["jxl"],
+ images: ["apng", "exr", "gif", "jpeg", "pam", "pfm", "pgm", "pgx", "png", "ppm"],
+ },
+ to: {
+ jxl: ["apng", "exr", "gif", "jpeg", "pam", "pfm", "pgm", "pgx", "png", "ppm"],
+ images: ["jxl"],
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ let tool = "";
+ if (fileType === "jxl") {
+ tool = "djxl";
+ }
+
+ if (convertTo === "jxl") {
+ tool = "cjxl";
+ }
+
+ return new Promise((resolve, reject) => {
+ execFile(tool, [filePath, targetPath], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/main.ts b/src/converters/main.ts
index 3d89e6a..a9f2e42 100644
--- a/src/converters/main.ts
+++ b/src/converters/main.ts
@@ -1,19 +1,21 @@
import { normalizeFiletype } from "../helpers/normalizeFiletype";
import { convert as convertassimp, properties as propertiesassimp } from "./assimp";
+import { convert as convertCalibre, properties as propertiesCalibre } from "./calibre";
+import { convert as convertDvisvgm, properties as propertiesDvisvgm } from "./dvisvgm";
import { convert as convertFFmpeg, properties as propertiesFFmpeg } from "./ffmpeg";
-import { convert as convertGraphicsmagick, properties as propertiesGraphicsmagick } from "./graphicsmagick";
+import {
+ convert as convertGraphicsmagick,
+ properties as propertiesGraphicsmagick,
+} from "./graphicsmagick";
+import { convert as convertImagemagick, properties as propertiesImagemagick } from "./imagemagick";
import { convert as convertInkscape, properties as propertiesInkscape } from "./inkscape";
+import { convert as convertLibheif, properties as propertiesLibheif } from "./libheif";
import { convert as convertLibjxl, properties as propertiesLibjxl } from "./libjxl";
import { convert as convertPandoc, properties as propertiesPandoc } from "./pandoc";
+import { convert as convertPotrace, properties as propertiesPotrace } from "./potrace";
import { convert as convertresvg, properties as propertiesresvg } from "./resvg";
import { convert as convertImage, properties as propertiesImage } from "./vips";
import { convert as convertxelatex, properties as propertiesxelatex } from "./xelatex";
-import { convert as convertCalibre, properties as propertiesCalibre } from "./calibre";
-import { convert as convertLibheif, properties as propertiesLibheif } from "./libheif";
-import { convert as convertPotrace, properties as propertiesPotrace } from "./potrace";
-import { convert as convertImagemagick, properties as propertiesImagemagick } from "./imagemagick";
-import { convert as convertDvisvgm, properties as propertiesDvisvgm } from "./dvisvgm";
-
// This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular
@@ -113,7 +115,7 @@ export async function mainConverter(
) {
const fileType = normalizeFiletype(fileTypeOriginal);
- let converterFunc: typeof properties["libjxl"]["converter"] | undefined;
+ let converterFunc: (typeof properties)["libjxl"]["converter"] | undefined;
if (converterName) {
converterFunc = properties[converterName]?.converter;
@@ -139,20 +141,12 @@ export async function mainConverter(
}
if (!converterFunc) {
- console.log(
- `No available converter supports converting from ${fileType} to ${convertTo}.`,
- );
+ console.log(`No available converter supports converting from ${fileType} to ${convertTo}.`);
return "File type not supported";
}
try {
- const result = await converterFunc(
- inputFilePath,
- fileType,
- convertTo,
- targetPath,
- options,
- );
+ const result = await converterFunc(inputFilePath, fileType, convertTo, targetPath, options);
console.log(
`Converted ${inputFilePath} from ${fileType} to ${convertTo} successfully using ${converterName}.`,
@@ -192,8 +186,7 @@ for (const converterName in properties) {
possibleTargets[extension] = {};
}
- possibleTargets[extension][converterName] =
- converterProperties.to[key] || [];
+ possibleTargets[extension][converterName] = converterProperties.to[key] || [];
}
}
}
@@ -294,4 +287,4 @@ export const getAllInputs = (converter: string) => {
// }
// // print the number of unique Inputs and Outputs
-// console.log(`Unique Formats: ${uniqueFormats.size}`);
\ No newline at end of file
+// console.log(`Unique Formats: ${uniqueFormats.size}`);
diff --git a/src/converters/pandoc.ts b/src/converters/pandoc.ts
index a3995fa..6aab79d 100644
--- a/src/converters/pandoc.ts
+++ b/src/converters/pandoc.ts
@@ -1,162 +1,162 @@
-import { execFile } from "node:child_process";
-
-export const properties = {
- from: {
- text: [
- "textile",
- "tikiwiki",
- "tsv",
- "twiki",
- "typst",
- "vimwiki",
- "biblatex",
- "bibtex",
- "bits",
- "commonmark",
- "commonmark_x",
- "creole",
- "csljson",
- "csv",
- "djot",
- "docbook",
- "docx",
- "dokuwiki",
- "endnotexml",
- "epub",
- "fb2",
- "gfm",
- "haddock",
- "html",
- "ipynb",
- "jats",
- "jira",
- "json",
- "latex",
- "man",
- "markdown",
- "markdown_mmd",
- "markdown_phpextra",
- "markdown_strict",
- "mediawiki",
- "muse",
- "pandoc native",
- "opml",
- "org",
- "ris",
- "rst",
- "rtf",
- "t2t",
- ],
- },
- to: {
- text: [
- "tei",
- "texinfo",
- "textile",
- "typst",
- "xwiki",
- "zimwiki",
- "asciidoc",
- "asciidoc_legacy",
- "asciidoctor",
- "beamer",
- "biblatex",
- "bibtex",
- "chunkedhtml",
- "commonmark",
- "commonmark_x",
- "context",
- "csljson",
- "djot",
- "docbook",
- "docbook4",
- "docbook5",
- "docx",
- "dokuwiki",
- "dzslides",
- "epub",
- "epub2",
- "epub3",
- "fb2",
- "gfm",
- "haddock",
- "html",
- "html4",
- "html5",
- "icml",
- "ipynb",
- "jats",
- "jats_archiving",
- "jats_articleauthoring",
- "jats_publishing",
- "jira",
- "json",
- "latex",
- "man",
- "markdown",
- "markdown_mmd",
- "markdown_phpextra",
- "markdown_strict",
- "markua",
- "mediawiki",
- "ms",
- "muse",
- "pandoc native",
- "odt",
- "opendocument",
- "opml",
- "org",
- "pdf",
- "plain",
- "pptx",
- "revealjs",
- "rst",
- "rtf",
- "s5",
- "slideous",
- "slidy",
- ],
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- // set xelatex here
- const xelatex = ["pdf", "latex"];
-
- // Build arguments array
- const args: string[] = [];
-
- if (xelatex.includes(convertTo)) {
- args.push("--pdf-engine=xelatex");
- }
-
- args.push(filePath);
- args.push("-f", fileType);
- args.push("-t", convertTo);
- args.push("-o", targetPath);
-
- return new Promise((resolve, reject) => {
- execFile("pandoc", args, (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- });
- });
-}
+import { execFile } from "node:child_process";
+
+export const properties = {
+ from: {
+ text: [
+ "textile",
+ "tikiwiki",
+ "tsv",
+ "twiki",
+ "typst",
+ "vimwiki",
+ "biblatex",
+ "bibtex",
+ "bits",
+ "commonmark",
+ "commonmark_x",
+ "creole",
+ "csljson",
+ "csv",
+ "djot",
+ "docbook",
+ "docx",
+ "dokuwiki",
+ "endnotexml",
+ "epub",
+ "fb2",
+ "gfm",
+ "haddock",
+ "html",
+ "ipynb",
+ "jats",
+ "jira",
+ "json",
+ "latex",
+ "man",
+ "markdown",
+ "markdown_mmd",
+ "markdown_phpextra",
+ "markdown_strict",
+ "mediawiki",
+ "muse",
+ "pandoc native",
+ "opml",
+ "org",
+ "ris",
+ "rst",
+ "rtf",
+ "t2t",
+ ],
+ },
+ to: {
+ text: [
+ "tei",
+ "texinfo",
+ "textile",
+ "typst",
+ "xwiki",
+ "zimwiki",
+ "asciidoc",
+ "asciidoc_legacy",
+ "asciidoctor",
+ "beamer",
+ "biblatex",
+ "bibtex",
+ "chunkedhtml",
+ "commonmark",
+ "commonmark_x",
+ "context",
+ "csljson",
+ "djot",
+ "docbook",
+ "docbook4",
+ "docbook5",
+ "docx",
+ "dokuwiki",
+ "dzslides",
+ "epub",
+ "epub2",
+ "epub3",
+ "fb2",
+ "gfm",
+ "haddock",
+ "html",
+ "html4",
+ "html5",
+ "icml",
+ "ipynb",
+ "jats",
+ "jats_archiving",
+ "jats_articleauthoring",
+ "jats_publishing",
+ "jira",
+ "json",
+ "latex",
+ "man",
+ "markdown",
+ "markdown_mmd",
+ "markdown_phpextra",
+ "markdown_strict",
+ "markua",
+ "mediawiki",
+ "ms",
+ "muse",
+ "pandoc native",
+ "odt",
+ "opendocument",
+ "opml",
+ "org",
+ "pdf",
+ "plain",
+ "pptx",
+ "revealjs",
+ "rst",
+ "rtf",
+ "s5",
+ "slideous",
+ "slidy",
+ ],
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ // set xelatex here
+ const xelatex = ["pdf", "latex"];
+
+ // Build arguments array
+ const args: string[] = [];
+
+ if (xelatex.includes(convertTo)) {
+ args.push("--pdf-engine=xelatex");
+ }
+
+ args.push(filePath);
+ args.push("-f", fileType);
+ args.push("-t", convertTo);
+ args.push("-o", targetPath);
+
+ return new Promise((resolve, reject) => {
+ execFile("pandoc", args, (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/potrace.ts b/src/converters/potrace.ts
index 0c145a7..cdf09cc 100644
--- a/src/converters/potrace.ts
+++ b/src/converters/potrace.ts
@@ -5,33 +5,45 @@ export const properties = {
images: ["pnm", "pbm", "pgm", "bmp"],
},
to: {
- images: ["svg", "pdf", "pdfpage", "eps", "postscript", "ps", "dxf", "geojson", "pgm", "gimppath", "xfig"],
+ images: [
+ "svg",
+ "pdf",
+ "pdfpage",
+ "eps",
+ "postscript",
+ "ps",
+ "dxf",
+ "geojson",
+ "pgm",
+ "gimppath",
+ "xfig",
+ ],
},
};
export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
- ): Promise {
- return new Promise((resolve, reject) => {
- execFile("potrace", [filePath, "-o", targetPath, "-b", convertTo], (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- });
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ return new Promise((resolve, reject) => {
+ execFile("potrace", [filePath, "-o", targetPath, "-b", convertTo], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
});
- }
\ No newline at end of file
+ });
+}
diff --git a/src/converters/resvg.ts b/src/converters/resvg.ts
index 9ea3745..1e409cb 100644
--- a/src/converters/resvg.ts
+++ b/src/converters/resvg.ts
@@ -1,37 +1,37 @@
-import { execFile } from "node:child_process";
-
-export const properties = {
- from: {
- images: ["svg"],
- },
- to: {
- images: ["png"],
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- return new Promise((resolve, reject) => {
- execFile("resvg", [filePath, targetPath], (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- });
- });
-}
+import { execFile } from "node:child_process";
+
+export const properties = {
+ from: {
+ images: ["svg"],
+ },
+ to: {
+ images: ["png"],
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ return new Promise((resolve, reject) => {
+ execFile("resvg", [filePath, targetPath], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/vips.ts b/src/converters/vips.ts
index 6781359..6451cda 100644
--- a/src/converters/vips.ts
+++ b/src/converters/vips.ts
@@ -1,142 +1,138 @@
-import { execFile } from "node:child_process";
-
-// declare possible conversions
-export const properties = {
- from: {
- images: [
- "avif",
- "bif",
- "csv",
- "exr",
- "fits",
- "gif",
- "hdr.gz",
- "hdr",
- "heic",
- "heif",
- "img.gz",
- "img",
- "j2c",
- "j2k",
- "jp2",
- "jpeg",
- "jpx",
- "jxl",
- "mat",
- "mrxs",
- "ndpi",
- "nia.gz",
- "nia",
- "nii.gz",
- "nii",
- "pdf",
- "pfm",
- "pgm",
- "pic",
- "png",
- "ppm",
- "raw",
- "scn",
- "svg",
- "svs",
- "svslide",
- "szi",
- "tif",
- "tiff",
- "v",
- "vips",
- "vms",
- "vmu",
- "webp",
- "zip",
- ],
- },
- to: {
- images: [
- "avif",
- "dzi",
- "fits",
- "gif",
- "hdr.gz",
- "heic",
- "heif",
- "img.gz",
- "j2c",
- "j2k",
- "jp2",
- "jpeg",
- "jpx",
- "jxl",
- "mat",
- "nia.gz",
- "nia",
- "nii.gz",
- "nii",
- "png",
- "tiff",
- "vips",
- "webp",
- ],
- },
- options: {
- svg: {
- scale: {
- description: "Scale the image up or down",
- type: "number",
- default: 1,
- },
- },
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- // if (fileType === "svg") {
- // const scale = options.scale || 1;
- // const metadata = await sharp(filePath).metadata();
-
- // if (!metadata || !metadata.width || !metadata.height) {
- // throw new Error("Could not get metadata from image");
- // }
-
- // const newWidth = Math.round(metadata.width * scale);
- // const newHeight = Math.round(metadata.height * scale);
-
- // return await sharp(filePath)
- // .resize(newWidth, newHeight)
- // .toFormat(convertTo)
- // .toFile(targetPath);
- // }
- let action = "copy";
- if (fileType === "pdf") {
- action = "pdfload";
- }
-
- return new Promise((resolve, reject) => {
- execFile(
- "vips",
- [action, filePath, targetPath],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- },
- );
- });
-}
+import { execFile } from "node:child_process";
+
+// declare possible conversions
+export const properties = {
+ from: {
+ images: [
+ "avif",
+ "bif",
+ "csv",
+ "exr",
+ "fits",
+ "gif",
+ "hdr.gz",
+ "hdr",
+ "heic",
+ "heif",
+ "img.gz",
+ "img",
+ "j2c",
+ "j2k",
+ "jp2",
+ "jpeg",
+ "jpx",
+ "jxl",
+ "mat",
+ "mrxs",
+ "ndpi",
+ "nia.gz",
+ "nia",
+ "nii.gz",
+ "nii",
+ "pdf",
+ "pfm",
+ "pgm",
+ "pic",
+ "png",
+ "ppm",
+ "raw",
+ "scn",
+ "svg",
+ "svs",
+ "svslide",
+ "szi",
+ "tif",
+ "tiff",
+ "v",
+ "vips",
+ "vms",
+ "vmu",
+ "webp",
+ "zip",
+ ],
+ },
+ to: {
+ images: [
+ "avif",
+ "dzi",
+ "fits",
+ "gif",
+ "hdr.gz",
+ "heic",
+ "heif",
+ "img.gz",
+ "j2c",
+ "j2k",
+ "jp2",
+ "jpeg",
+ "jpx",
+ "jxl",
+ "mat",
+ "nia.gz",
+ "nia",
+ "nii.gz",
+ "nii",
+ "png",
+ "tiff",
+ "vips",
+ "webp",
+ ],
+ },
+ options: {
+ svg: {
+ scale: {
+ description: "Scale the image up or down",
+ type: "number",
+ default: 1,
+ },
+ },
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ // if (fileType === "svg") {
+ // const scale = options.scale || 1;
+ // const metadata = await sharp(filePath).metadata();
+
+ // if (!metadata || !metadata.width || !metadata.height) {
+ // throw new Error("Could not get metadata from image");
+ // }
+
+ // const newWidth = Math.round(metadata.width * scale);
+ // const newHeight = Math.round(metadata.height * scale);
+
+ // return await sharp(filePath)
+ // .resize(newWidth, newHeight)
+ // .toFormat(convertTo)
+ // .toFile(targetPath);
+ // }
+ let action = "copy";
+ if (fileType === "pdf") {
+ action = "pdfload";
+ }
+
+ return new Promise((resolve, reject) => {
+ execFile("vips", [action, filePath, targetPath], (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ });
+ });
+}
diff --git a/src/converters/xelatex.ts b/src/converters/xelatex.ts
index 905202c..5b29356 100644
--- a/src/converters/xelatex.ts
+++ b/src/converters/xelatex.ts
@@ -1,53 +1,44 @@
-import { execFile } from "node:child_process";
-
-export const properties = {
- from: {
- text: ["tex", "latex"],
- },
- to: {
- text: ["pdf"],
- },
-};
-
-export function convert(
- filePath: string,
- fileType: string,
- convertTo: string,
- targetPath: string,
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- options?: unknown,
-): Promise {
- return new Promise((resolve, reject) => {
- // const fileName: string = (targetPath.split("/").pop() as string).replace(".pdf", "")
- const outputPath = targetPath
- .split("/")
- .slice(0, -1)
- .join("/")
- .replace("./", "");
-
- execFile(
- "latexmk",
- [
- "-xelatex",
- "-interaction=nonstopmode",
- `-output-directory=${outputPath}`,
- filePath,
- ],
- (error, stdout, stderr) => {
- if (error) {
- reject(`error: ${error}`);
- }
-
- if (stdout) {
- console.log(`stdout: ${stdout}`);
- }
-
- if (stderr) {
- console.error(`stderr: ${stderr}`);
- }
-
- resolve("Done");
- },
- );
- });
-}
+import { execFile } from "node:child_process";
+
+export const properties = {
+ from: {
+ text: ["tex", "latex"],
+ },
+ to: {
+ text: ["pdf"],
+ },
+};
+
+export function convert(
+ filePath: string,
+ fileType: string,
+ convertTo: string,
+ targetPath: string,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ options?: unknown,
+): Promise {
+ return new Promise((resolve, reject) => {
+ // const fileName: string = (targetPath.split("/").pop() as string).replace(".pdf", "")
+ const outputPath = targetPath.split("/").slice(0, -1).join("/").replace("./", "");
+
+ execFile(
+ "latexmk",
+ ["-xelatex", "-interaction=nonstopmode", `-output-directory=${outputPath}`, filePath],
+ (error, stdout, stderr) => {
+ if (error) {
+ reject(`error: ${error}`);
+ }
+
+ if (stdout) {
+ console.log(`stdout: ${stdout}`);
+ }
+
+ if (stderr) {
+ console.error(`stderr: ${stderr}`);
+ }
+
+ resolve("Done");
+ },
+ );
+ });
+}
diff --git a/src/db/db.ts b/src/db/db.ts
index 641a3f7..1193d5d 100644
--- a/src/db/db.ts
+++ b/src/db/db.ts
@@ -1,4 +1,5 @@
import { Database } from "bun:sqlite";
+
const db = new Database("./data/mydb.sqlite", { create: true });
if (!db.query("SELECT * FROM sqlite_master WHERE type='table'").get()) {
@@ -27,13 +28,9 @@ CREATE TABLE IF NOT EXISTS jobs (
PRAGMA user_version = 1;`);
}
-const dbVersion = (
- db.query("PRAGMA user_version").get() as { user_version?: number }
-).user_version;
+const dbVersion = (db.query("PRAGMA user_version").get() as { user_version?: number }).user_version;
if (dbVersion === 0) {
- db.exec(
- "ALTER TABLE file_names ADD COLUMN status TEXT DEFAULT 'not started';",
- );
+ db.exec("ALTER TABLE file_names ADD COLUMN status TEXT DEFAULT 'not started';");
db.exec("PRAGMA user_version = 1;");
console.log("Updated database to version 1.");
}
@@ -41,4 +38,4 @@ if (dbVersion === 0) {
// enable WAL mode
db.exec("PRAGMA journal_mode = WAL;");
-export default db;
\ No newline at end of file
+export default db;
diff --git a/src/db/types.ts b/src/db/types.ts
index 146a1b1..4825711 100644
--- a/src/db/types.ts
+++ b/src/db/types.ts
@@ -20,4 +20,4 @@ export class User {
id!: number;
email!: string;
password!: string;
-}
\ No newline at end of file
+}
diff --git a/src/helpers/env.ts b/src/helpers/env.ts
index 68b1c34..d00843f 100644
--- a/src/helpers/env.ts
+++ b/src/helpers/env.ts
@@ -1,8 +1,7 @@
export const ACCOUNT_REGISTRATION =
process.env.ACCOUNT_REGISTRATION?.toLowerCase() === "true" || false;
-export const HTTP_ALLOWED =
- process.env.HTTP_ALLOWED?.toLowerCase() === "true" || false;
+export const HTTP_ALLOWED = process.env.HTTP_ALLOWED?.toLowerCase() === "true" || false;
export const ALLOW_UNAUTHENTICATED =
process.env.ALLOW_UNAUTHENTICATED?.toLowerCase() === "true" || false;
@@ -11,7 +10,6 @@ export const AUTO_DELETE_EVERY_N_HOURS = process.env.AUTO_DELETE_EVERY_N_HOURS
? Number(process.env.AUTO_DELETE_EVERY_N_HOURS)
: 24;
-export const HIDE_HISTORY =
- process.env.HIDE_HISTORY?.toLowerCase() === "true" || false;
+export const HIDE_HISTORY = process.env.HIDE_HISTORY?.toLowerCase() === "true" || false;
export const WEBROOT = process.env.WEBROOT ?? "";
diff --git a/src/helpers/normalizeFiletype.ts b/src/helpers/normalizeFiletype.ts
index f6aba73..cf9389a 100644
--- a/src/helpers/normalizeFiletype.ts
+++ b/src/helpers/normalizeFiletype.ts
@@ -1,37 +1,37 @@
-export const normalizeFiletype = (filetype: string): string => {
- const lowercaseFiletype = filetype.toLowerCase();
-
- switch (lowercaseFiletype) {
- case "jfif":
- case "jpg":
- return "jpeg";
- case "htm":
- return "html";
- case "tex":
- return "latex";
- case "md":
- return "markdown";
- case "unknown":
- return "m4a";
- default:
- return lowercaseFiletype;
- }
-};
-
-export const normalizeOutputFiletype = (filetype: string): string => {
- const lowercaseFiletype = filetype.toLowerCase();
-
- switch (lowercaseFiletype) {
- case "jpeg":
- return "jpg";
- case "latex":
- return "tex";
- case "markdown_phpextra":
- case "markdown_strict":
- case "markdown_mmd":
- case "markdown":
- return "md";
- default:
- return lowercaseFiletype;
- }
-};
+export const normalizeFiletype = (filetype: string): string => {
+ const lowercaseFiletype = filetype.toLowerCase();
+
+ switch (lowercaseFiletype) {
+ case "jfif":
+ case "jpg":
+ return "jpeg";
+ case "htm":
+ return "html";
+ case "tex":
+ return "latex";
+ case "md":
+ return "markdown";
+ case "unknown":
+ return "m4a";
+ default:
+ return lowercaseFiletype;
+ }
+};
+
+export const normalizeOutputFiletype = (filetype: string): string => {
+ const lowercaseFiletype = filetype.toLowerCase();
+
+ switch (lowercaseFiletype) {
+ case "jpeg":
+ return "jpg";
+ case "latex":
+ return "tex";
+ case "markdown_phpextra":
+ case "markdown_strict":
+ case "markdown_mmd":
+ case "markdown":
+ return "md";
+ default:
+ return lowercaseFiletype;
+ }
+};
diff --git a/src/index.tsx b/src/index.tsx
index a801b84..b95b4b8 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -2,22 +2,21 @@ import { rmSync } from "node:fs";
import { mkdir } from "node:fs/promises";
import { html } from "@elysiajs/html";
import { staticPlugin } from "@elysiajs/static";
-
import { Elysia } from "elysia";
import "./helpers/printVersions";
-import { AUTO_DELETE_EVERY_N_HOURS, WEBROOT } from "./helpers/env";
-import { user } from "./pages/user";
-import { root } from "./pages/root"
-import { upload } from "./pages/upload"
-import { history } from "./pages/history";
-import { convert } from "./pages/convert"
-import { download } from "./pages/download"
-import { results } from "./pages/results";
-import { deleteFile } from "./pages/deleteFile";
-import { listConverters } from "./pages/listConverters";
-import { chooseConverter } from "./pages/chooseConverter";
import db from "./db/db";
import { Jobs } from "./db/types";
+import { AUTO_DELETE_EVERY_N_HOURS, WEBROOT } from "./helpers/env";
+import { chooseConverter } from "./pages/chooseConverter";
+import { convert } from "./pages/convert";
+import { deleteFile } from "./pages/deleteFile";
+import { download } from "./pages/download";
+import { history } from "./pages/history";
+import { listConverters } from "./pages/listConverters";
+import { results } from "./pages/results";
+import { root } from "./pages/root";
+import { upload } from "./pages/upload";
+import { user } from "./pages/user";
mkdir("./data", { recursive: true }).catch(console.error);
@@ -64,19 +63,13 @@ if (process.env.NODE_ENV !== "production") {
app.listen(3000);
-console.log(
- `🦊 Elysia is running at http://${app.server?.hostname}:${app.server?.port}${WEBROOT}`,
-);
+console.log(`🦊 Elysia is running at http://${app.server?.hostname}:${app.server?.port}${WEBROOT}`);
const clearJobs = () => {
const jobs = db
.query("SELECT * FROM jobs WHERE date_created < ?")
.as(Jobs)
- .all(
- new Date(
- Date.now() - AUTO_DELETE_EVERY_N_HOURS * 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
diff --git a/src/pages/chooseConverter.tsx b/src/pages/chooseConverter.tsx
index bbe067c..9557fb9 100644
--- a/src/pages/chooseConverter.tsx
+++ b/src/pages/chooseConverter.tsx
@@ -1,75 +1,67 @@
-import Elysia, { t } from "elysia";
-import { userService } from "./user";
import { Html } from "@elysiajs/html";
-import {
- getPossibleTargets,
-} from "../converters/main";
+import Elysia, { t } from "elysia";
+import { getPossibleTargets } from "../converters/main";
+import { userService } from "./user";
-export const chooseConverter = new Elysia()
- .use(userService)
- .post(
- "/conversions",
- ({ body }) => {
- return (
- <>
-
- {Object.entries(getPossibleTargets(body.fileType)).map(
- ([converter, targets]) => (
-
-
-
- {targets.map((target) => (
-
- ))}
-
-
- ),
- )}
-
+export const chooseConverter = new Elysia().use(userService).post(
+ "/conversions",
+ ({ body }) => {
+ return (
+ <>
+
+ {Object.entries(getPossibleTargets(body.fileType)).map(([converter, targets]) => (
+
+
+
+ {targets.map((target) => (
+
+ ))}
+
+
+ ))}
+
-
- >
- );
- },
- { body: t.Object({ fileType: t.String() }) },
- )
\ No newline at end of file
+
+ >
+ );
+ },
+ { body: t.Object({ fileType: t.String() }) },
+);
diff --git a/src/pages/convert.tsx b/src/pages/convert.tsx
index 9f8835e..a95302c 100644
--- a/src/pages/convert.tsx
+++ b/src/pages/convert.tsx
@@ -3,14 +3,11 @@ import { Elysia, t } from "elysia";
import sanitize from "sanitize-filename";
import { outputDir, uploadsDir } from "..";
import { mainConverter } from "../converters/main";
-import { WEBROOT } from "../helpers/env";
import db from "../db/db";
-import {
- normalizeFiletype,
- normalizeOutputFiletype,
-} from "../helpers/normalizeFiletype";
-import { userService } from "./user";
import { Jobs } from "../db/types";
+import { WEBROOT } from "../helpers/env";
+import { normalizeFiletype, normalizeOutputFiletype } from "../helpers/normalizeFiletype";
+import { userService } from "./user";
export const convert = new Elysia().use(userService).post(
"/convert",
@@ -44,10 +41,7 @@ export const convert = new Elysia().use(userService).post(
try {
await mkdir(userOutputDir, { recursive: true });
} catch (error) {
- console.error(
- `Failed to create the output directory: ${userOutputDir}.`,
- error,
- );
+ console.error(`Failed to create the output directory: ${userOutputDir}.`, error);
}
const convertTo = normalizeFiletype(body.convert_to.split(",")[0] ?? "");
@@ -62,9 +56,10 @@ export const convert = new Elysia().use(userService).post(
return redirect(`${WEBROOT}/`, 302);
}
- db.query(
- "UPDATE jobs SET num_files = ?1, status = 'pending' WHERE id = ?2",
- ).run(fileNames.length, jobId.value);
+ db.query("UPDATE jobs SET num_files = ?1, status = 'pending' WHERE id = ?2").run(
+ fileNames.length,
+ jobId.value,
+ );
const query = db.query(
"INSERT INTO file_names (job_id, file_name, output_file_name, status) VALUES (?1, ?2, ?3, ?4)",
@@ -99,9 +94,7 @@ export const convert = new Elysia().use(userService).post(
.then(() => {
// All conversions are done, update the job status to 'completed'
if (jobId.value) {
- db.query("UPDATE jobs SET status = 'completed' WHERE id = ?1").run(
- jobId.value,
- );
+ db.query("UPDATE jobs SET status = 'completed' WHERE id = ?1").run(jobId.value);
}
// delete all uploaded files in userUploadsDir
diff --git a/src/pages/deleteFile.tsx b/src/pages/deleteFile.tsx
index ef8b719..665d802 100644
--- a/src/pages/deleteFile.tsx
+++ b/src/pages/deleteFile.tsx
@@ -1,39 +1,41 @@
-import { Elysia, t } from "elysia";
-import { userService } from "./user";
import { unlink } from "node:fs/promises";
-import { WEBROOT } from "../helpers/env";
+import { Elysia, t } from "elysia";
import { uploadsDir } from "..";
import db from "../db/db";
+import { WEBROOT } from "../helpers/env";
+import { userService } from "./user";
-export const deleteFile = new Elysia()
- .use(userService)
- .post(
- "/delete",
- async ({ body, redirect, jwt, cookie: { auth, jobId } }) => {
- if (!auth?.value) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+export const deleteFile = new Elysia().use(userService).post(
+ "/delete",
+ async ({ body, redirect, jwt, cookie: { auth, jobId } }) => {
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const user = await jwt.verify(auth.value);
- if (!user) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- if (!jobId?.value) {
- return redirect(`${WEBROOT}/`, 302);
- }
+ if (!jobId?.value) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
- const existingJob = await db
- .query("SELECT * FROM jobs WHERE id = ? AND user_id = ?")
- .get(jobId.value, user.id);
+ const existingJob = await db
+ .query("SELECT * FROM jobs WHERE id = ? AND user_id = ?")
+ .get(jobId.value, user.id);
- if (!existingJob) {
- return redirect(`${WEBROOT}/`, 302);
- }
+ if (!existingJob) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
- const userUploadsDir = `${uploadsDir}${user.id}/${jobId.value}/`;
+ const userUploadsDir = `${uploadsDir}${user.id}/${jobId.value}/`;
- await unlink(`${userUploadsDir}${body.filename}`);
- },
- { body: t.Object({ filename: t.String() }) },
- )
\ No newline at end of file
+ await unlink(`${userUploadsDir}${body.filename}`);
+
+ return {
+ message: "File deleted successfully.",
+ };
+ },
+ { body: t.Object({ filename: t.String() }) },
+);
diff --git a/src/pages/download.tsx b/src/pages/download.tsx
index f5517e8..917ee39 100644
--- a/src/pages/download.tsx
+++ b/src/pages/download.tsx
@@ -1,10 +1,9 @@
-
import { Elysia } from "elysia";
-import { userService } from "./user";
-import { WEBROOT } from "../helpers/env";
import sanitize from "sanitize-filename";
import { outputDir } from "..";
import db from "../db/db";
+import { WEBROOT } from "../helpers/env";
+import { userService } from "./user";
export const download = new Elysia()
.use(userService)
@@ -36,31 +35,28 @@ export const download = new Elysia()
return Bun.file(filePath);
},
)
- .get(
- "/zip/:userId/:jobId",
- async ({ params, jwt, redirect, cookie: { auth } }) => {
- // TODO: Implement zip download
- if (!auth?.value) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ .get("/zip/:userId/:jobId", async ({ params, jwt, redirect, cookie: { auth } }) => {
+ // TODO: Implement zip download
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const user = await jwt.verify(auth.value);
- if (!user) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const job = await db
- .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
- .get(user.id, params.jobId);
+ const job = await db
+ .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
+ .get(user.id, params.jobId);
- if (!job) {
- return redirect(`${WEBROOT}/results`, 302);
- }
+ if (!job) {
+ return redirect(`${WEBROOT}/results`, 302);
+ }
- // const userId = decodeURIComponent(params.userId);
- // const jobId = decodeURIComponent(params.jobId);
- // const outputPath = `${outputDir}${userId}/`{jobId}/);
+ // const userId = decodeURIComponent(params.userId);
+ // const jobId = decodeURIComponent(params.jobId);
+ // const outputPath = `${outputDir}${userId}/`{jobId}/);
- // return Bun.zip(outputPath);
- },
- )
\ No newline at end of file
+ // return Bun.zip(outputPath);
+ });
diff --git a/src/pages/history.tsx b/src/pages/history.tsx
index 648efcb..52e27bf 100644
--- a/src/pages/history.tsx
+++ b/src/pages/history.tsx
@@ -1,11 +1,11 @@
+import { Html } from "@elysiajs/html";
import { Elysia } from "elysia";
import { BaseHtml } from "../components/base";
-import { Html } from "@elysiajs/html";
import { Header } from "../components/header";
-import { userService } from "./user";
-import { ALLOW_UNAUTHENTICATED, HIDE_HISTORY, WEBROOT } from "../helpers/env";
-import { Filename, Jobs } from "../db/types";
import db from "../db/db";
+import { Filename, Jobs } from "../db/types";
+import { ALLOW_UNAUTHENTICATED, HIDE_HISTORY, WEBROOT } from "../helpers/env";
+import { userService } from "./user";
export const history = new Elysia()
.use(userService)
@@ -23,17 +23,10 @@ export const history = new Elysia()
return redirect(`${WEBROOT}/login`, 302);
}
- let userJobs = db
- .query("SELECT * FROM jobs WHERE user_id = ?")
- .as(Jobs)
- .all(user.id)
- .reverse();
+ let userJobs = db.query("SELECT * FROM jobs WHERE user_id = ?").as(Jobs).all(user.id).reverse();
for (const job of userJobs) {
- const files = db
- .query("SELECT * FROM file_names WHERE job_id = ?")
- .as(Filename)
- .all(job.id);
+ const files = db.query("SELECT * FROM file_names WHERE job_id = ?").as(Filename).all(job.id);
job.finished_files = files.length;
job.files_detailed = files;
@@ -123,10 +116,7 @@ export const history = new Elysia()
{userJobs.map((job) => (
<>
- |
+ |
|
-
- {new Date(job.date_created).toLocaleTimeString()}
- |
+ {new Date(job.date_created).toLocaleTimeString()} |
{job.num_files} |
{job.finished_files} |
{job.status} |
@@ -164,43 +152,29 @@ export const history = new Elysia()
-
- Detailed File Information:
-
- {job.files_detailed.map(
- (file: Filename) => (
- Detailed File Information:
+ {job.files_detailed.map((file: Filename) => (
+
+
+ {file.file_name}
+
+
- ),
- )}
+
+
+
+ {file.output_file_name}
+
+
+ ))}
|
@@ -239,4 +213,4 @@ export const history = new Elysia()
>
);
- })
\ No newline at end of file
+ });
diff --git a/src/pages/listConverters.tsx b/src/pages/listConverters.tsx
index adf9f57..a2b99be 100644
--- a/src/pages/listConverters.tsx
+++ b/src/pages/listConverters.tsx
@@ -1,13 +1,10 @@
-import Elysia from "elysia";
-import { userService } from "./user";
import { Html } from "@elysiajs/html";
-import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
+import Elysia from "elysia";
import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
-import {
- getAllInputs,
- getAllTargets,
-} from "../converters/main";
+import { getAllInputs, getAllTargets } from "../converters/main";
+import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
+import { userService } from "./user";
export const listConverters = new Elysia()
.use(userService)
@@ -24,11 +21,7 @@ export const listConverters = new Elysia()
return (
<>
-
+
- {Object.entries(getAllTargets()).map(
- ([converter, targets]) => {
- const inputs = getAllInputs(converter);
- return (
-
- | {converter} |
-
- Count: {inputs.length}
-
- {inputs.map((input) => (
- - {input}
- ))}
-
- |
-
- Count: {targets.length}
-
- {targets.map((target) => (
- - {target}
- ))}
-
- |
-
- );
- },
- )}
+ {Object.entries(getAllTargets()).map(([converter, targets]) => {
+ const inputs = getAllInputs(converter);
+ return (
+
+ | {converter} |
+
+ Count: {inputs.length}
+
+ {inputs.map((input) => (
+ - {input}
+ ))}
+
+ |
+
+ Count: {targets.length}
+
+ {targets.map((target) => (
+ - {target}
+ ))}
+
+ |
+
+ );
+ })}
@@ -86,4 +77,4 @@ export const listConverters = new Elysia()
>
);
- })
\ No newline at end of file
+ });
diff --git a/src/pages/results.tsx b/src/pages/results.tsx
index a1570db..81e6128 100644
--- a/src/pages/results.tsx
+++ b/src/pages/results.tsx
@@ -1,214 +1,215 @@
-import { Elysia } from "elysia";
-import { userService } from "./user";
import { Html } from "@elysiajs/html";
-import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
-import { Filename, Jobs } from "../db/types";
-import { Header } from "../components/header";
+import { Elysia } from "elysia";
import { BaseHtml } from "../components/base";
+import { Header } from "../components/header";
import db from "../db/db";
+import { Filename, Jobs } from "../db/types";
+import { ALLOW_UNAUTHENTICATED, WEBROOT } from "../helpers/env";
+import { userService } from "./user";
-function ResultsArticle({ job, files, outputPath }: { job: Jobs, files: Filename[], outputPath: string }) {
- return (
-
-
Results
-
-
+function ResultsArticle({
+ job,
+ files,
+ outputPath,
+}: {
+ job: Jobs;
+ files: Filename[];
+ outputPath: string;
+}) {
+ return (
+
+
+
Results
+
+
+
-
-
-
-
-
- |
- Converted File Name
- |
-
- Status
- |
-
- View
- |
-
- Download
- |
-
-
-
- {files.map((file) => (
+
+
+
- |
- {file.output_file_name}
- |
- {file.status} |
-
-
- View
-
- |
-
-
- Download
-
- |
+
+ Converted File Name
+ |
+
+ Status
+ |
+
+ View
+ |
+
+ Download
+ |
- ))}
-
-
-
- )
+
+
+ {files.map((file) => (
+
+ |
+ {file.output_file_name}
+ |
+ {file.status} |
+
+
+ View
+
+ |
+
+
+ Download
+
+ |
+
+ ))}
+
+
+
+ );
}
export const results = new Elysia()
.use(userService)
- .get(
- "/results/:jobId",
- async ({ params, jwt, set, redirect, cookie: { auth, job_id } }) => {
- if (!auth?.value) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ .get("/results/:jobId", async ({ params, jwt, set, redirect, cookie: { auth, job_id } }) => {
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- if (job_id?.value) {
- // clear the job_id cookie since we are viewing the results
- job_id.remove();
- }
+ if (job_id?.value) {
+ // clear the job_id cookie since we are viewing the results
+ job_id.remove();
+ }
- const user = await jwt.verify(auth.value);
- if (!user) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const job = db
- .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
- .as(Jobs)
- .get(user.id, params.jobId);
+ const job = db
+ .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
+ .as(Jobs)
+ .get(user.id, params.jobId);
- if (!job) {
- set.status = 404;
- return {
- message: "Job not found.",
- };
- }
+ if (!job) {
+ set.status = 404;
+ return {
+ message: "Job not found.",
+ };
+ }
- const outputPath = `${user.id}/${params.jobId}/`;
+ const outputPath = `${user.id}/${params.jobId}/`;
- const files = db
- .query("SELECT * FROM file_names WHERE job_id = ?")
- .as(Filename)
- .all(params.jobId);
+ const files = db
+ .query("SELECT * FROM file_names WHERE job_id = ?")
+ .as(Filename)
+ .all(params.jobId);
- return (
-
- <>
-
-
-
-
-
- >
-
- );
- },
- )
- .post(
- "/progress/:jobId",
- async ({ jwt, set, params, redirect, cookie: { auth, job_id } }) => {
- if (!auth?.value) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ return (
+
+ <>
+
+
+
+
+
+ >
+
+ );
+ })
+ .post("/progress/:jobId", async ({ jwt, set, params, redirect, cookie: { auth, job_id } }) => {
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- if (job_id?.value) {
- // clear the job_id cookie since we are viewing the results
- job_id.remove();
- }
+ if (job_id?.value) {
+ // clear the job_id cookie since we are viewing the results
+ job_id.remove();
+ }
- const user = await jwt.verify(auth.value);
- if (!user) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const job = db
- .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
- .as(Jobs)
- .get(user.id, params.jobId);
+ const job = db
+ .query("SELECT * FROM jobs WHERE user_id = ? AND id = ?")
+ .as(Jobs)
+ .get(user.id, params.jobId);
- if (!job) {
- set.status = 404;
- return {
- message: "Job not found.",
- };
- }
+ if (!job) {
+ set.status = 404;
+ return {
+ message: "Job not found.",
+ };
+ }
- const outputPath = `${user.id}/${params.jobId}/`;
+ const outputPath = `${user.id}/${params.jobId}/`;
- const files = db
- .query("SELECT * FROM file_names WHERE job_id = ?")
- .as(Filename)
- .all(params.jobId);
+ const files = db
+ .query("SELECT * FROM file_names WHERE job_id = ?")
+ .as(Filename)
+ .all(params.jobId);
- return
;
- },
- )
\ No newline at end of file
+ return
;
+ });
diff --git a/src/pages/root.tsx b/src/pages/root.tsx
index 8c23471..35e0c86 100644
--- a/src/pages/root.tsx
+++ b/src/pages/root.tsx
@@ -1,14 +1,20 @@
-import { Elysia } from "elysia";
-import { Html } from "@elysiajs/html";
-import { FIRST_RUN, userService } from "./user";
-import { ACCOUNT_REGISTRATION, ALLOW_UNAUTHENTICATED, HIDE_HISTORY, HTTP_ALLOWED, WEBROOT } from "../helpers/env";
-import { JWTPayloadSpec } from "@elysiajs/jwt";
import { randomInt } from "node:crypto";
+import { Html } from "@elysiajs/html";
+import { JWTPayloadSpec } from "@elysiajs/jwt";
+import { Elysia } from "elysia";
import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
import { getAllTargets } from "../converters/main";
import db from "../db/db";
import { User } from "../db/types";
+import {
+ ACCOUNT_REGISTRATION,
+ ALLOW_UNAUTHENTICATED,
+ HIDE_HISTORY,
+ HTTP_ALLOWED,
+ WEBROOT,
+} from "../helpers/env";
+import { FIRST_RUN, userService } from "./user";
export const root = new Elysia()
.use(userService)
@@ -27,10 +33,7 @@ export const root = new Elysia()
let user: ({ id: string } & JWTPayloadSpec) | false = false;
if (ALLOW_UNAUTHENTICATED) {
const newUserId = String(
- randomInt(
- 2 ** 24,
- Math.min(2 ** 48 + 2 ** 24 - 1, Number.MAX_SAFE_INTEGER),
- ),
+ randomInt(2 ** 24, Math.min(2 ** 48 + 2 ** 24 - 1, Number.MAX_SAFE_INTEGER)),
);
const accessToken = await jwt.sign({
id: newUserId,
@@ -54,20 +57,19 @@ export const root = new Elysia()
} else if (auth?.value) {
user = await jwt.verify(auth.value);
- if (user !== false && user.id) {
- if (Number.parseInt(user.id) < 2 ** 24 || !ALLOW_UNAUTHENTICATED) {
- // make sure user exists in db
- const existingUser = db
- .query("SELECT * FROM users WHERE id = ?")
- .as(User)
- .get(user.id);
+ if (
+ user !== false &&
+ user.id &&
+ (Number.parseInt(user.id) < 2 ** 24 || !ALLOW_UNAUTHENTICATED)
+ ) {
+ // make sure user exists in db
+ const existingUser = db.query("SELECT * FROM users WHERE id = ?").as(User).get(user.id);
- if (!existingUser) {
- if (auth?.value) {
- auth.remove();
- }
- return redirect(`${WEBROOT}/login`, 302);
+ if (!existingUser) {
+ if (auth?.value) {
+ auth.remove();
}
+ return redirect(`${WEBROOT}/login`, 302);
}
}
}
@@ -82,11 +84,9 @@ export const root = new Elysia()
new Date().toISOString(),
);
- const id = (
- db
- .query("SELECT id FROM jobs WHERE user_id = ? ORDER BY id DESC")
- .get(user.id) as { id: number }
- ).id;
+ const { id } = db
+ .query("SELECT id FROM jobs WHERE user_id = ? ORDER BY id DESC")
+ .get(user.id) as { id: number };
if (!jobId) {
return { message: "Cookies should be enabled to use this app." };
@@ -172,62 +172,53 @@ export const root = new Elysia()
sm:h-[30vh]
`}
>
- {Object.entries(getAllTargets()).map(
- ([converter, targets]) => (
-
-
-
- {targets.map((target) => (
-
- ))}
-
-
- ),
- )}
+ {Object.entries(getAllTargets()).map(([converter, targets]) => (
+
+
+
+ {targets.map((target) => (
+
+ ))}
+
+
+ ))}
{/* Hidden element which determines the format to convert the file too and the converter to use */}
-
@@ -246,4 +237,4 @@ export const root = new Elysia()
>
);
- })
\ No newline at end of file
+ });
diff --git a/src/pages/upload.tsx b/src/pages/upload.tsx
index b4808b1..1a2e634 100644
--- a/src/pages/upload.tsx
+++ b/src/pages/upload.tsx
@@ -1,51 +1,48 @@
import { Elysia, t } from "elysia";
-import { userService } from "./user";
+import db from "../db/db";
import { WEBROOT } from "../helpers/env";
import { uploadsDir } from "../index";
-import db from "../db/db";
+import { userService } from "./user";
+export const upload = new Elysia().use(userService).post(
+ "/upload",
+ async ({ body, redirect, jwt, cookie: { auth, jobId } }) => {
+ if (!auth?.value) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
-export const upload = new Elysia()
- .use(userService)
- .post(
- "/upload",
- async ({ body, redirect, jwt, cookie: { auth, jobId } }) => {
- if (!auth?.value) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ const user = await jwt.verify(auth.value);
+ if (!user) {
+ return redirect(`${WEBROOT}/login`, 302);
+ }
- const user = await jwt.verify(auth.value);
- if (!user) {
- return redirect(`${WEBROOT}/login`, 302);
- }
+ if (!jobId?.value) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
- if (!jobId?.value) {
- return redirect(`${WEBROOT}/`, 302);
- }
+ const existingJob = await db
+ .query("SELECT * FROM jobs WHERE id = ? AND user_id = ?")
+ .get(jobId.value, user.id);
- const existingJob = await db
- .query("SELECT * FROM jobs WHERE id = ? AND user_id = ?")
- .get(jobId.value, user.id);
+ if (!existingJob) {
+ return redirect(`${WEBROOT}/`, 302);
+ }
- if (!existingJob) {
- return redirect(`${WEBROOT}/`, 302);
- }
+ const userUploadsDir = `${uploadsDir}${user.id}/${jobId.value}/`;
- const userUploadsDir = `${uploadsDir}${user.id}/${jobId.value}/`;
-
- if (body?.file) {
- if (Array.isArray(body.file)) {
- for (const file of body.file) {
- await Bun.write(`${userUploadsDir}${file.name}`, file);
- }
- } else {
- await Bun.write(`${userUploadsDir}${body.file["name"]}`, body.file);
+ if (body?.file) {
+ if (Array.isArray(body.file)) {
+ for (const file of body.file) {
+ await Bun.write(`${userUploadsDir}${file.name}`, file);
}
+ } else {
+ await Bun.write(`${userUploadsDir}${body.file["name"]}`, body.file);
}
+ }
- return {
- message: "Files uploaded successfully.",
- };
- },
- { body: t.Object({ file: t.Files() }) },
- )
\ No newline at end of file
+ return {
+ message: "Files uploaded successfully.",
+ };
+ },
+ { body: t.Object({ file: t.Files() }) },
+);
diff --git a/src/pages/user.tsx b/src/pages/user.tsx
index 07d8a85..3e34827 100644
--- a/src/pages/user.tsx
+++ b/src/pages/user.tsx
@@ -1,17 +1,22 @@
-import { Elysia, t } from "elysia";
+import { randomUUID } from "node:crypto";
import { Html } from "@elysiajs/html";
+import { jwt } from "@elysiajs/jwt";
+import { Elysia, t } from "elysia";
import { BaseHtml } from "../components/base";
import { Header } from "../components/header";
-import { jwt } from "@elysiajs/jwt";
-import { randomUUID } from "node:crypto";
-
-import { ACCOUNT_REGISTRATION, WEBROOT, HIDE_HISTORY, ALLOW_UNAUTHENTICATED, HTTP_ALLOWED } from "../helpers/env";
import db from "../db/db";
import { User } from "../db/types";
+import {
+ ACCOUNT_REGISTRATION,
+ ALLOW_UNAUTHENTICATED,
+ HIDE_HISTORY,
+ HTTP_ALLOWED,
+ WEBROOT,
+} from "../helpers/env";
export let FIRST_RUN = db.query("SELECT * FROM users").get() === null || false;
-export const userService = new Elysia({ name: 'user/service' })
+export const userService = new Elysia({ name: "user/service" })
.use(
jwt({
name: "jwt",
@@ -25,35 +30,31 @@ export const userService = new Elysia({ name: 'user/service' })
.model({
signIn: t.Object({
email: t.String(),
- password: t.String()
+ password: t.String(),
}),
})
.macro({
isSignIn(enabled: boolean) {
- if (!enabled) return
+ if (!enabled) return;
return {
- async beforeHandle({
- status,
- jwt,
- cookie: { auth },
- }) {
+ async beforeHandle({ status, jwt, cookie: { auth } }) {
if (auth?.value) {
const user = await jwt.verify(auth.value);
return {
success: true,
- user
- }
+ user,
+ };
}
return status(401, {
success: false,
- message: 'Unauthorized'
- })
- }
- }
- }
- })
+ message: "Unauthorized",
+ });
+ },
+ };
+ },
+ });
export const user = new Elysia()
.use(userService)
@@ -72,9 +73,7 @@ export const user = new Elysia()
>
Welcome to ConvertX!
-
+
@@ -189,9 +184,7 @@ export const user = new Elysia()
FIRST_RUN = false;
}
- const existingUser = await db
- .query("SELECT * FROM users WHERE email = ?")
- .get(email);
+ const existingUser = await db.query("SELECT * FROM users WHERE email = ?").get(email);
if (existingUser) {
set.status = 400;
return {
@@ -200,15 +193,9 @@ export const user = new Elysia()
}
const savedPassword = await Bun.password.hash(password);
- db.query("INSERT INTO users (email, password) VALUES (?, ?)").run(
- email,
- savedPassword,
- );
+ db.query("INSERT INTO users (email, password) VALUES (?, ?)").run(email, savedPassword);
- const user = db
- .query("SELECT * FROM users WHERE email = ?")
- .as(User)
- .get(email);
+ const user = db.query("SELECT * FROM users WHERE email = ?").as(User).get(email);
if (!user) {
set.status = 500;
@@ -239,7 +226,7 @@ export const user = new Elysia()
return redirect(`${WEBROOT}/`, 302);
},
- { body: 'signIn' },
+ { body: "signIn" },
)
.get("/login", async ({ jwt, redirect, cookie: { auth } }) => {
if (FIRST_RUN) {
@@ -308,11 +295,7 @@ export const user = new Elysia()
Register
) : null}
-
+
@@ -324,10 +307,7 @@ export const user = new Elysia()
.post(
"/login",
async function handler({ body, set, redirect, jwt, cookie: { auth } }) {
- const existingUser = db
- .query("SELECT * FROM users WHERE email = ?")
- .as(User)
- .get(body.email);
+ const existingUser = db.query("SELECT * FROM users WHERE email = ?").as(User).get(body.email);
if (!existingUser) {
set.status = 403;
@@ -336,10 +316,7 @@ export const user = new Elysia()
};
}
- const validPassword = await Bun.password.verify(
- body.password,
- existingUser.password,
- );
+ const validPassword = await Bun.password.verify(body.password, existingUser.password);
if (!validPassword) {
set.status = 403;
@@ -370,7 +347,7 @@ export const user = new Elysia()
return redirect(`${WEBROOT}/`, 302);
},
- { body: 'signIn' },
+ { body: "signIn" },
)
.get("/logoff", ({ redirect, cookie: { auth } }) => {
if (auth?.value) {
@@ -396,10 +373,7 @@ export const user = new Elysia()
return redirect(`${WEBROOT}/`, 302);
}
- const userData = db
- .query("SELECT * FROM users WHERE id = ?")
- .as(User)
- .get(user.id);
+ const userData = db.query("SELECT * FROM users WHERE id = ?").as(User).get(user.id);
if (!userData) {
return redirect(`${WEBROOT}/`, 302);
@@ -459,11 +433,7 @@ export const user = new Elysia()
-
+
@@ -483,10 +453,7 @@ export const user = new Elysia()
if (!user) {
return redirect(`${WEBROOT}/login`, 302);
}
- const existingUser = db
- .query("SELECT * FROM users WHERE id = ?")
- .as(User)
- .get(user.id);
+ const existingUser = db.query("SELECT * FROM users WHERE id = ?").as(User).get(user.id);
if (!existingUser) {
if (auth?.value) {
@@ -495,10 +462,7 @@ export const user = new Elysia()
return redirect(`${WEBROOT}/login`, 302);
}
- const validPassword = await Bun.password.verify(
- body.password,
- existingUser.password,
- );
+ const validPassword = await Bun.password.verify(body.password, existingUser.password);
if (!validPassword) {
set.status = 403;
@@ -542,4 +506,4 @@ export const user = new Elysia()
password: t.String(),
}),
},
- )
\ No newline at end of file
+ );