Compare commits
35 Commits
v0.28.0
...
testCleanu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a9b4e1eaf1 | ||
|
|
b23784f598 | ||
|
|
90cbcde029 | ||
|
|
382edc01f8 | ||
|
|
3ff4a5e5b9 | ||
|
|
2bbbbf8e38 | ||
|
|
dee912f075 | ||
|
|
faed367cde | ||
|
|
788744c1be | ||
|
|
686b88d21d | ||
|
|
1a594b27ab | ||
|
|
9f0088c839 | ||
|
|
c778fa73ef | ||
|
|
5564a6e730 | ||
|
|
8a58647ffd | ||
|
|
37dcae282a | ||
|
|
58618b3a21 | ||
|
|
4a4c7faf47 | ||
|
|
66324a5bdc | ||
|
|
3bd18f7c5e | ||
|
|
e693bbb2bd | ||
|
|
f11ad92fa5 | ||
|
|
f443a4e0de | ||
|
|
fa0152aa2d | ||
|
|
e1d0f2cd3e | ||
|
|
81e2a77e57 | ||
|
|
6c9a4e8acc | ||
|
|
8e5b3ea7f1 | ||
|
|
b47f8a2c17 | ||
|
|
56a07bbf3a | ||
|
|
987d793ef4 | ||
|
|
ea85d76f5b | ||
|
|
fc762329a8 | ||
|
|
89031246cf | ||
|
|
e5cb9a28ac |
16
.github/ISSUE_TEMPLATE/1-bug.yml
vendored
16
.github/ISSUE_TEMPLATE/1-bug.yml
vendored
@@ -10,7 +10,21 @@ body:
|
|||||||
Thanks for taking the time to fill out this bug report!
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
|
||||||
This issue form is for reporting bugs only. Please fill out the following sections to help us understand the issue you are facing.
|
This issue form is for reporting bugs only. Please fill out the following sections to help us understand the issue you are facing.
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
id: installation-method
|
||||||
|
attributes:
|
||||||
|
label: Installation Method
|
||||||
|
description: |
|
||||||
|
Indicate whether you are using Docker or a local installation.
|
||||||
|
options:
|
||||||
|
- Docker
|
||||||
|
- Docker ultra lite
|
||||||
|
- Docker fat
|
||||||
|
- Local Installation
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: problem
|
id: problem
|
||||||
validations:
|
validations:
|
||||||
|
|||||||
1
.github/labeler-config.yml
vendored
1
.github/labeler-config.yml
vendored
@@ -2,6 +2,7 @@ Translation:
|
|||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
|
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
|
||||||
- any-glob-to-any-file: 'scripts/ignore_translation.toml'
|
- any-glob-to-any-file: 'scripts/ignore_translation.toml'
|
||||||
|
- any-glob-to-any-file: 'src/main/resources/templates/fragments/languages.html'
|
||||||
|
|
||||||
Front End:
|
Front End:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
6
.github/pull_request_template.md
vendored
6
.github/pull_request_template.md
vendored
@@ -10,9 +10,3 @@ Closes #(issue_number)
|
|||||||
- [ ] I have performed a self-review of my own code
|
- [ ] I have performed a self-review of my own code
|
||||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
- [ ] My changes generate no new warnings
|
- [ ] My changes generate no new warnings
|
||||||
|
|
||||||
## Contributor License Agreement
|
|
||||||
|
|
||||||
By submitting this pull request, I acknowledge and agree that my contributions will be included in Stirling-PDF and that they can be relicensed in the future under the MPL 2.0 (Mozilla Public License Version 2.0) license.
|
|
||||||
|
|
||||||
(This does not change the general open-source nature of Stirling-PDF, simply moving from one license to another license)
|
|
||||||
|
|||||||
32
.github/release.yml
vendored
Normal file
32
.github/release.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
changelog:
|
||||||
|
exclude:
|
||||||
|
labels:
|
||||||
|
- Documentation
|
||||||
|
- Test
|
||||||
|
- Github
|
||||||
|
|
||||||
|
categories:
|
||||||
|
- title: Bug Fixes
|
||||||
|
labels:
|
||||||
|
- Bug
|
||||||
|
|
||||||
|
- title: Enhancements
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
|
||||||
|
- title: Minor Enhancements
|
||||||
|
labels:
|
||||||
|
- Java
|
||||||
|
- Front End
|
||||||
|
|
||||||
|
- title: Docker Updates
|
||||||
|
labels:
|
||||||
|
- Docker
|
||||||
|
|
||||||
|
- title: Translation Changes
|
||||||
|
labels:
|
||||||
|
- Translation
|
||||||
|
|
||||||
|
- title: Other Changes
|
||||||
|
labels:
|
||||||
|
- "*"
|
||||||
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
|
|
||||||
- name: Set up Gradle
|
- name: Set up Gradle
|
||||||
uses: gradle/actions/setup-gradle@v3
|
uses: gradle/actions/setup-gradle@v4
|
||||||
with:
|
with:
|
||||||
gradle-version: 8.7
|
gradle-version: 8.7
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
run: ./gradlew build --no-build-cache
|
run: ./gradlew build --no-build-cache
|
||||||
|
|
||||||
docker-compose-tests:
|
docker-compose-tests:
|
||||||
# if: github.event_name == 'push' && github.ref == 'refs/heads/main' ||
|
# if: github.event_name == 'push' && github.ref == 'refs/heads/main' ||
|
||||||
# (github.event_name == 'pull_request' &&
|
# (github.event_name == 'pull_request' &&
|
||||||
# contains(github.event.pull_request.labels.*.name, 'licenses') == false &&
|
# contains(github.event.pull_request.labels.*.name, 'licenses') == false &&
|
||||||
# (
|
# (
|
||||||
@@ -74,14 +74,14 @@ jobs:
|
|||||||
sudo chmod +x /usr/local/bin/docker-compose
|
sudo chmod +x /usr/local/bin/docker-compose
|
||||||
|
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.7"
|
python-version: "3.7"
|
||||||
|
|
||||||
- name: Pip requirements
|
- name: Pip requirements
|
||||||
run: |
|
run: |
|
||||||
pip install -r ./cucumber/requirements.txt
|
pip install -r ./cucumber/requirements.txt
|
||||||
|
|
||||||
- name: Run Docker Compose Tests
|
- name: Run Docker Compose Tests
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./test.sh
|
chmod +x ./test.sh
|
||||||
|
|||||||
5
.github/workflows/licenses-update.yml
vendored
5
.github/workflows/licenses-update.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
|||||||
java-version: "17"
|
java-version: "17"
|
||||||
distribution: "adopt"
|
distribution: "adopt"
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v3
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Run Gradle Command
|
- name: Run Gradle Command
|
||||||
run: ./gradlew clean generateLicenseReport
|
run: ./gradlew clean generateLicenseReport
|
||||||
@@ -58,6 +58,7 @@ jobs:
|
|||||||
title: "Update 3rd Party Licenses"
|
title: "Update 3rd Party Licenses"
|
||||||
body: |
|
body: |
|
||||||
Auto-generated by [create-pull-request][1]
|
Auto-generated by [create-pull-request][1]
|
||||||
|
|
||||||
[1]: https://github.com/peter-evans/create-pull-request
|
[1]: https://github.com/peter-evans/create-pull-request
|
||||||
labels: licenses
|
labels: licenses
|
||||||
draft: false
|
draft: false
|
||||||
@@ -68,7 +69,7 @@ jobs:
|
|||||||
run: gh pr review --approve "${{ steps.cpr.outputs.pull-request-number }}"
|
run: gh pr review --approve "${{ steps.cpr.outputs.pull-request-number }}"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Enable auto-merge
|
- name: Enable auto-merge
|
||||||
if: steps.cpr.outputs.pull-request-operation == 'created'
|
if: steps.cpr.outputs.pull-request-operation == 'created'
|
||||||
uses: peter-evans/enable-pull-request-automerge@v3
|
uses: peter-evans/enable-pull-request-automerge@v3
|
||||||
|
|||||||
9
.github/workflows/push-docker.yml
vendored
9
.github/workflows/push-docker.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
java-version: "17"
|
java-version: "17"
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v3
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
with:
|
with:
|
||||||
gradle-version: 8.7
|
gradle-version: 8.7
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
|
type=raw,value=alpha,enable=${{ github.ref == 'refs/heads/main' }}
|
||||||
|
|
||||||
- name: Build and push main Dockerfile
|
- name: Build and push main Dockerfile
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
context: .
|
context: .
|
||||||
@@ -98,7 +98,7 @@ jobs:
|
|||||||
type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
type=raw,value=latest-ultra-lite,enable=${{ github.ref == 'refs/heads/master' }}
|
||||||
|
|
||||||
- name: Build and push Dockerfile-ultra-lite
|
- name: Build and push Dockerfile-ultra-lite
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
if: github.ref != 'refs/heads/main'
|
if: github.ref != 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@@ -111,7 +111,6 @@ jobs:
|
|||||||
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
build-args: VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
|
||||||
platforms: linux/amd64,linux/arm64/v8
|
platforms: linux/amd64,linux/arm64/v8
|
||||||
|
|
||||||
|
|
||||||
- name: Generate tags fat
|
- name: Generate tags fat
|
||||||
id: meta3
|
id: meta3
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
@@ -125,7 +124,7 @@ jobs:
|
|||||||
type=raw,value=latest-fat,enable=${{ github.ref == 'refs/heads/master' }}
|
type=raw,value=latest-fat,enable=${{ github.ref == 'refs/heads/master' }}
|
||||||
|
|
||||||
- name: Build and push main Dockerfile fat
|
- name: Build and push main Dockerfile fat
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
if: github.ref != 'refs/heads/main'
|
if: github.ref != 'refs/heads/main'
|
||||||
with:
|
with:
|
||||||
builder: ${{ steps.buildx.outputs.name }}
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
|||||||
2
.github/workflows/releaseArtifacts.yml
vendored
2
.github/workflows/releaseArtifacts.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
|||||||
java-version: "17"
|
java-version: "17"
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v3
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
with:
|
with:
|
||||||
gradle-version: 8.7
|
gradle-version: 8.7
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/swagger.yml
vendored
2
.github/workflows/swagger.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
java-version: "17"
|
java-version: "17"
|
||||||
distribution: "temurin"
|
distribution: "temurin"
|
||||||
|
|
||||||
- uses: gradle/actions/setup-gradle@v3
|
- uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Generate Swagger documentation
|
- name: Generate Swagger documentation
|
||||||
run: ./gradlew generateOpenApiDocs
|
run: ./gradlew generateOpenApiDocs
|
||||||
|
|||||||
@@ -39,16 +39,16 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
|||||||
libreoffice \
|
libreoffice \
|
||||||
# pdftohtml
|
# pdftohtml
|
||||||
poppler-utils \
|
poppler-utils \
|
||||||
# OCR MY PDF (unpaper for descew and other advanced featues)
|
# OCR MY PDF (unpaper for descew and other advanced features)
|
||||||
ocrmypdf \
|
ocrmypdf \
|
||||||
tesseract-ocr-data-eng \
|
tesseract-ocr-data-eng \
|
||||||
# CV
|
# CV
|
||||||
py3-opencv \
|
py3-opencv \
|
||||||
# python3/pip
|
# python3/pip
|
||||||
python3 \
|
python3 \
|
||||||
py3-pip && \
|
py3-pip && \
|
||||||
# uno unoconv and HTML
|
# uno unoconv and HTML
|
||||||
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
|
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint pdf2image pillow && \
|
||||||
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
||||||
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
|
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
|
||||||
fc-cache -f -v && \
|
fc-cache -f -v && \
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ COPY . .
|
|||||||
|
|
||||||
# Build the application with DOCKER_ENABLE_SECURITY=false
|
# Build the application with DOCKER_ENABLE_SECURITY=false
|
||||||
RUN DOCKER_ENABLE_SECURITY=true \
|
RUN DOCKER_ENABLE_SECURITY=true \
|
||||||
./gradlew clean build
|
./gradlew clean build
|
||||||
|
|
||||||
# Main stage
|
# Main stage
|
||||||
FROM alpine:3.20.2
|
FROM alpine:3.20.2
|
||||||
@@ -32,7 +32,7 @@ ENV DOCKER_ENABLE_SECURITY=false \
|
|||||||
UMASK=022 \
|
UMASK=022 \
|
||||||
FAT_DOCKER=true \
|
FAT_DOCKER=true \
|
||||||
INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
|
INSTALL_BOOK_AND_ADVANCED_HTML_OPS=false
|
||||||
|
|
||||||
|
|
||||||
# JDK for app
|
# JDK for app
|
||||||
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
|
||||||
@@ -64,7 +64,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
|
|||||||
python3 \
|
python3 \
|
||||||
py3-pip && \
|
py3-pip && \
|
||||||
# uno unoconv and HTML
|
# uno unoconv and HTML
|
||||||
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
|
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint pdf2image pillow && \
|
||||||
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
mv /usr/share/tessdata /usr/share/tessdata-original && \
|
||||||
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
|
mkdir -p $HOME /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
|
||||||
fc-cache -f -v && \
|
fc-cache -f -v && \
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
|
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
|
||||||
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
|
| pdf-to-img | | ✔️ | | | | ✔️ | | | | ✔️ | |
|
||||||
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
|
||||||
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
|
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
|
||||||
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
|
||||||
@@ -44,4 +44,4 @@
|
|||||||
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
|
||||||
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
|
||||||
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
|
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
|
||||||
| sign | | | | ✔️ | | | | | | | ✔️ |
|
| sign | | | | ✔️ | | | | | | | ✔️ |
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -169,42 +169,42 @@ Stirling PDF currently supports 38!
|
|||||||
|
|
||||||
| Language | Progress |
|
| Language | Progress |
|
||||||
| ------------------------------------------- | -------------------------------------- |
|
| ------------------------------------------- | -------------------------------------- |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| Basque (Euskara) (eu_ES) |  |
|
| Basque (Euskara) (eu_ES) |  |
|
||||||
| Bulgarian (Български) (bg_BG) |  |
|
| Bulgarian (Български) (bg_BG) |  |
|
||||||
| Catalan (Català) (ca_CA) |  |
|
| Catalan (Català) (ca_CA) |  |
|
||||||
| Croatian (Hrvatski) (hr_HR) |  |
|
| Croatian (Hrvatski) (hr_HR) |  |
|
||||||
| Czech (Česky) (cs_CZ) |  |
|
| Czech (Česky) (cs_CZ) |  |
|
||||||
| Danish (Dansk) (da_DK) |  |
|
| Danish (Dansk) (da_DK) |  |
|
||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
| Hungarian (Magyar) (hu_HU) |  |
|
| Hungarian (Magyar) (hu_HU) |  |
|
||||||
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
||||||
| Irish (Gaeilge) (ga_IE) |  |
|
| Irish (Gaeilge) (ga_IE) |  |
|
||||||
| Italian (Italiano) (it_IT) |  |
|
| Italian (Italiano) (it_IT) |  |
|
||||||
| Japanese (日本語) (ja_JP) |  |
|
| Japanese (日本語) (ja_JP) |  |
|
||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
| Russian (Русский) (ru_RU) |  |
|
| Russian (Русский) (ru_RU) |  |
|
||||||
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||||
| Slovakian (Slovensky) (sk_SK) |  |
|
| Slovakian (Slovensky) (sk_SK) |  |
|
||||||
| Spanish (Español) (es_ES) |  |
|
| Spanish (Español) (es_ES) |  |
|
||||||
| Swedish (Svenska) (sv_SE) |  |
|
| Swedish (Svenska) (sv_SE) |  |
|
||||||
| Thai (ไทย) (th_TH) |  |
|
| Thai (ไทย) (th_TH) |  |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||||
| Turkish (Türkçe) (tr_TR) |  |
|
| Turkish (Türkçe) (tr_TR) |  |
|
||||||
| Ukrainian (Українська) (uk_UA) |  |
|
| Ukrainian (Українська) (uk_UA) |  |
|
||||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||||
|
|
||||||
## Contributing (creating issues, translations, fixing bugs, etc.)
|
## Contributing (creating issues, translations, fixing bugs, etc.)
|
||||||
|
|
||||||
|
|||||||
41
build.gradle
41
build.gradle
@@ -7,6 +7,7 @@ plugins {
|
|||||||
id "edu.sc.seis.launch4j" version "3.0.6"
|
id "edu.sc.seis.launch4j" version "3.0.6"
|
||||||
id "com.diffplug.spotless" version "6.25.0"
|
id "com.diffplug.spotless" version "6.25.0"
|
||||||
id "com.github.jk1.dependency-license-report" version "2.9"
|
id "com.github.jk1.dependency-license-report" version "2.9"
|
||||||
|
//id "nebula.lint" version "19.0.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
@@ -21,7 +22,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.28.0"
|
version = "0.28.2"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// 17 is lowest but we support and recommend 21
|
// 17 is lowest but we support and recommend 21
|
||||||
@@ -100,15 +101,21 @@ spotless {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//gradleLint {
|
||||||
|
// rules=['unused-dependency']
|
||||||
|
// }
|
||||||
tasks.wrapper {
|
tasks.wrapper {
|
||||||
gradleVersion = "8.7"
|
gradleVersion = "8.7"
|
||||||
}
|
}
|
||||||
|
//tasks.withType(JavaCompile) {
|
||||||
|
// options.compilerArgs << "-Xlint:deprecation"
|
||||||
|
//}
|
||||||
|
configurations.all {
|
||||||
|
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
||||||
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
//security updates
|
//security updates
|
||||||
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
implementation "org.springframework:spring-webmvc:6.1.9"
|
||||||
implementation "ch.qos.logback:logback-core:$logbackVersion"
|
|
||||||
implementation "org.springframework:spring-webmvc:6.1.12"
|
|
||||||
|
|
||||||
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
implementation("io.github.pixee:java-security-toolkit:1.2.0")
|
||||||
|
|
||||||
@@ -116,36 +123,33 @@ dependencies {
|
|||||||
implementation 'com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4'
|
implementation 'com.github.Carleslc.Simple-YAML:Simple-Yaml:1.8.4'
|
||||||
|
|
||||||
// Exclude Tomcat and include Jetty
|
// Exclude Tomcat and include Jetty
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion") {
|
implementation("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
|
||||||
exclude group: "org.springframework.boot", module: "spring-boot-starter-tomcat"
|
|
||||||
}
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion"
|
||||||
|
|
||||||
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-thymeleaf:$springBootVersion"
|
||||||
|
|
||||||
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
if (System.getenv("DOCKER_ENABLE_SECURITY") != "false") {
|
||||||
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-security:$springBootVersion"
|
||||||
implementation "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
|
runtimeOnly "org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
|
||||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:$springBootVersion"
|
||||||
|
|
||||||
//2.2.x requires rebuild of DB file.. need migration path
|
//2.2.x requires rebuild of DB file.. need migration path
|
||||||
implementation "com.h2database:h2:2.1.214"
|
runtimeOnly "com.h2database:h2:2.1.214"
|
||||||
// implementation "com.h2database:h2:2.2.224"
|
// implementation "com.h2database:h2:2.2.224"
|
||||||
}
|
}
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
||||||
|
|
||||||
// Batik
|
// Batik
|
||||||
implementation "org.apache.xmlgraphics:batik-all:1.17"
|
|
||||||
|
|
||||||
// TwelveMonkeys
|
// TwelveMonkeys
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-batik:$imageioVersion"
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-bmp:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-hdr:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-icns:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-iff:$imageioVersion"
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-jpeg:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
|
// implementation "com.twelvemonkeys.imageio:imageio-pcx:$imageioVersion@
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-pict:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-pnm:$imageioVersion"
|
||||||
@@ -153,13 +157,12 @@ dependencies {
|
|||||||
// implementation "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-sgi:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-tga:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-thumbsdb:$imageioVersion"
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-tiff:$imageioVersion"
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
runtimeOnly "com.twelvemonkeys.imageio:imageio-webp:$imageioVersion"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
// implementation "com.twelvemonkeys.imageio:imageio-xwd:$imageioVersion"
|
||||||
|
|
||||||
implementation "commons-io:commons-io:2.16.1"
|
implementation "commons-io:commons-io:2.16.1"
|
||||||
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0"
|
||||||
|
|
||||||
//general PDF
|
//general PDF
|
||||||
|
|
||||||
// https://mvnrepository.com/artifact/com.opencsv/opencsv
|
// https://mvnrepository.com/artifact/com.opencsv/opencsv
|
||||||
@@ -189,14 +192,14 @@ dependencies {
|
|||||||
implementation "org.commonmark:commonmark:0.22.0"
|
implementation "org.commonmark:commonmark:0.22.0"
|
||||||
implementation "org.commonmark:commonmark-ext-gfm-tables:0.22.0"
|
implementation "org.commonmark:commonmark-ext-gfm-tables:0.22.0"
|
||||||
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
// https://mvnrepository.com/artifact/com.bucket4j/bucket4j_jdk17
|
||||||
implementation "com.bucket4j:bucket4j_jdk17-core:8.13.1"
|
implementation "com.bucket4j:bucket4j_jdk17-core:8.14.0"
|
||||||
implementation "com.fathzer:javaluator:3.0.4"
|
implementation "com.fathzer:javaluator:3.0.4"
|
||||||
|
|
||||||
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
|
developmentOnly("org.springframework.boot:spring-boot-devtools:$springBootVersion")
|
||||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||||
|
|
||||||
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
testRuntimeOnly 'org.mockito:mockito-inline:5.2.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile).configureEach {
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.28.0
|
appVersion: 0.28.2
|
||||||
description: locally hosted web application that allows you to perform various operations
|
description: locally hosted web application that allows you to perform various operations
|
||||||
on PDF files
|
on PDF files
|
||||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
|
|||||||
@@ -181,7 +181,9 @@ ignore = [
|
|||||||
|
|
||||||
[pt_BR]
|
[pt_BR]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'changeMetadata.trapped',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'pipelineOptions.pipelineHeader',
|
||||||
]
|
]
|
||||||
|
|
||||||
[pt_PT]
|
[pt_PT]
|
||||||
|
|||||||
174
scripts/png_to_webp.py
Normal file
174
scripts/png_to_webp.py
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
"""
|
||||||
|
Author: Ludy87
|
||||||
|
Description: This script converts a PDF file to WebP images. It includes functionality to resize images if they exceed specified dimensions and handle conversion of PDF pages to WebP format.
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
To convert a PDF file to WebP images with each page as a separate WebP file:
|
||||||
|
python script.py input.pdf output_directory
|
||||||
|
|
||||||
|
To convert a PDF file to a single WebP image:
|
||||||
|
python script.py input.pdf output_directory --single
|
||||||
|
|
||||||
|
To adjust the DPI resolution for rendering PDF pages:
|
||||||
|
python script.py input.pdf output_directory --dpi 150
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
from pdf2image import convert_from_path
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
def resize_image(input_image_path, output_image_path, max_size=(16383, 16383)):
|
||||||
|
"""
|
||||||
|
Resize the image if its dimensions exceed the maximum allowed size and save it as WebP.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
input_image_path : str
|
||||||
|
Path to the input image file.
|
||||||
|
output_image_path : str
|
||||||
|
Path where the output WebP image will be saved.
|
||||||
|
max_size : tuple of int, optional
|
||||||
|
Maximum allowed dimensions for the image (width, height). Default is (16383, 16383).
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Open the image
|
||||||
|
image = Image.open(input_image_path)
|
||||||
|
width, height = image.size
|
||||||
|
max_width, max_height = max_size
|
||||||
|
|
||||||
|
# Check if the image dimensions exceed the maximum allowed dimensions
|
||||||
|
if width > max_width or height > max_height:
|
||||||
|
# Calculate the scaling ratio
|
||||||
|
ratio = min(max_width / width, max_height / height)
|
||||||
|
new_width = int(width * ratio)
|
||||||
|
new_height = int(height * ratio)
|
||||||
|
|
||||||
|
# Resize the image
|
||||||
|
resized_image = image.resize((new_width, new_height), Image.LANCZOS)
|
||||||
|
resized_image.save(output_image_path, format="WEBP", quality=100)
|
||||||
|
print(
|
||||||
|
f"The image was successfully resized to ({new_width}, {new_height}) and saved as WebP: {output_image_path}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# If dimensions are within the allowed limits, save the image directly
|
||||||
|
image.save(output_image_path, format="WEBP", quality=100)
|
||||||
|
print(f"The image was successfully saved as WebP: {output_image_path}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def convert_image_to_webp(input_image, output_file):
|
||||||
|
"""
|
||||||
|
Convert an image to WebP format, resizing it if it exceeds the maximum dimensions.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
input_image : str
|
||||||
|
Path to the input image file.
|
||||||
|
output_file : str
|
||||||
|
Path where the output WebP image will be saved.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
# Resize the image if it exceeds the maximum dimensions
|
||||||
|
resize_image(input_image, output_file, max_size=(16383, 16383))
|
||||||
|
|
||||||
|
|
||||||
|
def pdf_to_webp(pdf_path, output_dir, dpi=300):
|
||||||
|
"""
|
||||||
|
Convert each page of a PDF file to WebP images.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
pdf_path : str
|
||||||
|
Path to the input PDF file.
|
||||||
|
output_dir : str
|
||||||
|
Directory where the WebP images will be saved.
|
||||||
|
dpi : int, optional
|
||||||
|
DPI resolution for rendering PDF pages. Default is 300.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
# Convert the PDF to a list of images
|
||||||
|
images = convert_from_path(pdf_path, dpi=dpi)
|
||||||
|
|
||||||
|
for page_number, image in enumerate(images):
|
||||||
|
# Define temporary PNG path
|
||||||
|
temp_png_path = os.path.join(output_dir, f"temp_page_{page_number + 1}.png")
|
||||||
|
image.save(temp_png_path, format="PNG")
|
||||||
|
|
||||||
|
# Define the output path for WebP
|
||||||
|
output_path = os.path.join(output_dir, f"page_{page_number + 1}.webp")
|
||||||
|
|
||||||
|
# Convert PNG to WebP
|
||||||
|
convert_image_to_webp(temp_png_path, output_path)
|
||||||
|
|
||||||
|
# Delete the temporary PNG file
|
||||||
|
os.remove(temp_png_path)
|
||||||
|
|
||||||
|
|
||||||
|
def main(pdf_image_path, output_dir, dpi=300, single_images_flag=False):
|
||||||
|
"""
|
||||||
|
Main function to handle conversion from PDF to WebP images.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
pdf_image_path : str
|
||||||
|
Path to the input PDF file or image.
|
||||||
|
output_dir : str
|
||||||
|
Directory where the WebP images will be saved.
|
||||||
|
dpi : int, optional
|
||||||
|
DPI resolution for rendering PDF pages. Default is 300.
|
||||||
|
single_images_flag : bool, optional
|
||||||
|
If True, combine all pages into a single WebP image. Default is False.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
if single_images_flag:
|
||||||
|
# Combine all pages into a single WebP image
|
||||||
|
output_path = os.path.join(output_dir, "combined_image.webp")
|
||||||
|
convert_image_to_webp(pdf_image_path, output_path)
|
||||||
|
else:
|
||||||
|
# Convert each PDF page to a separate WebP image
|
||||||
|
pdf_to_webp(pdf_image_path, output_dir, dpi)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Convert a PDF file to WebP images.")
|
||||||
|
parser.add_argument("pdf_path", help="The path to the input PDF file.")
|
||||||
|
parser.add_argument(
|
||||||
|
"output_dir", help="The directory where the WebP images should be saved."
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--dpi",
|
||||||
|
type=int,
|
||||||
|
default=300,
|
||||||
|
help="The DPI resolution for rendering the PDF pages (default: 300).",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--single",
|
||||||
|
action="store_true",
|
||||||
|
help="Combine all pages into a single WebP image.",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
os.makedirs(args.output_dir, exist_ok=True)
|
||||||
|
main(
|
||||||
|
args.pdf_path,
|
||||||
|
args.output_dir,
|
||||||
|
dpi=args.dpi,
|
||||||
|
single_images_flag=args.single,
|
||||||
|
)
|
||||||
@@ -65,6 +65,7 @@ public class SPdfApplication {
|
|||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
public static void main(String[] args) throws IOException, InterruptedException {
|
||||||
|
|
||||||
SpringApplication app = new SpringApplication(SPdfApplication.class);
|
SpringApplication app = new SpringApplication(SPdfApplication.class);
|
||||||
|
app.setAdditionalProfiles("default");
|
||||||
app.addInitializers(new ConfigInitializer());
|
app.addInitializers(new ConfigInitializer());
|
||||||
Map<String, String> propertyFiles = new HashMap<>();
|
Map<String, String> propertyFiles = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.simpleyaml.configuration.comments.CommentType;
|
import org.simpleyaml.configuration.comments.CommentType;
|
||||||
import org.simpleyaml.configuration.file.YamlFile;
|
import org.simpleyaml.configuration.file.YamlFile;
|
||||||
|
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
|
||||||
|
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.ApplicationContextInitializer;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
@@ -71,9 +73,17 @@ public class ConfigInitializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
final YamlFile settingsTemplateFile = new YamlFile(tempTemplatePath.toFile());
|
final YamlFile settingsTemplateFile = new YamlFile(tempTemplatePath.toFile());
|
||||||
|
DumperOptions yamlOptionsSettingsTemplateFile =
|
||||||
|
((SimpleYamlImplementation) settingsTemplateFile.getImplementation())
|
||||||
|
.getDumperOptions();
|
||||||
|
yamlOptionsSettingsTemplateFile.setSplitLines(false);
|
||||||
settingsTemplateFile.loadWithComments();
|
settingsTemplateFile.loadWithComments();
|
||||||
|
|
||||||
final YamlFile settingsFile = new YamlFile(settingsPath.toFile());
|
final YamlFile settingsFile = new YamlFile(settingsPath.toFile());
|
||||||
|
DumperOptions yamlOptionsSettingsFile =
|
||||||
|
((SimpleYamlImplementation) settingsFile.getImplementation())
|
||||||
|
.getDumperOptions();
|
||||||
|
yamlOptionsSettingsFile.setSplitLines(false);
|
||||||
settingsFile.loadWithComments();
|
settingsFile.loadWithComments();
|
||||||
|
|
||||||
// Load headers and comments
|
// Load headers and comments
|
||||||
@@ -81,6 +91,10 @@ public class ConfigInitializer
|
|||||||
|
|
||||||
// Create a new file for temporary settings
|
// Create a new file for temporary settings
|
||||||
final YamlFile tempSettingFile = new YamlFile(settingsPath.toFile());
|
final YamlFile tempSettingFile = new YamlFile(settingsPath.toFile());
|
||||||
|
DumperOptions yamlOptionsTempSettingFile =
|
||||||
|
((SimpleYamlImplementation) tempSettingFile.getImplementation())
|
||||||
|
.getDumperOptions();
|
||||||
|
yamlOptionsTempSettingFile.setSplitLines(false);
|
||||||
tempSettingFile.createNewFile(true);
|
tempSettingFile.createNewFile(true);
|
||||||
tempSettingFile.setHeader(header);
|
tempSettingFile.setHeader(header);
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ public class EndpointConfiguration {
|
|||||||
addEndpointToGroup("Python", REMOVE_BLANKS);
|
addEndpointToGroup("Python", REMOVE_BLANKS);
|
||||||
addEndpointToGroup("Python", "html-to-pdf");
|
addEndpointToGroup("Python", "html-to-pdf");
|
||||||
addEndpointToGroup("Python", "url-to-pdf");
|
addEndpointToGroup("Python", "url-to-pdf");
|
||||||
|
addEndpointToGroup("Python", "pdf-to-img");
|
||||||
|
|
||||||
// openCV
|
// openCV
|
||||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import java.nio.file.Paths;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.simpleyaml.configuration.file.YamlFile;
|
import org.simpleyaml.configuration.file.YamlFile;
|
||||||
|
import org.simpleyaml.configuration.implementation.SimpleYamlImplementation;
|
||||||
|
import org.simpleyaml.configuration.implementation.snakeyaml.lib.DumperOptions;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -92,6 +94,9 @@ public class InitialSecuritySetup {
|
|||||||
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
Path path = Paths.get("configs", "settings.yml"); // Target the configs/settings.yml
|
||||||
|
|
||||||
final YamlFile settingsYml = new YamlFile(path.toFile());
|
final YamlFile settingsYml = new YamlFile(path.toFile());
|
||||||
|
DumperOptions yamlOptionssettingsYml =
|
||||||
|
((SimpleYamlImplementation) settingsYml.getImplementation()).getDumperOptions();
|
||||||
|
yamlOptionssettingsYml.setSplitLines(false);
|
||||||
|
|
||||||
settingsYml.loadWithComments();
|
settingsYml.loadWithComments();
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
@@ -150,8 +149,7 @@ public class SecurityConfiguration {
|
|||||||
})
|
})
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.anyRequest()
|
.anyRequest()
|
||||||
.authenticated())
|
.authenticated());
|
||||||
.authenticationProvider(authenticationProvider());
|
|
||||||
|
|
||||||
// Handle OAUTH2 Logins
|
// Handle OAUTH2 Logins
|
||||||
if (applicationProperties.getSecurity().getOAUTH2() != null
|
if (applicationProperties.getSecurity().getOAUTH2() != null
|
||||||
@@ -379,14 +377,6 @@ public class SecurityConfiguration {
|
|||||||
return new IPRateLimitingFilter(maxRequestsPerIp, maxRequestsPerIp);
|
return new IPRateLimitingFilter(maxRequestsPerIp, maxRequestsPerIp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
|
||||||
public DaoAuthenticationProvider authenticationProvider() {
|
|
||||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
|
||||||
authProvider.setUserDetailsService(userDetailsService);
|
|
||||||
authProvider.setPasswordEncoder(passwordEncoder());
|
|
||||||
return authProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PersistentTokenRepository persistentTokenRepository() {
|
public PersistentTokenRepository persistentTokenRepository() {
|
||||||
return new JPATokenRepositoryImpl();
|
return new JPATokenRepositoryImpl();
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package stirling.software.SPDF.config.security;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -9,6 +11,7 @@ import org.springframework.context.annotation.Lazy;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.session.SessionInformation;
|
import org.springframework.security.core.session.SessionInformation;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
@@ -22,6 +25,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
import stirling.software.SPDF.config.security.session.SessionPersistentRegistry;
|
||||||
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
import stirling.software.SPDF.model.ApiKeyAuthenticationToken;
|
||||||
|
import stirling.software.SPDF.model.User;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class UserAuthenticationFilter extends OncePerRequestFilter {
|
public class UserAuthenticationFilter extends OncePerRequestFilter {
|
||||||
@@ -54,15 +58,20 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
try {
|
try {
|
||||||
// Use API key to authenticate. This requires you to have an authentication
|
// Use API key to authenticate. This requires you to have an authentication
|
||||||
// provider for API keys.
|
// provider for API keys.
|
||||||
UserDetails userDetails = userService.loadUserByApiKey(apiKey);
|
Optional<User> user = userService.getUserByApiKey(apiKey);
|
||||||
if (userDetails == null) {
|
if (!user.isPresent()) {
|
||||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||||
response.getWriter().write("Invalid API Key.");
|
response.getWriter().write("Invalid API Key.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
authentication =
|
List<SimpleGrantedAuthority> authorities =
|
||||||
new ApiKeyAuthenticationToken(
|
user.get().getAuthorities().stream()
|
||||||
userDetails, apiKey, userDetails.getAuthorities());
|
.map(
|
||||||
|
authority ->
|
||||||
|
new SimpleGrantedAuthority(
|
||||||
|
authority.getAuthority()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
authentication = new ApiKeyAuthenticationToken(user.get(), apiKey, authorities);
|
||||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
} catch (AuthenticationException e) {
|
} catch (AuthenticationException e) {
|
||||||
// If API key authentication fails, deny the request
|
// If API key authentication fails, deny the request
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ public class UserService implements UserServiceInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Authentication getAuthentication(String apiKey) {
|
public Authentication getAuthentication(String apiKey) {
|
||||||
User user = getUserByApiKey(apiKey);
|
Optional<User> user = getUserByApiKey(apiKey);
|
||||||
if (user == null) {
|
if (!user.isPresent()) {
|
||||||
throw new UsernameNotFoundException("API key is not valid");
|
throw new UsernameNotFoundException("API key is not valid");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
return new UsernamePasswordAuthenticationToken(
|
return new UsernamePasswordAuthenticationToken(
|
||||||
user, // principal (typically the user)
|
user, // principal (typically the user)
|
||||||
null, // credentials (we don't expose the password or API key here)
|
null, // credentials (we don't expose the password or API key here)
|
||||||
getAuthorities(user) // user's authorities (roles/permissions)
|
getAuthorities(user.get()) // user's authorities (roles/permissions)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,17 +89,17 @@ public class UserService implements UserServiceInterface {
|
|||||||
String apiKey;
|
String apiKey;
|
||||||
do {
|
do {
|
||||||
apiKey = UUID.randomUUID().toString();
|
apiKey = UUID.randomUUID().toString();
|
||||||
} while (userRepository.findByApiKey(apiKey) != null); // Ensure uniqueness
|
} while (userRepository.findByApiKey(apiKey).isPresent()); // Ensure uniqueness
|
||||||
return apiKey;
|
return apiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public User addApiKeyToUser(String username) {
|
public User addApiKeyToUser(String username) {
|
||||||
User user =
|
Optional<User> user = findByUsernameIgnoreCase(username);
|
||||||
findByUsernameIgnoreCase(username)
|
if (user.isPresent()) {
|
||||||
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
user.get().setApiKey(generateApiKey());
|
||||||
|
return userRepository.save(user.get());
|
||||||
user.setApiKey(generateApiKey());
|
}
|
||||||
return userRepository.save(user);
|
throw new UsernameNotFoundException("User not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
public User refreshApiKeyForUser(String username) {
|
public User refreshApiKeyForUser(String username) {
|
||||||
@@ -114,21 +114,18 @@ public class UserService implements UserServiceInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isValidApiKey(String apiKey) {
|
public boolean isValidApiKey(String apiKey) {
|
||||||
return userRepository.findByApiKey(apiKey) != null;
|
return userRepository.findByApiKey(apiKey).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public User getUserByApiKey(String apiKey) {
|
public Optional<User> getUserByApiKey(String apiKey) {
|
||||||
return userRepository.findByApiKey(apiKey);
|
return userRepository.findByApiKey(apiKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserDetails loadUserByApiKey(String apiKey) {
|
public Optional<User> loadUserByApiKey(String apiKey) {
|
||||||
User user = userRepository.findByApiKey(apiKey);
|
Optional<User> user = userRepository.findByApiKey(apiKey);
|
||||||
if (user != null) {
|
|
||||||
// Convert your User entity to a UserDetails object with authorities
|
if (user.isPresent()) {
|
||||||
return new org.springframework.security.core.userdetails.User(
|
return user;
|
||||||
user.getUsername(),
|
|
||||||
user.getPassword(), // you might not need this for API key auth
|
|
||||||
getAuthorities(user));
|
|
||||||
}
|
}
|
||||||
return null; // or throw an exception
|
return null; // or throw an exception
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
package stirling.software.SPDF.controller.api.converters;
|
package stirling.software.SPDF.controller.api.converters;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.pdfbox.rendering.ImageType;
|
import org.apache.pdfbox.rendering.ImageType;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -20,7 +30,10 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
|||||||
|
|
||||||
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
|
import stirling.software.SPDF.model.api.converters.ConvertToImageRequest;
|
||||||
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
|
import stirling.software.SPDF.model.api.converters.ConvertToPdfRequest;
|
||||||
|
import stirling.software.SPDF.utils.CheckProgramInstall;
|
||||||
import stirling.software.SPDF.utils.PdfUtils;
|
import stirling.software.SPDF.utils.PdfUtils;
|
||||||
|
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||||
|
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@@ -60,15 +73,87 @@ public class ConvertImgPDFController {
|
|||||||
result =
|
result =
|
||||||
PdfUtils.convertFromPdf(
|
PdfUtils.convertFromPdf(
|
||||||
pdfBytes,
|
pdfBytes,
|
||||||
imageFormat.toUpperCase(),
|
imageFormat.equalsIgnoreCase("webp") ? "png" : imageFormat.toUpperCase(),
|
||||||
colorTypeResult,
|
colorTypeResult,
|
||||||
singleImage,
|
singleImage,
|
||||||
Integer.valueOf(dpi),
|
Integer.valueOf(dpi),
|
||||||
filename);
|
filename);
|
||||||
|
|
||||||
if (result == null || result.length == 0) {
|
if (result == null || result.length == 0) {
|
||||||
logger.error("resultant bytes for {} is null, error converting ", filename);
|
logger.error("resultant bytes for {} is null, error converting ", filename);
|
||||||
}
|
}
|
||||||
|
if (imageFormat.equalsIgnoreCase("webp") && !CheckProgramInstall.isPythonAvailable()) {
|
||||||
|
throw new IOException("Python is not installed. Required for WebP conversion.");
|
||||||
|
} else if (imageFormat.equalsIgnoreCase("webp")
|
||||||
|
&& CheckProgramInstall.isPythonAvailable()) {
|
||||||
|
// Write the output stream to a temp file
|
||||||
|
Path tempFile = Files.createTempFile("temp_png", ".png");
|
||||||
|
try (FileOutputStream fos = new FileOutputStream(tempFile.toFile())) {
|
||||||
|
fos.write(result);
|
||||||
|
fos.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
String pythonVersion = CheckProgramInstall.getAvailablePythonCommand();
|
||||||
|
|
||||||
|
List<String> command = new ArrayList<>();
|
||||||
|
command.add(pythonVersion);
|
||||||
|
command.add("./scripts/png_to_webp.py"); // Python script to handle the conversion
|
||||||
|
|
||||||
|
// Create a temporary directory for the output WebP files
|
||||||
|
Path tempOutputDir = Files.createTempDirectory("webp_output");
|
||||||
|
if (singleImage) {
|
||||||
|
// Run the Python script to convert PNG to WebP
|
||||||
|
command.add(tempFile.toString());
|
||||||
|
command.add(tempOutputDir.toString());
|
||||||
|
command.add("--single");
|
||||||
|
} else {
|
||||||
|
// Save the uploaded PDF to a temporary file
|
||||||
|
Path tempPdfPath = Files.createTempFile("temp_pdf", ".pdf");
|
||||||
|
file.transferTo(tempPdfPath.toFile());
|
||||||
|
// Run the Python script to convert PDF to WebP
|
||||||
|
command.add(tempPdfPath.toString());
|
||||||
|
command.add(tempOutputDir.toString());
|
||||||
|
}
|
||||||
|
command.add("--dpi");
|
||||||
|
command.add(dpi);
|
||||||
|
ProcessExecutorResult resultProcess =
|
||||||
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
|
||||||
|
.runCommandWithOutputHandling(command);
|
||||||
|
|
||||||
|
// Find all WebP files in the output directory
|
||||||
|
List<Path> webpFiles =
|
||||||
|
Files.walk(tempOutputDir)
|
||||||
|
.filter(path -> path.toString().endsWith(".webp"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (webpFiles.isEmpty()) {
|
||||||
|
logger.error("No WebP files were created in: {}", tempOutputDir.toString());
|
||||||
|
throw new IOException("No WebP files were created. " + resultProcess.getMessages());
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bodyBytes = new byte[0];
|
||||||
|
|
||||||
|
if (webpFiles.size() == 1) {
|
||||||
|
// Return the single WebP file directly
|
||||||
|
Path webpFilePath = webpFiles.get(0);
|
||||||
|
bodyBytes = Files.readAllBytes(webpFilePath);
|
||||||
|
} else {
|
||||||
|
// Create a ZIP file containing all WebP images
|
||||||
|
ByteArrayOutputStream zipOutputStream = new ByteArrayOutputStream();
|
||||||
|
try (ZipOutputStream zos = new ZipOutputStream(zipOutputStream)) {
|
||||||
|
for (Path webpFile : webpFiles) {
|
||||||
|
zos.putNextEntry(new ZipEntry(webpFile.getFileName().toString()));
|
||||||
|
Files.copy(webpFile, zos);
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bodyBytes = zipOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
// Clean up the temporary files
|
||||||
|
Files.deleteIfExists(tempFile);
|
||||||
|
if (tempOutputDir != null) FileUtils.deleteDirectory(tempOutputDir.toFile());
|
||||||
|
result = bodyBytes;
|
||||||
|
}
|
||||||
|
|
||||||
if (singleImage) {
|
if (singleImage) {
|
||||||
String docName = filename + "." + imageFormat;
|
String docName = filename + "." + imageFormat;
|
||||||
MediaType mediaType = MediaType.parseMediaType(getMediaType(imageFormat));
|
MediaType mediaType = MediaType.parseMediaType(getMediaType(imageFormat));
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest;
|
import stirling.software.SPDF.model.api.misc.ExtractImageScansRequest;
|
||||||
|
import stirling.software.SPDF.utils.CheckProgramInstall;
|
||||||
import stirling.software.SPDF.utils.ProcessExecutor;
|
import stirling.software.SPDF.utils.ProcessExecutor;
|
||||||
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||||
import stirling.software.SPDF.utils.WebResponseUtils;
|
import stirling.software.SPDF.utils.WebResponseUtils;
|
||||||
@@ -76,6 +77,11 @@ public class ExtractImageScansController {
|
|||||||
Path tempZipFile = null;
|
Path tempZipFile = null;
|
||||||
List<Path> tempDirs = new ArrayList<>();
|
List<Path> tempDirs = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!CheckProgramInstall.isPythonAvailable()) {
|
||||||
|
throw new IOException("Python is not installed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String pythonVersion = CheckProgramInstall.getAvailablePythonCommand();
|
||||||
try {
|
try {
|
||||||
// Check if input file is a PDF
|
// Check if input file is a PDF
|
||||||
if ("pdf".equalsIgnoreCase(extension)) {
|
if ("pdf".equalsIgnoreCase(extension)) {
|
||||||
@@ -117,7 +123,7 @@ public class ExtractImageScansController {
|
|||||||
List<String> command =
|
List<String> command =
|
||||||
new ArrayList<>(
|
new ArrayList<>(
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
"python3",
|
pythonVersion,
|
||||||
"./scripts/split_photos.py",
|
"./scripts/split_photos.py",
|
||||||
images.get(i),
|
images.get(i),
|
||||||
tempDir.toString(),
|
tempDir.toString(),
|
||||||
|
|||||||
@@ -140,6 +140,9 @@ public class ExtractImagesController {
|
|||||||
Set<Integer> processedImages,
|
Set<Integer> processedImages,
|
||||||
ZipOutputStream zos)
|
ZipOutputStream zos)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
if (page.getResources() == null || page.getResources().getXObjectNames() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (COSName name : page.getResources().getXObjectNames()) {
|
for (COSName name : page.getResources().getXObjectNames()) {
|
||||||
if (page.getResources().isImageXObject(name)) {
|
if (page.getResources().isImageXObject(name)) {
|
||||||
PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name);
|
PDImageXObject image = (PDImageXObject) page.getResources().getXObject(name);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class ApiDocService {
|
|||||||
|
|
||||||
Map<String, List<String>> outputToFileTypes = new HashMap<>();
|
Map<String, List<String>> outputToFileTypes = new HashMap<>();
|
||||||
|
|
||||||
public List getExtensionTypes(boolean output, String operationName) {
|
public List<String> getExtensionTypes(boolean output, String operationName) {
|
||||||
if (outputToFileTypes.size() == 0) {
|
if (outputToFileTypes.size() == 0) {
|
||||||
outputToFileTypes.put("PDF", Arrays.asList("pdf"));
|
outputToFileTypes.put("PDF", Arrays.asList("pdf"));
|
||||||
outputToFileTypes.put(
|
outputToFileTypes.put(
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import org.springframework.web.servlet.ModelAndView;
|
|||||||
import io.swagger.v3.oas.annotations.Hidden;
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.utils.CheckProgramInstall;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "Convert", description = "Convert APIs")
|
@Tag(name = "Convert", description = "Convert APIs")
|
||||||
public class ConverterWebController {
|
public class ConverterWebController {
|
||||||
@@ -21,14 +23,6 @@ public class ConverterWebController {
|
|||||||
return "convert/book-to-pdf";
|
return "convert/book-to-pdf";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConditionalOnExpression("#{bookAndHtmlFormatsInstalled}")
|
|
||||||
@GetMapping("/pdf-to-book")
|
|
||||||
@Hidden
|
|
||||||
public String convertPdfToBookForm(Model model) {
|
|
||||||
model.addAttribute("currentPage", "pdf-to-book");
|
|
||||||
return "convert/pdf-to-book";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/img-to-pdf")
|
@GetMapping("/img-to-pdf")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String convertImgToPdfForm(Model model) {
|
public String convertImgToPdfForm(Model model) {
|
||||||
@@ -57,13 +51,6 @@ public class ConverterWebController {
|
|||||||
return "convert/url-to-pdf";
|
return "convert/url-to-pdf";
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/pdf-to-img")
|
|
||||||
@Hidden
|
|
||||||
public String pdfToimgForm(Model model) {
|
|
||||||
model.addAttribute("currentPage", "pdf-to-img");
|
|
||||||
return "convert/pdf-to-img";
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/file-to-pdf")
|
@GetMapping("/file-to-pdf")
|
||||||
@Hidden
|
@Hidden
|
||||||
public String convertToPdfForm(Model model) {
|
public String convertToPdfForm(Model model) {
|
||||||
@@ -73,6 +60,23 @@ public class ConverterWebController {
|
|||||||
|
|
||||||
// PDF TO......
|
// PDF TO......
|
||||||
|
|
||||||
|
@ConditionalOnExpression("#{bookAndHtmlFormatsInstalled}")
|
||||||
|
@GetMapping("/pdf-to-book")
|
||||||
|
@Hidden
|
||||||
|
public String convertPdfToBookForm(Model model) {
|
||||||
|
model.addAttribute("currentPage", "pdf-to-book");
|
||||||
|
return "convert/pdf-to-book";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/pdf-to-img")
|
||||||
|
@Hidden
|
||||||
|
public String pdfToimgForm(Model model) {
|
||||||
|
boolean isPython = CheckProgramInstall.isPythonAvailable();
|
||||||
|
model.addAttribute("isPython", isPython);
|
||||||
|
model.addAttribute("currentPage", "pdf-to-img");
|
||||||
|
return "convert/pdf-to-img";
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/pdf-to-html")
|
@GetMapping("/pdf-to-html")
|
||||||
@Hidden
|
@Hidden
|
||||||
public ModelAndView pdfToHTML() {
|
public ModelAndView pdfToHTML() {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import io.swagger.v3.oas.annotations.Hidden;
|
|||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
import stirling.software.SPDF.utils.CheckProgramInstall;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
@@ -34,6 +35,8 @@ public class OtherWebController {
|
|||||||
@Hidden
|
@Hidden
|
||||||
public ModelAndView extractImageScansForm() {
|
public ModelAndView extractImageScansForm() {
|
||||||
ModelAndView modelAndView = new ModelAndView("misc/extract-image-scans");
|
ModelAndView modelAndView = new ModelAndView("misc/extract-image-scans");
|
||||||
|
boolean isPython = CheckProgramInstall.isPythonAvailable();
|
||||||
|
modelAndView.addObject("isPython", isPython);
|
||||||
modelAndView.addObject("currentPage", "extract-image-scans");
|
modelAndView.addObject("currentPage", "extract-image-scans");
|
||||||
return modelAndView;
|
return modelAndView;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package stirling.software.SPDF.model;
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
@@ -11,7 +13,9 @@ import jakarta.persistence.Table;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "authorities")
|
@Table(name = "authorities")
|
||||||
public class Authority {
|
public class Authority implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public Authority() {}
|
public Authority() {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package stirling.software.SPDF.model;
|
package stirling.software.SPDF.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -23,7 +24,9 @@ import jakarta.persistence.Table;
|
|||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
public class User {
|
public class User implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class ConvertToImageRequest extends PDFFile {
|
|||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "The output image format",
|
description = "The output image format",
|
||||||
allowableValues = {"png", "jpeg", "jpg", "gif"})
|
allowableValues = {"png", "jpeg", "jpg", "gif", "webp"})
|
||||||
private String imageFormat;
|
private String imageFormat;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import lombok.EqualsAndHashCode;
|
|||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class UrlToPdfRequest {
|
public class UrlToPdfRequest {
|
||||||
|
|
||||||
@Schema(description = "The input URL to be converted to a PDF file", required = true)
|
@Schema(
|
||||||
|
description = "The input URL to be converted to a PDF file",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String urlInput;
|
private String urlInput;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFWithPageNums;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class ContainsTextRequest extends PDFWithPageNums {
|
public class ContainsTextRequest extends PDFWithPageNums {
|
||||||
|
|
||||||
@Schema(description = "The text to check for", required = true)
|
@Schema(description = "The text to check for", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String text;
|
private String text;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class FileSizeRequest extends PDFComparison {
|
public class FileSizeRequest extends PDFComparison {
|
||||||
|
|
||||||
@Schema(description = "File Size", required = true)
|
@Schema(description = "File Size", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String fileSize;
|
private String fileSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class PageRotationRequest extends PDFComparison {
|
public class PageRotationRequest extends PDFComparison {
|
||||||
|
|
||||||
@Schema(description = "Rotation in degrees", required = true)
|
@Schema(description = "Rotation in degrees", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private int rotation;
|
private int rotation;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ import stirling.software.SPDF.model.api.PDFComparison;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class PageSizeRequest extends PDFComparison {
|
public class PageSizeRequest extends PDFComparison {
|
||||||
|
|
||||||
@Schema(description = "Standard Page Size", required = true)
|
@Schema(description = "Standard Page Size", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String standardPageSize;
|
private String standardPageSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ public class OverlayPdfsRequest extends PDFFile {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"The mode of overlaying: 'SequentialOverlay' for sequential application, 'InterleavedOverlay' for round-robin application, 'FixedRepeatOverlay' for fixed repetition based on provided counts",
|
"The mode of overlaying: 'SequentialOverlay' for sequential application, 'InterleavedOverlay' for round-robin application, 'FixedRepeatOverlay' for fixed repetition based on provided counts",
|
||||||
required = true)
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String overlayMode;
|
private String overlayMode;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"An array of integers specifying the number of times each corresponding overlay file should be applied in the 'FixedRepeatOverlay' mode. This should match the length of the overlayFiles array.",
|
"An array of integers specifying the number of times each corresponding overlay file should be applied in the 'FixedRepeatOverlay' mode. This should match the length of the overlayFiles array.",
|
||||||
required = false)
|
requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
||||||
private int[] counts;
|
private int[] counts;
|
||||||
|
|
||||||
@Schema(description = "Overlay position 0 is Foregound, 1 is Background")
|
@Schema(description = "Overlay position 0 is Foregound, 1 is Background")
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ public class SplitPdfBySizeOrCountRequest extends PDFFile {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"Determines the type of split: 0 for size, 1 for page count, 2 for document count",
|
"Determines the type of split: 0 for size, 1 for page count, 2 for document count",
|
||||||
required = false,
|
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||||
defaultValue = "0")
|
defaultValue = "0")
|
||||||
private int splitType;
|
private int splitType;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"Value for split: size in MB (e.g., '10MB') or number of pages (e.g., '5')",
|
"Value for split: size in MB (e.g., '10MB') or number of pages (e.g., '5')",
|
||||||
required = false,
|
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||||
defaultValue = "10MB")
|
defaultValue = "10MB")
|
||||||
private String splitValue;
|
private String splitValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class AddStampRequest extends PDFWithPageNums {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description = "The stamp type (text or image)",
|
description = "The stamp type (text or image)",
|
||||||
allowableValues = {"text", "image"},
|
allowableValues = {"text", "image"},
|
||||||
required = true)
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String stampType;
|
private String stampType;
|
||||||
|
|
||||||
@Schema(description = "The stamp text")
|
@Schema(description = "The stamp text")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class AutoSplitPdfRequest extends PDFFile {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"Flag indicating if the duplex mode is active, where the page after the divider also gets removed.",
|
"Flag indicating if the duplex mode is active, where the page after the divider also gets removed.",
|
||||||
required = false,
|
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||||
defaultValue = "false")
|
defaultValue = "false")
|
||||||
private boolean duplexMode;
|
private boolean duplexMode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class ExtractHeaderRequest extends PDFFile {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description =
|
description =
|
||||||
"Flag indicating whether to use the first text as a fallback if no suitable title is found. Defaults to false.",
|
"Flag indicating whether to use the first text as a fallback if no suitable title is found. Defaults to false.",
|
||||||
required = false,
|
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||||
defaultValue = "false")
|
defaultValue = "false")
|
||||||
private boolean useFirstTextAsFallback;
|
private boolean useFirstTextAsFallback;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import lombok.EqualsAndHashCode;
|
|||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
public class ExtractImageScansRequest {
|
public class ExtractImageScansRequest {
|
||||||
@Schema(description = "The input file containing image scans", required = true)
|
@Schema(
|
||||||
|
description = "The input file containing image scans",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private MultipartFile fileInput;
|
private MultipartFile fileInput;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import stirling.software.SPDF.model.api.PDFFile;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class PrintFileRequest extends PDFFile {
|
public class PrintFileRequest extends PDFFile {
|
||||||
|
|
||||||
@Schema(description = "Name of printer to match against", required = true)
|
@Schema(
|
||||||
|
description = "Name of printer to match against",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String printerName;
|
private String printerName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class AddWatermarkRequest extends PDFFile {
|
|||||||
@Schema(
|
@Schema(
|
||||||
description = "The watermark type (text or image)",
|
description = "The watermark type (text or image)",
|
||||||
allowableValues = {"text", "image"},
|
allowableValues = {"text", "image"},
|
||||||
required = true)
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String watermarkType;
|
private String watermarkType;
|
||||||
|
|
||||||
@Schema(description = "The watermark text")
|
@Schema(description = "The watermark text")
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import stirling.software.SPDF.model.api.PDFFile;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class PDFPasswordRequest extends PDFFile {
|
public class PDFPasswordRequest extends PDFFile {
|
||||||
|
|
||||||
@Schema(description = "The password of the PDF file", required = true)
|
@Schema(
|
||||||
|
description = "The password of the PDF file",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String password;
|
private String password;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ import stirling.software.SPDF.model.api.PDFFile;
|
|||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
public class RedactPdfRequest extends PDFFile {
|
public class RedactPdfRequest extends PDFFile {
|
||||||
|
|
||||||
@Schema(description = "List of text to redact from the PDF", type = "string", required = true)
|
@Schema(
|
||||||
|
description = "List of text to redact from the PDF",
|
||||||
|
type = "string",
|
||||||
|
requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private String listOfText;
|
private String listOfText;
|
||||||
|
|
||||||
@Schema(description = "Whether to use regex for the listOfText", defaultValue = "false")
|
@Schema(description = "Whether to use regex for the listOfText", defaultValue = "false")
|
||||||
|
|||||||
@@ -13,5 +13,5 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
|||||||
|
|
||||||
Optional<User> findByUsername(String username);
|
Optional<User> findByUsername(String username);
|
||||||
|
|
||||||
User findByApiKey(String apiKey);
|
Optional<User> findByApiKey(String apiKey);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package stirling.software.SPDF.service;
|
package stirling.software.SPDF.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.pdfbox.cos.COSName;
|
import org.apache.pdfbox.cos.COSName;
|
||||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
@@ -16,7 +18,7 @@ public class PdfImageRemovalService {
|
|||||||
/**
|
/**
|
||||||
* Removes all image objects from the provided PDF document.
|
* Removes all image objects from the provided PDF document.
|
||||||
*
|
*
|
||||||
* This method iterates over each page in the document and removes any image XObjects found
|
* <p>This method iterates over each page in the document and removes any image XObjects found
|
||||||
* in the page's resources.
|
* in the page's resources.
|
||||||
*
|
*
|
||||||
* @param document The PDF document from which images will be removed.
|
* @param document The PDF document from which images will be removed.
|
||||||
@@ -27,14 +29,22 @@ public class PdfImageRemovalService {
|
|||||||
// Iterate over each page in the PDF document
|
// Iterate over each page in the PDF document
|
||||||
for (PDPage page : document.getPages()) {
|
for (PDPage page : document.getPages()) {
|
||||||
PDResources resources = page.getResources();
|
PDResources resources = page.getResources();
|
||||||
|
// Collect the XObject names to remove
|
||||||
|
List<COSName> namesToRemove = new ArrayList<>();
|
||||||
|
|
||||||
// Iterate over all XObject names in the page's resources
|
// Iterate over all XObject names in the page's resources
|
||||||
for (COSName name : resources.getXObjectNames()) {
|
for (COSName name : resources.getXObjectNames()) {
|
||||||
// Check if the XObject is an image
|
// Check if the XObject is an image
|
||||||
if (resources.isImageXObject(name)) {
|
if (resources.isImageXObject(name)) {
|
||||||
// Remove the image XObject by setting it to null
|
// Collect the name for removal
|
||||||
resources.put(name, (PDXObject) null);
|
namesToRemove.add(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now, modify the resources by removing the collected names
|
||||||
|
for (COSName name : namesToRemove) {
|
||||||
|
resources.put(name, (PDXObject) null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package stirling.software.SPDF.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
|
||||||
|
|
||||||
|
public class CheckProgramInstall {
|
||||||
|
|
||||||
|
private static final List<String> PYTHON_COMMANDS = Arrays.asList("python3", "python");
|
||||||
|
private static boolean pythonAvailableChecked = false;
|
||||||
|
private static String availablePythonCommand = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks which Python command is available and returns it.
|
||||||
|
*
|
||||||
|
* @return The available Python command ("python3" or "python"), or null if neither is
|
||||||
|
* available.
|
||||||
|
*/
|
||||||
|
public static String getAvailablePythonCommand() {
|
||||||
|
if (!pythonAvailableChecked) {
|
||||||
|
availablePythonCommand =
|
||||||
|
PYTHON_COMMANDS.stream()
|
||||||
|
.filter(CheckProgramInstall::checkPythonVersion)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
pythonAvailableChecked = true;
|
||||||
|
}
|
||||||
|
return availablePythonCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the specified command is available by running the command with --version.
|
||||||
|
*
|
||||||
|
* @param pythonCommand The Python command to check.
|
||||||
|
* @return true if the command is available, false otherwise.
|
||||||
|
*/
|
||||||
|
private static boolean checkPythonVersion(String pythonCommand) {
|
||||||
|
try {
|
||||||
|
ProcessExecutorResult result =
|
||||||
|
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
|
||||||
|
.runCommandWithOutputHandling(
|
||||||
|
Arrays.asList(pythonCommand, "--version"));
|
||||||
|
return true; // Command succeeded, Python is available
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
return false; // Command failed, Python is not available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if any Python command is available.
|
||||||
|
*
|
||||||
|
* @return true if any Python command is available, false otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isPythonAvailable() {
|
||||||
|
return getAvailablePythonCommand() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,10 @@ import java.io.File;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.file.FileVisitResult;
|
import java.nio.file.FileVisitResult;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -13,8 +16,6 @@ import java.nio.file.SimpleFileVisitor;
|
|||||||
import java.nio.file.attribute.BasicFileAttributes;
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.net.URL;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -73,12 +74,11 @@ public class GeneralUtils {
|
|||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isURLReachable(String urlStr) {
|
public static boolean isURLReachable(String urlStr) {
|
||||||
try {
|
try {
|
||||||
URL url = new URL(urlStr);
|
URL url = URI.create(urlStr).toURL();
|
||||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||||
connection.setRequestMethod("HEAD");
|
connection.setRequestMethod("HEAD");
|
||||||
int responseCode = connection.getResponseCode();
|
int responseCode = connection.getResponseCode();
|
||||||
@@ -112,16 +112,19 @@ public class GeneralUtils {
|
|||||||
sizeStr = sizeStr.replace(",", ".").replace(" ", "");
|
sizeStr = sizeStr.replace(",", ".").replace(" ", "");
|
||||||
try {
|
try {
|
||||||
if (sizeStr.endsWith("KB")) {
|
if (sizeStr.endsWith("KB")) {
|
||||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
|
return (long)
|
||||||
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2)) * 1024);
|
||||||
} else if (sizeStr.endsWith("MB")) {
|
} else if (sizeStr.endsWith("MB")) {
|
||||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
return (long)
|
||||||
* 1024
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
||||||
* 1024);
|
* 1024
|
||||||
|
* 1024);
|
||||||
} else if (sizeStr.endsWith("GB")) {
|
} else if (sizeStr.endsWith("GB")) {
|
||||||
return (long) (Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
return (long)
|
||||||
* 1024
|
(Double.parseDouble(sizeStr.substring(0, sizeStr.length() - 2))
|
||||||
* 1024
|
* 1024
|
||||||
* 1024);
|
* 1024
|
||||||
|
* 1024);
|
||||||
} else if (sizeStr.endsWith("B")) {
|
} else if (sizeStr.endsWith("B")) {
|
||||||
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
|
return Long.parseLong(sizeStr.substring(0, sizeStr.length() - 1));
|
||||||
} else {
|
} else {
|
||||||
@@ -191,8 +194,7 @@ public class GeneralUtils {
|
|||||||
|
|
||||||
// Check if the result is null or not within bounds
|
// Check if the result is null or not within bounds
|
||||||
if (result == null || result <= 0 || result.intValue() > maxValue) {
|
if (result == null || result <= 0 || result.intValue() > maxValue) {
|
||||||
if (n != 0)
|
if (n != 0) break;
|
||||||
break;
|
|
||||||
} else {
|
} else {
|
||||||
results.add(result.intValue());
|
results.add(result.intValue());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
multipart.enabled=true
|
multipart.enabled=true
|
||||||
|
|
||||||
|
logging.level.org.springframework=WARN
|
||||||
|
logging.level.org.hibernate=WARN
|
||||||
|
logging.level.org.eclipse.jetty=WARN
|
||||||
|
logging.level.com.zaxxer.hikari=WARN
|
||||||
|
|
||||||
|
spring.jpa.open-in-view=false
|
||||||
|
|
||||||
server.forward-headers-strategy=NATIVE
|
server.forward-headers-strategy=NATIVE
|
||||||
|
|
||||||
@@ -24,10 +30,8 @@ spring.devtools.livereload.enabled=true
|
|||||||
|
|
||||||
spring.thymeleaf.encoding=UTF-8
|
spring.thymeleaf.encoding=UTF-8
|
||||||
|
|
||||||
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:20m}
|
|
||||||
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
|
|
||||||
|
|
||||||
spring.resources.static-locations=file:customFiles/static/
|
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
|
||||||
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
|
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/
|
||||||
#spring.thymeleaf.cache=false
|
#spring.thymeleaf.cache=false
|
||||||
|
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=الحد الأدنى لمنطقة المحيط:
|
|||||||
ScannerImageSplit.selectText.8=تعيين الحد الأدنى لمنطقة المحيط للصورة
|
ScannerImageSplit.selectText.8=تعيين الحد الأدنى لمنطقة المحيط للصورة
|
||||||
ScannerImageSplit.selectText.9=حجم الحدود:
|
ScannerImageSplit.selectText.9=حجم الحدود:
|
||||||
ScannerImageSplit.selectText.10=يضبط حجم الحدود المضافة والمزالة لمنع الحدود البيضاء في الإخراج (الافتراضي: 1).
|
ScannerImageSplit.selectText.10=يضبط حجم الحدود المضافة والمزالة لمنع الحدود البيضاء في الإخراج (الافتراضي: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=اللون
|
|||||||
pdfToImage.grey=تدرج الرمادي
|
pdfToImage.grey=تدرج الرمادي
|
||||||
pdfToImage.blackwhite=أبيض وأسود (قد يفقد البيانات!)
|
pdfToImage.blackwhite=أبيض وأسود (قد يفقد البيانات!)
|
||||||
pdfToImage.submit=تحول
|
pdfToImage.submit=تحول
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Минимална контурна площ:
|
|||||||
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
ScannerImageSplit.selectText.8=Задава минималния праг на контурната площ за изображение
|
||||||
ScannerImageSplit.selectText.9=Размер на рамката:
|
ScannerImageSplit.selectText.9=Размер на рамката:
|
||||||
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Цвят
|
|||||||
pdfToImage.grey=Скала на сивото
|
pdfToImage.grey=Скала на сивото
|
||||||
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
pdfToImage.blackwhite=Черно и бяло (може да загубите данни!)
|
||||||
pdfToImage.submit=Преобразуване
|
pdfToImage.submit=Преобразуване
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Àrea de contorn mínima:
|
|||||||
ScannerImageSplit.selectText.8=Estableix el llindar mínim de l'àrea de contorn per a una foto
|
ScannerImageSplit.selectText.8=Estableix el llindar mínim de l'àrea de contorn per a una foto
|
||||||
ScannerImageSplit.selectText.9=Mida Vora:
|
ScannerImageSplit.selectText.9=Mida Vora:
|
||||||
ScannerImageSplit.selectText.10=Estableix la mida de la vora afegida i eliminada per evitar vores blanques a la sortida (per defecte: 1).
|
ScannerImageSplit.selectText.10=Estableix la mida de la vora afegida i eliminada per evitar vores blanques a la sortida (per defecte: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Color
|
|||||||
pdfToImage.grey=Escala de Grisos
|
pdfToImage.grey=Escala de Grisos
|
||||||
pdfToImage.blackwhite=Blanc i Negre (Pot perdre dades!)
|
pdfToImage.blackwhite=Blanc i Negre (Pot perdre dades!)
|
||||||
pdfToImage.submit=Converteix
|
pdfToImage.submit=Converteix
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimální plocha kontury:
|
|||||||
ScannerImageSplit.selectText.8=Nastaví minimální plošný práh kontury pro fotografii
|
ScannerImageSplit.selectText.8=Nastaví minimální plošný práh kontury pro fotografii
|
||||||
ScannerImageSplit.selectText.9=Velikost okraje:
|
ScannerImageSplit.selectText.9=Velikost okraje:
|
||||||
ScannerImageSplit.selectText.10=Nastaví velikost okraje přidaného a odebraného k zabránění bílých ohraničení ve výstupu (výchozí: 1).
|
ScannerImageSplit.selectText.10=Nastaví velikost okraje přidaného a odebraného k zabránění bílých ohraničení ve výstupu (výchozí: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Barevný
|
|||||||
pdfToImage.grey=Stupně šedi
|
pdfToImage.grey=Stupně šedi
|
||||||
pdfToImage.blackwhite=Černobílý (Může dojít k ztrátě dat!)
|
pdfToImage.blackwhite=Černobílý (Může dojít k ztrátě dat!)
|
||||||
pdfToImage.submit=Převést
|
pdfToImage.submit=Převést
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
|
|||||||
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||||
ScannerImageSplit.selectText.9=Border Size:
|
ScannerImageSplit.selectText.9=Border Size:
|
||||||
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Colour
|
|||||||
pdfToImage.grey=Greyscale
|
pdfToImage.grey=Greyscale
|
||||||
pdfToImage.blackwhite=Black and White (May lose data!)
|
pdfToImage.blackwhite=Black and White (May lose data!)
|
||||||
pdfToImage.submit=Convert
|
pdfToImage.submit=Convert
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimaler Konturbereich:
|
|||||||
ScannerImageSplit.selectText.8=Legt den minimalen Konturbereichsschwellenwert für ein Foto fest
|
ScannerImageSplit.selectText.8=Legt den minimalen Konturbereichsschwellenwert für ein Foto fest
|
||||||
ScannerImageSplit.selectText.9=Randgröße:
|
ScannerImageSplit.selectText.9=Randgröße:
|
||||||
ScannerImageSplit.selectText.10=Legt die Größe des hinzugefügten und entfernten Randes fest, um weiße Ränder in der Ausgabe zu verhindern (Standard: 1).
|
ScannerImageSplit.selectText.10=Legt die Größe des hinzugefügten und entfernten Randes fest, um weiße Ränder in der Ausgabe zu verhindern (Standard: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Farbe
|
|||||||
pdfToImage.grey=Graustufen
|
pdfToImage.grey=Graustufen
|
||||||
pdfToImage.blackwhite=Schwarzweiß (Datenverlust möglich!)
|
pdfToImage.blackwhite=Schwarzweiß (Datenverlust möglich!)
|
||||||
pdfToImage.submit=Umwandeln
|
pdfToImage.submit=Umwandeln
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Ελάχιστη επιφάνεια περιγρ
|
|||||||
ScannerImageSplit.selectText.8=Ρυθμίζει το ελάχιστο όριο περιγράμματος για μια φωτογραφία
|
ScannerImageSplit.selectText.8=Ρυθμίζει το ελάχιστο όριο περιγράμματος για μια φωτογραφία
|
||||||
ScannerImageSplit.selectText.9=Μέγεθος περιγράμματος:
|
ScannerImageSplit.selectText.9=Μέγεθος περιγράμματος:
|
||||||
ScannerImageSplit.selectText.10=Ορίζει το μέγεθος του περιγράμματος που προστίθεται και αφαιρείται για να αποτρέπονται λευκά περιγράμματα στην έξοδο (προεπιλογή: 1).
|
ScannerImageSplit.selectText.10=Ορίζει το μέγεθος του περιγράμματος που προστίθεται και αφαιρείται για να αποτρέπονται λευκά περιγράμματα στην έξοδο (προεπιλογή: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Χρώμα
|
|||||||
pdfToImage.grey=Κλίμακα του γκρι
|
pdfToImage.grey=Κλίμακα του γκρι
|
||||||
pdfToImage.blackwhite=Ασπρόμαυρο (Μπορεί να χαθούν δεδομένα!)
|
pdfToImage.blackwhite=Ασπρόμαυρο (Μπορεί να χαθούν δεδομένα!)
|
||||||
pdfToImage.submit=Μετατροπή
|
pdfToImage.submit=Μετατροπή
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
|
|||||||
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||||
ScannerImageSplit.selectText.9=Border Size:
|
ScannerImageSplit.selectText.9=Border Size:
|
||||||
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Colour
|
|||||||
pdfToImage.grey=Greyscale
|
pdfToImage.grey=Greyscale
|
||||||
pdfToImage.blackwhite=Black and White (May lose data!)
|
pdfToImage.blackwhite=Black and White (May lose data!)
|
||||||
pdfToImage.submit=Convert
|
pdfToImage.submit=Convert
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
@@ -1147,4 +1149,4 @@ error.discordSubmit=Discord - Submit Support post
|
|||||||
removeImage.title=Remove image
|
removeImage.title=Remove image
|
||||||
removeImage.header=Remove image
|
removeImage.header=Remove image
|
||||||
removeImage.removeImage=Remove image
|
removeImage.removeImage=Remove image
|
||||||
removeImage.submit=Remove image
|
removeImage.submit=Remove image
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Contour Area:
|
|||||||
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||||
ScannerImageSplit.selectText.9=Border Size:
|
ScannerImageSplit.selectText.9=Border Size:
|
||||||
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Color
|
|||||||
pdfToImage.grey=Grayscale
|
pdfToImage.grey=Grayscale
|
||||||
pdfToImage.blackwhite=Black and White (May lose data!)
|
pdfToImage.blackwhite=Black and White (May lose data!)
|
||||||
pdfToImage.submit=Convert
|
pdfToImage.submit=Convert
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Área mínima de contorno:
|
|||||||
ScannerImageSplit.selectText.8=Establecer el umbral mínimo del área de contorno para una foto
|
ScannerImageSplit.selectText.8=Establecer el umbral mínimo del área de contorno para una foto
|
||||||
ScannerImageSplit.selectText.9=Tamaño del borde:
|
ScannerImageSplit.selectText.9=Tamaño del borde:
|
||||||
ScannerImageSplit.selectText.10=Establece el tamaño del borde agregado y eliminado para evitar bordes blancos en la salida (predeterminado: 1).
|
ScannerImageSplit.selectText.10=Establece el tamaño del borde agregado y eliminado para evitar bordes blancos en la salida (predeterminado: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Color
|
|||||||
pdfToImage.grey=Escala de grises
|
pdfToImage.grey=Escala de grises
|
||||||
pdfToImage.blackwhite=Blanco y Negro (¡Puede perder datos!)
|
pdfToImage.blackwhite=Blanco y Negro (¡Puede perder datos!)
|
||||||
pdfToImage.submit=Convertir
|
pdfToImage.submit=Convertir
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Inguruko area gutxienekoa:
|
|||||||
ScannerImageSplit.selectText.8=Ezarri inguruko arearen gutxieneko balioa argazki batentzat
|
ScannerImageSplit.selectText.8=Ezarri inguruko arearen gutxieneko balioa argazki batentzat
|
||||||
ScannerImageSplit.selectText.9=Ertzaren tamaina:
|
ScannerImageSplit.selectText.9=Ertzaren tamaina:
|
||||||
ScannerImageSplit.selectText.10=Ezarri gehitutako eta ezabatutako ertzaren tamaina irteeran ertz zuriak saihesteko (lehenetsia: 1).
|
ScannerImageSplit.selectText.10=Ezarri gehitutako eta ezabatutako ertzaren tamaina irteeran ertz zuriak saihesteko (lehenetsia: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Kolorea
|
|||||||
pdfToImage.grey=Gris-eskala
|
pdfToImage.grey=Gris-eskala
|
||||||
pdfToImage.blackwhite=Zuria eta Beltza (Datuak galdu ditzake!)
|
pdfToImage.blackwhite=Zuria eta Beltza (Datuak galdu ditzake!)
|
||||||
pdfToImage.submit=Bihurtu
|
pdfToImage.submit=Bihurtu
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Surface de contour minimale
|
|||||||
ScannerImageSplit.selectText.8=Définit la surface de contour minimale pour une photo (par défaut : 500).
|
ScannerImageSplit.selectText.8=Définit la surface de contour minimale pour une photo (par défaut : 500).
|
||||||
ScannerImageSplit.selectText.9=Taille de la bordure
|
ScannerImageSplit.selectText.9=Taille de la bordure
|
||||||
ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut : 1).
|
ScannerImageSplit.selectText.10=Définit la taille de la bordure ajoutée et supprimée pour éviter les bordures blanches dans la sortie (par défaut : 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Couleur
|
|||||||
pdfToImage.grey=Niveaux de gris
|
pdfToImage.grey=Niveaux de gris
|
||||||
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
pdfToImage.blackwhite=Noir et blanc (peut engendrer une perte de données !)
|
||||||
pdfToImage.submit=Convertir
|
pdfToImage.submit=Convertir
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Íos-Limistéar Comhrianta:
|
|||||||
ScannerImageSplit.selectText.8=Socraíonn sé an tairseach íosta achar comhrianta le haghaidh grianghraf
|
ScannerImageSplit.selectText.8=Socraíonn sé an tairseach íosta achar comhrianta le haghaidh grianghraf
|
||||||
ScannerImageSplit.selectText.9=Méid na Teorann:
|
ScannerImageSplit.selectText.9=Méid na Teorann:
|
||||||
ScannerImageSplit.selectText.10=Socraíonn sé méid na teorann a chuirtear leis agus a bhaintear chun teorainneacha bán a chosc san aschur (réamhshocraithe: 1).
|
ScannerImageSplit.selectText.10=Socraíonn sé méid na teorann a chuirtear leis agus a bhaintear chun teorainneacha bán a chosc san aschur (réamhshocraithe: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Dath
|
|||||||
pdfToImage.grey=Scála Liath
|
pdfToImage.grey=Scála Liath
|
||||||
pdfToImage.blackwhite=Dubh agus Bán (D’fhéadfadh sonraí a chailleadh!)
|
pdfToImage.blackwhite=Dubh agus Bán (D’fhéadfadh sonraí a chailleadh!)
|
||||||
pdfToImage.submit=Tiontaigh
|
pdfToImage.submit=Tiontaigh
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=न्यूनतम कंटोर क्ष
|
|||||||
ScannerImageSplit.selectText.8=फोटो के लिए न्यूनतम कंटोर क्षेत्र थ्रेशोल्ड को सेट करता है।
|
ScannerImageSplit.selectText.8=फोटो के लिए न्यूनतम कंटोर क्षेत्र थ्रेशोल्ड को सेट करता है।
|
||||||
ScannerImageSplit.selectText.9=बॉर्डर का आकार:
|
ScannerImageSplit.selectText.9=बॉर्डर का आकार:
|
||||||
ScannerImageSplit.selectText.10=निकालने और जोड़ने के लिए जोड़ा जाने वाला बॉर्डर का आकार सेट करता है ताकि आउटपुट में सफेद बॉर्डर न आए (डिफ़ॉल्ट: 1)।
|
ScannerImageSplit.selectText.10=निकालने और जोड़ने के लिए जोड़ा जाने वाला बॉर्डर का आकार सेट करता है ताकि आउटपुट में सफेद बॉर्डर न आए (डिफ़ॉल्ट: 1)।
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=रंगीन
|
|||||||
pdfToImage.grey=ग्रे स्केल
|
pdfToImage.grey=ग्रे स्केल
|
||||||
pdfToImage.blackwhite=काला और सफेद (डेटा खो सकता है!)
|
pdfToImage.blackwhite=काला और सफेद (डेटा खो सकता है!)
|
||||||
pdfToImage.submit=परिवर्तित करें
|
pdfToImage.submit=परिवर्तित करें
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalna konturna površina:
|
|||||||
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
|
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
|
||||||
ScannerImageSplit.selectText.9=Veličina obruba:
|
ScannerImageSplit.selectText.9=Veličina obruba:
|
||||||
ScannerImageSplit.selectText.10=Postavlja veličinu obruba koji se dodaje i uklanja kako bi se spriječili bijeli obrubi u ispisu (zadano: 1).
|
ScannerImageSplit.selectText.10=Postavlja veličinu obruba koji se dodaje i uklanja kako bi se spriječili bijeli obrubi u ispisu (zadano: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Boja
|
|||||||
pdfToImage.grey=Sivi tonovi
|
pdfToImage.grey=Sivi tonovi
|
||||||
pdfToImage.blackwhite=Crno-bijelo (mogu se izgubiti podaci!)
|
pdfToImage.blackwhite=Crno-bijelo (mogu se izgubiti podaci!)
|
||||||
pdfToImage.submit=Pretvori
|
pdfToImage.submit=Pretvori
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimális kontúr terület:
|
|||||||
ScannerImageSplit.selectText.8=A fotók minimális kontúrterületének beállítása
|
ScannerImageSplit.selectText.8=A fotók minimális kontúrterületének beállítása
|
||||||
ScannerImageSplit.selectText.9=Keret mérete:
|
ScannerImageSplit.selectText.9=Keret mérete:
|
||||||
ScannerImageSplit.selectText.10=A hozzáadott és eltávolított keret méretének beállítása a fehér keretek elkerülése érdekében a kimeneten (alapértelmezett: 1).
|
ScannerImageSplit.selectText.10=A hozzáadott és eltávolított keret méretének beállítása a fehér keretek elkerülése érdekében a kimeneten (alapértelmezett: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=színes
|
|||||||
pdfToImage.grey=szürkeárnyalatos
|
pdfToImage.grey=szürkeárnyalatos
|
||||||
pdfToImage.blackwhite=fekete-fehér (adatvesztéssel járhat!)
|
pdfToImage.blackwhite=fekete-fehér (adatvesztéssel járhat!)
|
||||||
pdfToImage.submit=Átalakítás
|
pdfToImage.submit=Átalakítás
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Area Kontur Minimum:
|
|||||||
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk foto
|
||||||
ScannerImageSplit.selectText.9=Ukuran Batas:
|
ScannerImageSplit.selectText.9=Ukuran Batas:
|
||||||
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Warna
|
|||||||
pdfToImage.grey=Skala abu-abu
|
pdfToImage.grey=Skala abu-abu
|
||||||
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
pdfToImage.blackwhite=Black and White (Bisa kehilangan data!)
|
||||||
pdfToImage.submit=Konversi
|
pdfToImage.submit=Konversi
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ userNotFoundMessage=Utente non trovato.
|
|||||||
incorrectPasswordMessage=La password attuale non è corretta.
|
incorrectPasswordMessage=La password attuale non è corretta.
|
||||||
usernameExistsMessage=Il nuovo nome utente esiste già.
|
usernameExistsMessage=Il nuovo nome utente esiste già.
|
||||||
invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
|
invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
|
||||||
invalidPasswordMessage=The password must not be empty and must not have spaces at the beginning or end.
|
invalidPasswordMessage=La password non deve essere vuota e non deve contenere spazi all'inizio o alla fine.
|
||||||
confirmPasswordErrorMessage=La nuova password e la conferma della nuova password devono corrispondere.
|
confirmPasswordErrorMessage=La nuova password e la conferma della nuova password devono corrispondere.
|
||||||
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
|
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
|
||||||
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
|
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
|
||||||
@@ -179,7 +179,7 @@ adminUserSettings.user=Utente
|
|||||||
adminUserSettings.addUser=Aggiungi un nuovo Utente
|
adminUserSettings.addUser=Aggiungi un nuovo Utente
|
||||||
adminUserSettings.deleteUser=Elimina utente
|
adminUserSettings.deleteUser=Elimina utente
|
||||||
adminUserSettings.confirmDeleteUser=L'utente deve essere eliminato?
|
adminUserSettings.confirmDeleteUser=L'utente deve essere eliminato?
|
||||||
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
adminUserSettings.confirmChangeUserStatus=L'utente dovrebbe essere disabilitato/abilitato?
|
||||||
adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
|
adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
|
||||||
adminUserSettings.roles=Ruoli
|
adminUserSettings.roles=Ruoli
|
||||||
adminUserSettings.role=Ruolo
|
adminUserSettings.role=Ruolo
|
||||||
@@ -193,13 +193,13 @@ adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password a
|
|||||||
adminUserSettings.submit=Salva utente
|
adminUserSettings.submit=Salva utente
|
||||||
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
|
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
|
||||||
adminUserSettings.authenticated=Autenticato
|
adminUserSettings.authenticated=Autenticato
|
||||||
adminUserSettings.editOwnProfil=Edit own profile
|
adminUserSettings.editOwnProfil=Modifica il tuo profilo
|
||||||
adminUserSettings.enabledUser=enabled user
|
adminUserSettings.enabledUser=utente abilitato
|
||||||
adminUserSettings.disabledUser=disabled user
|
adminUserSettings.disabledUser=utente disabilitato
|
||||||
adminUserSettings.activeUsers=Active Users:
|
adminUserSettings.activeUsers=Utenti attivi:
|
||||||
adminUserSettings.disabledUsers=Disabled Users:
|
adminUserSettings.disabledUsers=Utenti disabili:
|
||||||
adminUserSettings.totalUsers=Total Users:
|
adminUserSettings.totalUsers=Utenti totali:
|
||||||
adminUserSettings.lastRequest=Last Request
|
adminUserSettings.lastRequest=Ultima richiesta
|
||||||
|
|
||||||
|
|
||||||
database.title=Importazione/Esportazione database
|
database.title=Importazione/Esportazione database
|
||||||
@@ -491,14 +491,14 @@ login.locked=Il tuo account è stato bloccato.
|
|||||||
login.signinTitle=Per favore accedi
|
login.signinTitle=Per favore accedi
|
||||||
login.ssoSignIn=Accedi tramite Single Sign-on
|
login.ssoSignIn=Accedi tramite Single Sign-on
|
||||||
login.oauth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
|
login.oauth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
|
||||||
login.oauth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
login.oauth2AdminBlockedUser=La registrazione o l'accesso degli utenti non registrati è attualmente bloccata. Si prega di contattare l'amministratore.
|
||||||
login.oauth2RequestNotFound=Richiesta di autorizzazione non trovata
|
login.oauth2RequestNotFound=Richiesta di autorizzazione non trovata
|
||||||
login.oauth2InvalidUserInfoResponse=Risposta relativa alle informazioni utente non valida
|
login.oauth2InvalidUserInfoResponse=Risposta relativa alle informazioni utente non valida
|
||||||
login.oauth2invalidRequest=Richiesta non valida
|
login.oauth2invalidRequest=Richiesta non valida
|
||||||
login.oauth2AccessDenied=Accesso negato
|
login.oauth2AccessDenied=Accesso negato
|
||||||
login.oauth2InvalidTokenResponse=Risposta token non valida
|
login.oauth2InvalidTokenResponse=Risposta token non valida
|
||||||
login.oauth2InvalidIdToken=Id Token non valido
|
login.oauth2InvalidIdToken=Id Token non valido
|
||||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
login.userIsDisabled=L'utente è disattivato, l'accesso è attualmente bloccato con questo nome utente. Si prega di contattare l'amministratore.
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Area di contorno minima:
|
|||||||
ScannerImageSplit.selectText.8=Imposta l'area minima del contorno di una foto
|
ScannerImageSplit.selectText.8=Imposta l'area minima del contorno di una foto
|
||||||
ScannerImageSplit.selectText.9=Spessore bordo:
|
ScannerImageSplit.selectText.9=Spessore bordo:
|
||||||
ScannerImageSplit.selectText.10=Imposta lo spessore del bordo aggiunto o rimosso per prevenire bordi bianchi nel risultato (predefinito: 1).
|
ScannerImageSplit.selectText.10=Imposta lo spessore del bordo aggiunto o rimosso per prevenire bordi bianchi nel risultato (predefinito: 1).
|
||||||
|
ScannerImageSplit.info=Python non è installato. È necessario per l'esecuzione.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=A colori
|
|||||||
pdfToImage.grey=Scala di grigi
|
pdfToImage.grey=Scala di grigi
|
||||||
pdfToImage.blackwhite=Bianco e Nero (potresti perdere dettagli!)
|
pdfToImage.blackwhite=Bianco e Nero (potresti perdere dettagli!)
|
||||||
pdfToImage.submit=Converti
|
pdfToImage.submit=Converti
|
||||||
|
pdfToImage.info=Python non è installato.È richiesto per la conversione WebP.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小輪郭面積:
|
|||||||
ScannerImageSplit.selectText.8=画像の最小の輪郭面積のしきい値を設定。
|
ScannerImageSplit.selectText.8=画像の最小の輪郭面積のしきい値を設定。
|
||||||
ScannerImageSplit.selectText.9=境界線サイズ:
|
ScannerImageSplit.selectText.9=境界線サイズ:
|
||||||
ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定 (初期値:1)。
|
ScannerImageSplit.selectText.10=出力に白い縁取りが出ないように追加・削除される境界線の大きさを設定 (初期値:1)。
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=カラー
|
|||||||
pdfToImage.grey=グレースケール
|
pdfToImage.grey=グレースケール
|
||||||
pdfToImage.blackwhite=白黒 (データが失われる可能性があります!)
|
pdfToImage.blackwhite=白黒 (データが失われる可能性があります!)
|
||||||
pdfToImage.submit=変換
|
pdfToImage.submit=変換
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=최소 윤곽 영역:
|
|||||||
ScannerImageSplit.selectText.8=사진의 최소 윤곽선 영역 임계값을 설정합니다.
|
ScannerImageSplit.selectText.8=사진의 최소 윤곽선 영역 임계값을 설정합니다.
|
||||||
ScannerImageSplit.selectText.9=테두리 크기:
|
ScannerImageSplit.selectText.9=테두리 크기:
|
||||||
ScannerImageSplit.selectText.10=출력에서 흰색 테두리를 방지하기 위해 추가 및 제거되는 테두리의 크기를 설정합니다(기본값: 1).
|
ScannerImageSplit.selectText.10=출력에서 흰색 테두리를 방지하기 위해 추가 및 제거되는 테두리의 크기를 설정합니다(기본값: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=컬러
|
|||||||
pdfToImage.grey=그레이스케일
|
pdfToImage.grey=그레이스케일
|
||||||
pdfToImage.blackwhite=흑백 (데이터 손실 가능성 있음!)
|
pdfToImage.blackwhite=흑백 (데이터 손실 가능성 있음!)
|
||||||
pdfToImage.submit=변환
|
pdfToImage.submit=변환
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum contour oppervlakte:
|
|||||||
ScannerImageSplit.selectText.8=Stelt de minimale contour oppervlakte drempel in voor een foto
|
ScannerImageSplit.selectText.8=Stelt de minimale contour oppervlakte drempel in voor een foto
|
||||||
ScannerImageSplit.selectText.9=Randgrootte:
|
ScannerImageSplit.selectText.9=Randgrootte:
|
||||||
ScannerImageSplit.selectText.10=Stelt de grootte van de toegevoegde en verwijderde rand in om witte randen in de uitvoer te voorkomen (standaard: 1).
|
ScannerImageSplit.selectText.10=Stelt de grootte van de toegevoegde en verwijderde rand in om witte randen in de uitvoer te voorkomen (standaard: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Kleur
|
|||||||
pdfToImage.grey=Grijstinten
|
pdfToImage.grey=Grijstinten
|
||||||
pdfToImage.blackwhite=Zwart en wit (kan data verliezen!)
|
pdfToImage.blackwhite=Zwart en wit (kan data verliezen!)
|
||||||
pdfToImage.submit=Omzetten
|
pdfToImage.submit=Omzetten
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimumskonturområde:
|
|||||||
ScannerImageSplit.selectText.8=Angir minimumskonturområde terskel for et bilde
|
ScannerImageSplit.selectText.8=Angir minimumskonturområde terskel for et bilde
|
||||||
ScannerImageSplit.selectText.9=Kantstørrelse:
|
ScannerImageSplit.selectText.9=Kantstørrelse:
|
||||||
ScannerImageSplit.selectText.10=Angir størrelsen på kanten som legges til og fjernes for å forhindre hvite kanter i utdataen (standard: 1).
|
ScannerImageSplit.selectText.10=Angir størrelsen på kanten som legges til og fjernes for å forhindre hvite kanter i utdataen (standard: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Farge
|
|||||||
pdfToImage.grey=Gråtone
|
pdfToImage.grey=Gråtone
|
||||||
pdfToImage.blackwhite=Svart-hvitt (kan miste data!)
|
pdfToImage.blackwhite=Svart-hvitt (kan miste data!)
|
||||||
pdfToImage.submit=Konverter
|
pdfToImage.submit=Konverter
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalny obszar konturu:
|
|||||||
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
ScannerImageSplit.selectText.8=Ustawia próg minimalnego obszaru konturu dla zdjęcia
|
||||||
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
ScannerImageSplit.selectText.9=Rozmiar obramowania:
|
||||||
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
ScannerImageSplit.selectText.10=Ustawia rozmiar dodawanego i usuwanego obramowania, aby uniknąć białych obramowań na wyjściu (domyślnie: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Kolor
|
|||||||
pdfToImage.grey=Odcień szarości
|
pdfToImage.grey=Odcień szarości
|
||||||
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
pdfToImage.blackwhite=Czarno-biały (może spowodować utratę danych!)
|
||||||
pdfToImage.submit=Konwertuj
|
pdfToImage.submit=Konwertuj
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Área mínima de contorno:
|
|||||||
ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
|
ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para uma foto
|
||||||
ScannerImageSplit.selectText.9=Tamanho do contorno:
|
ScannerImageSplit.selectText.9=Tamanho do contorno:
|
||||||
ScannerImageSplit.selectText.10=Define o tamanho do contorno adicionado e removido para evitar contornos brancos na saída (padrão: 1).
|
ScannerImageSplit.selectText.10=Define o tamanho do contorno adicionado e removido para evitar contornos brancos na saída (padrão: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Colorida
|
|||||||
pdfToImage.grey=Escala de Cinza
|
pdfToImage.grey=Escala de Cinza
|
||||||
pdfToImage.blackwhite=Preto e Branco (pode resultar em perda de dados!)
|
pdfToImage.blackwhite=Preto e Branco (pode resultar em perda de dados!)
|
||||||
pdfToImage.submit=Converter
|
pdfToImage.submit=Converter
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Arie minimă a conturului:
|
|||||||
ScannerImageSplit.selectText.8=Stabilește pragul minim de arie a conturului pentru o fotografie.
|
ScannerImageSplit.selectText.8=Stabilește pragul minim de arie a conturului pentru o fotografie.
|
||||||
ScannerImageSplit.selectText.9=Mărimea marginii:
|
ScannerImageSplit.selectText.9=Mărimea marginii:
|
||||||
ScannerImageSplit.selectText.10=Stabilește mărimea marginii adăugate și eliminate pentru a evita marginile albe în rezultat (implicit: 1).
|
ScannerImageSplit.selectText.10=Stabilește mărimea marginii adăugate și eliminate pentru a evita marginile albe în rezultat (implicit: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Culoare
|
|||||||
pdfToImage.grey=Scală de gri
|
pdfToImage.grey=Scală de gri
|
||||||
pdfToImage.blackwhite=Alb și negru (Poate pierde date!)
|
pdfToImage.blackwhite=Alb și negru (Poate pierde date!)
|
||||||
pdfToImage.submit=Convertă
|
pdfToImage.submit=Convertă
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Минимальная площадь конту
|
|||||||
ScannerImageSplit.selectText.8=Устанавливает минимальный порог области контура для фотографии
|
ScannerImageSplit.selectText.8=Устанавливает минимальный порог области контура для фотографии
|
||||||
ScannerImageSplit.selectText.9=Размер границы:
|
ScannerImageSplit.selectText.9=Размер границы:
|
||||||
ScannerImageSplit.selectText.10=Устанавливает размер добавляемой и удаляемой границы, чтобы предотвратить появление белых границ на выходе (по умолчанию: 1).
|
ScannerImageSplit.selectText.10=Устанавливает размер добавляемой и удаляемой границы, чтобы предотвратить появление белых границ на выходе (по умолчанию: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Цвет
|
|||||||
pdfToImage.grey=Оттенки серого
|
pdfToImage.grey=Оттенки серого
|
||||||
pdfToImage.blackwhite=Черно-белый (может потерять данные!)
|
pdfToImage.blackwhite=Черно-белый (может потерять данные!)
|
||||||
pdfToImage.submit=Конвертировать
|
pdfToImage.submit=Конвертировать
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimálna plocha obrysu:
|
|||||||
ScannerImageSplit.selectText.8=Nastaví minimálnu prahovú hodnotu plochy obrysu pre fotografiu
|
ScannerImageSplit.selectText.8=Nastaví minimálnu prahovú hodnotu plochy obrysu pre fotografiu
|
||||||
ScannerImageSplit.selectText.9=Veľkosť okraja:
|
ScannerImageSplit.selectText.9=Veľkosť okraja:
|
||||||
ScannerImageSplit.selectText.10=Nastaví veľkosť okraja pridaného a odstráneného, aby sa zabránilo bielym okrajom vo výstupe (predvolené: 1).
|
ScannerImageSplit.selectText.10=Nastaví veľkosť okraja pridaného a odstráneného, aby sa zabránilo bielym okrajom vo výstupe (predvolené: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Farba
|
|||||||
pdfToImage.grey=Odtiene šedej
|
pdfToImage.grey=Odtiene šedej
|
||||||
pdfToImage.blackwhite=Čierno-biele (Môže stratiť údaje!)
|
pdfToImage.blackwhite=Čierno-biele (Môže stratiť údaje!)
|
||||||
pdfToImage.submit=Konvertovať
|
pdfToImage.submit=Konvertovať
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimalna površina konture:
|
|||||||
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
|
ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fotografiju
|
||||||
ScannerImageSplit.selectText.9=Veličina ivice:
|
ScannerImageSplit.selectText.9=Veličina ivice:
|
||||||
ScannerImageSplit.selectText.10=Postavlja veličinu ivice dodate i uklonjene kako bi se sprečile bele ivice u izlazu (podrazumevano: 1).
|
ScannerImageSplit.selectText.10=Postavlja veličinu ivice dodate i uklonjene kako bi se sprečile bele ivice u izlazu (podrazumevano: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Boja
|
|||||||
pdfToImage.grey=Nijanse sive
|
pdfToImage.grey=Nijanse sive
|
||||||
pdfToImage.blackwhite=Crno-belo (Može izgubiti podatke!)
|
pdfToImage.blackwhite=Crno-belo (Može izgubiti podatke!)
|
||||||
pdfToImage.submit=Konvertuj
|
pdfToImage.submit=Konvertuj
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minsta konturarea:
|
|||||||
ScannerImageSplit.selectText.8=Ställer in minsta tröskelvärde för konturarea för ett foto
|
ScannerImageSplit.selectText.8=Ställer in minsta tröskelvärde för konturarea för ett foto
|
||||||
ScannerImageSplit.selectText.9=Kantstorlek:
|
ScannerImageSplit.selectText.9=Kantstorlek:
|
||||||
ScannerImageSplit.selectText.10=Ställer in storleken på kanten som läggs till och tas bort för att förhindra vita kanter i utdata (standard: 1).
|
ScannerImageSplit.selectText.10=Ställer in storleken på kanten som läggs till och tas bort för att förhindra vita kanter i utdata (standard: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Färg
|
|||||||
pdfToImage.grey=Gråskala
|
pdfToImage.grey=Gråskala
|
||||||
pdfToImage.blackwhite=Svartvitt (kan förlora data!)
|
pdfToImage.blackwhite=Svartvitt (kan förlora data!)
|
||||||
pdfToImage.submit=Konvertera
|
pdfToImage.submit=Konvertera
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=พื้นที่เค้าโครงข
|
|||||||
ScannerImageSplit.selectText.8=ตั้งค่าเกณฑ์พื้นที่เค้าโครงขั้นต่ำสำหรับรูปภาพ
|
ScannerImageSplit.selectText.8=ตั้งค่าเกณฑ์พื้นที่เค้าโครงขั้นต่ำสำหรับรูปภาพ
|
||||||
ScannerImageSplit.selectText.9=ขนาดขอบ:
|
ScannerImageSplit.selectText.9=ขนาดขอบ:
|
||||||
ScannerImageSplit.selectText.10=ตั้งค่าขนาดขอบที่เพิ่มและลบเพื่อป้องกันขอบขาวในผลลัพธ์ (ค่าเริ่มต้น: 1)
|
ScannerImageSplit.selectText.10=ตั้งค่าขนาดขอบที่เพิ่มและลบเพื่อป้องกันขอบขาวในผลลัพธ์ (ค่าเริ่มต้น: 1)
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=สี
|
|||||||
pdfToImage.grey=ระดับสีเทา
|
pdfToImage.grey=ระดับสีเทา
|
||||||
pdfToImage.blackwhite=ขาวดำ (อาจสูญเสียข้อมูล!)
|
pdfToImage.blackwhite=ขาวดำ (อาจสูญเสียข้อมูล!)
|
||||||
pdfToImage.submit=แปลง
|
pdfToImage.submit=แปลง
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Minimum Kontur Alanı:
|
|||||||
ScannerImageSplit.selectText.8=Bir fotoğraf için minimum kontur alanı eşiğini ayarlar
|
ScannerImageSplit.selectText.8=Bir fotoğraf için minimum kontur alanı eşiğini ayarlar
|
||||||
ScannerImageSplit.selectText.9=Kenar Boyutu:
|
ScannerImageSplit.selectText.9=Kenar Boyutu:
|
||||||
ScannerImageSplit.selectText.10=Çıktıda beyaz kenarların önlenmesi için eklenen ve kaldırılan kenarın boyutunu ayarlar (varsayılan: 1).
|
ScannerImageSplit.selectText.10=Çıktıda beyaz kenarların önlenmesi için eklenen ve kaldırılan kenarın boyutunu ayarlar (varsayılan: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Renk
|
|||||||
pdfToImage.grey=Gri tonlama
|
pdfToImage.grey=Gri tonlama
|
||||||
pdfToImage.blackwhite=Siyah ve Beyaz (Veri kaybolabilir!)
|
pdfToImage.blackwhite=Siyah ve Beyaz (Veri kaybolabilir!)
|
||||||
pdfToImage.submit=Dönüştür
|
pdfToImage.submit=Dönüştür
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Мінімальна площа контуру:
|
|||||||
ScannerImageSplit.selectText.8=Встановлює мінімальний поріг площі контуру для фотографії
|
ScannerImageSplit.selectText.8=Встановлює мінімальний поріг площі контуру для фотографії
|
||||||
ScannerImageSplit.selectText.9=Розмір рамки:
|
ScannerImageSplit.selectText.9=Розмір рамки:
|
||||||
ScannerImageSplit.selectText.10=Встановлює розмір додаваної та видаляної рамки, щоб запобігти появі білих рамок на виході (за замовчуванням: 1).
|
ScannerImageSplit.selectText.10=Встановлює розмір додаваної та видаляної рамки, щоб запобігти появі білих рамок на виході (за замовчуванням: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Колір
|
|||||||
pdfToImage.grey=Відтінки сірого
|
pdfToImage.grey=Відтінки сірого
|
||||||
pdfToImage.blackwhite=Чорно-білий (може втратити дані!)
|
pdfToImage.blackwhite=Чорно-білий (може втратити дані!)
|
||||||
pdfToImage.submit=Конвертувати
|
pdfToImage.submit=Конвертувати
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=Diện tích đường viền tối thiểu:
|
|||||||
ScannerImageSplit.selectText.8=Đặt ngưỡng diện tích đường viền tối thiểu cho một ảnh
|
ScannerImageSplit.selectText.8=Đặt ngưỡng diện tích đường viền tối thiểu cho một ảnh
|
||||||
ScannerImageSplit.selectText.9=Kích thước viền:
|
ScannerImageSplit.selectText.9=Kích thước viền:
|
||||||
ScannerImageSplit.selectText.10=Đặt kích thước của viền được thêm vào và loại bỏ để ngăn chặn viền trắng trong đầu ra (mặc định: 1).
|
ScannerImageSplit.selectText.10=Đặt kích thước của viền được thêm vào và loại bỏ để ngăn chặn viền trắng trong đầu ra (mặc định: 1).
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=Màu
|
|||||||
pdfToImage.grey=Thang độ xám
|
pdfToImage.grey=Thang độ xám
|
||||||
pdfToImage.blackwhite=Đen trắng (Có thể mất dữ liệu!)
|
pdfToImage.blackwhite=Đen trắng (Có thể mất dữ liệu!)
|
||||||
pdfToImage.submit=Chuyển đổi
|
pdfToImage.submit=Chuyển đổi
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小轮廓面积:
|
|||||||
ScannerImageSplit.selectText.8=设置照片的最小轮廓面积阈值。
|
ScannerImageSplit.selectText.8=设置照片的最小轮廓面积阈值。
|
||||||
ScannerImageSplit.selectText.9=边框尺寸:
|
ScannerImageSplit.selectText.9=边框尺寸:
|
||||||
ScannerImageSplit.selectText.10=设置添加和删除的边框大小,以防止输出中出现白边(默认值:1)。
|
ScannerImageSplit.selectText.10=设置添加和删除的边框大小,以防止输出中出现白边(默认值:1)。
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=颜色
|
|||||||
pdfToImage.grey=灰度
|
pdfToImage.grey=灰度
|
||||||
pdfToImage.blackwhite=黑白(可能会丢失数据!)。
|
pdfToImage.blackwhite=黑白(可能会丢失数据!)。
|
||||||
pdfToImage.submit=转换
|
pdfToImage.submit=转换
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -775,6 +775,7 @@ ScannerImageSplit.selectText.7=最小輪廓區域:
|
|||||||
ScannerImageSplit.selectText.8=設定照片的最小輪廓區域閾值
|
ScannerImageSplit.selectText.8=設定照片的最小輪廓區域閾值
|
||||||
ScannerImageSplit.selectText.9=邊框大小:
|
ScannerImageSplit.selectText.9=邊框大小:
|
||||||
ScannerImageSplit.selectText.10=設定新增和移除的邊框大小,以防止輸出中的白色邊框(預設:1)。
|
ScannerImageSplit.selectText.10=設定新增和移除的邊框大小,以防止輸出中的白色邊框(預設:1)。
|
||||||
|
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||||
|
|
||||||
|
|
||||||
#OCR
|
#OCR
|
||||||
@@ -925,6 +926,7 @@ pdfToImage.color=顏色
|
|||||||
pdfToImage.grey=灰度
|
pdfToImage.grey=灰度
|
||||||
pdfToImage.blackwhite=黑白(可能會遺失資料!)
|
pdfToImage.blackwhite=黑白(可能會遺失資料!)
|
||||||
pdfToImage.submit=轉換
|
pdfToImage.submit=轉換
|
||||||
|
pdfToImage.info=Python is not installed. Required for WebP conversion.
|
||||||
|
|
||||||
|
|
||||||
#addPassword
|
#addPassword
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "com.bucket4j:bucket4j_jdk17-core",
|
"moduleName": "com.bucket4j:bucket4j_jdk17-core",
|
||||||
"moduleUrl": "http://github.com/bucket4j/bucket4j/bucket4j_jdk17-core",
|
"moduleUrl": "http://github.com/bucket4j/bucket4j/bucket4j_jdk17-core",
|
||||||
"moduleVersion": "8.13.1",
|
"moduleVersion": "8.14.0",
|
||||||
"moduleLicense": "The Apache Software License, Version 2.0",
|
"moduleLicense": "The Apache Software License, Version 2.0",
|
||||||
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
@@ -1143,7 +1143,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-webmvc",
|
"moduleName": "org.springframework:spring-webmvc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.12",
|
"moduleVersion": "6.1.9",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Binary file not shown.
@@ -37,7 +37,7 @@ $(document).ready(function () {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (remoteCall === true) {
|
if (remoteCall === true) {
|
||||||
if (override === "multi" || (!multiple && files.length > 1 && override !== "single")) {
|
if (override === "multi" || (!multipleInputsForSingleRequest && files.length > 1 && override !== "single")) {
|
||||||
await submitMultiPdfForm(url, files);
|
await submitMultiPdfForm(url, files);
|
||||||
} else {
|
} else {
|
||||||
await handleSingleDownload(url, formData);
|
await handleSingleDownload(url, formData);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/misc/auto-split-pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/misc/auto-split-pdf'}">
|
||||||
<p th:text="#{autoSplitPDF.formPrompt}"></p>
|
<p th:text="#{autoSplitPDF.formPrompt}"></p>
|
||||||
<div
|
<div
|
||||||
th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}">
|
th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" name="duplexMode" id="duplexMode">
|
<input type="checkbox" name="duplexMode" id="duplexMode">
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 th:text="#{BookToPDF.header}"></h2>
|
<h2 th:text="#{BookToPDF.header}"></h2>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/book/pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/book/pdf'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false)}"></div>
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>
|
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<p th:text="#{processTimeWarning}"></p>
|
<p th:text="#{processTimeWarning}"></p>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/file/pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/file/pdf'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false)}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false)}"></div>
|
||||||
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
|
<a class="btn btn-outline-primary" data-bs-toggle="collapse" href="#info" role="button"
|
||||||
aria-expanded="false" aria-controls="info" th:text="#{fileToPDF.supportedFileTypesInfo}"></a>
|
aria-expanded="false" aria-controls="info" th:text="#{fileToPDF.supportedFileTypesInfo}"></a>
|
||||||
<div class="collapse" id="info">
|
<div class="collapse" id="info">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>
|
<span class="tool-header-text" th:text="#{HTMLToPDF.header}"></span>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/html/pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/html/pdf'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/html,application/zip' )}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='text/html,application/zip' )}"></div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="zoom" th:text="#{HTMLToPDF.zoom}" class="form-label"></label>
|
<label for="zoom" th:text="#{HTMLToPDF.zoom}" class="form-label"></label>
|
||||||
<input type="number" step="0.1" class="form-control" id="zoom" name="zoom" value="1">
|
<input type="number" step="0.1" class="form-control" id="zoom" name="zoom" value="1">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<span class="tool-header-text" th:text="#{imageToPDF.header}"></span>
|
<span class="tool-header-text" th:text="#{imageToPDF.header}"></span>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/img/pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/img/pdf'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='image/*', inputText=#{imgPrompt})}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='image/*', inputText=#{imgPrompt})}"></div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
|
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
|
||||||
<select class="form-control" id="fitOption" name="fitOption">
|
<select class="form-control" id="fitOption" name="fitOption">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>
|
<span class="tool-header-text" th:text="#{MarkdownToPDF.header}"></span>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/markdown/pdf'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/markdown/pdf'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='text/markdown')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='text/markdown')}"></div>
|
||||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button>
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{MarkdownToPDF.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<p class="mt-3" th:text="#{MarkdownToPDF.help}"></p>
|
<p class="mt-3" th:text="#{MarkdownToPDF.help}"></p>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h2 th:text="#{PDFToBook.header}"></h2>
|
<h2 th:text="#{PDFToBook.header}"></h2>
|
||||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/book'}">
|
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/pdf/book'}">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label th:text="#{PDFToBook.selectText.1}"></label>
|
<label th:text="#{PDFToBook.selectText.1}"></label>
|
||||||
<select class="form-control" name="outputFormat">
|
<select class="form-control" name="outputFormat">
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<form id="PDFToCSVForm" th:action="@{'/api/v1/convert/pdf/csv'}" method="post" enctype="multipart/form-data">
|
<form id="PDFToCSVForm" th:action="@{'/api/v1/convert/pdf/csv'}" method="post" enctype="multipart/form-data">
|
||||||
<input id="pageId" type="hidden" name="pageId">
|
<input id="pageId" type="hidden" name="pageId">
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='application/pdf')}"></div>
|
||||||
<button type="submit" class="btn btn-primary" th:text="#{PDFToCSV.submit}"></button>
|
<button type="submit" class="btn btn-primary" th:text="#{PDFToCSV.submit}"></button>
|
||||||
</form>
|
</form>
|
||||||
<p id="instruction-text" style="margin: 0; display: none" th:text="#{PDFToCSV.prompt}"></p>
|
<p id="instruction-text" style="margin: 0; display: none" th:text="#{PDFToCSV.prompt}"></p>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user