Merge pull request #802 from Stirling-Tools/normalize_files

refactor: normalize all files (strip trailing whitespace + convert CRLF to LF)
This commit is contained in:
Eric 2024-02-11 13:11:37 -05:00 committed by GitHub
commit 6a487ce514
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
143 changed files with 17468 additions and 17470 deletions

View file

@ -1,2 +1,5 @@
# Formatting
5f771b785130154ed47952635b7acef371ffe0ec
5f771b785130154ed47952635b7acef371ffe0ec
# Normalize files
55d4fda01b2f39f5b7d7b4fda5214bd7ff0fd5dd

View file

@ -3,7 +3,7 @@ name: Push Docker Image with VersionNumber
on:
workflow_dispatch:
push:
branches:
branches:
- master
- main
permissions:
@ -15,13 +15,13 @@ jobs:
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- uses: gradle/gradle-build-action@v2.4.2
env:
@ -32,11 +32,11 @@ jobs:
- name: Make Gradle wrapper executable
run: chmod +x gradlew
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
- name: Login to Docker Hub
uses: docker/login-action@v2.1.0
with:
@ -53,7 +53,7 @@ jobs:
- name: Convert repository owner to lowercase
id: repoowner
run: echo "::set-output name=lowercase::$(echo ${{ github.repository_owner }} | awk '{print tolower($0)}')"
- name: Generate tags
id: meta
uses: docker/metadata-action@v4.4.0
@ -82,7 +82,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
@ -99,7 +99,7 @@ jobs:
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-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
uses: docker/build-push-action@v4.0.0
@ -112,7 +112,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta2.outputs.tags }}
labels: ${{ steps.meta2.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
@ -129,7 +129,7 @@ jobs:
tags: |
type=raw,value=${{ steps.versionNumber.outputs.versionNumber }}-lite,enable=${{ github.ref == 'refs/heads/master' }}
type=raw,value=latest-lite,enable=${{ github.ref == 'refs/heads/master' }}
- name: Build and push Dockerfile-lite
uses: docker/build-push-action@v4.0.0
@ -142,7 +142,7 @@ jobs:
cache-to: type=gha,mode=max
tags: ${{ steps.meta3.outputs.tags }}
labels: ${{ steps.meta3.outputs.labels }}
build-args:
build-args:
VERSION_TAG=${{ steps.versionNumber.outputs.versionNumber }}
platforms: linux/amd64,linux/arm64/v8
- name: Build and Push Helm Chart

View file

@ -1,7 +1,7 @@
name: Release Artifacts
on:
release:
on:
release:
types: [created]
permissions:
contents: write
@ -19,13 +19,13 @@ jobs:
file_suffix: ''
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
@ -42,11 +42,11 @@ jobs:
asset_name: Stirling-PDF${{ matrix.file_suffix }}.exe
tag: ${{ github.ref }}
overwrite: true
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"
- name: Upload jar binaries to release
uses: svenstaro/upload-release-action@v2
with:

View file

@ -3,7 +3,7 @@ name: Update Swagger
on:
workflow_dispatch:
push:
branches:
branches:
- master
jobs:
push:
@ -12,13 +12,13 @@ jobs:
steps:
- uses: actions/checkout@v3.5.2
- name: Set up JDK 17
uses: actions/setup-java@v3.11.0
with:
java-version: '17'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew

View file

@ -30,7 +30,7 @@ jobs:
- name: Run Docker Compose Tests
run: |
chmod +x ./gradlew
- name: Get version number
id: versionNumber
run: echo "::set-output name=versionNumber::$(./gradlew printVersion --quiet | tail -1)"

252
.gitignore vendored
View file

@ -1,127 +1,127 @@
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
pipeline/watchedFolders/
pipeline/finishedFolders/
#### Stirling-PDF Files ###
customFiles/
configs/
watchedFolders/
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
/.vscode
/.idea
# Ignore Mac DS_Store files
.DS_Store
### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
.classpath
.project
version.properties
pipeline/watchedFolders/
pipeline/finishedFolders/
#### Stirling-PDF Files ###
customFiles/
configs/
watchedFolders/
# Gradle
.gradle
.lock
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
.apt_generated_test/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
# Uncomment this line if you wish to ignore the project description file.
# Typically, this file would be tracked if it contains build/dependency configurations:
#.project
### Eclipse Patch ###
# Spring Boot Tooling
.sts4-cache/
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
*.orig
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Java ###
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
*.db
/build
/.vscode
/.idea
# Ignore Mac DS_Store files
.DS_Store
**/.DS_Store

View file

@ -1,69 +1,69 @@
# Main stage
FROM alpine:3.19.1
# JDK for app
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
bash \
curl \
openjdk17-jre \
# Doc conversion
libreoffice@testing \
# OCR MY PDF (unpaper for descew and other advanced featues)
ocrmypdf \
tesseract-ocr-data-eng \
# CV
py3-opencv \
# python3/pip
python3 && \
wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
# uno unoconv and HTML
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
mv /usr/share/tessdata /usr/share/tessdata-original
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Copy necessary files
COPY scripts /scripts
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
COPY build/libs/*.jar app.jar
# Create user and group
##RUN groupadd -g $PGID stirlingpdfgroup && \
## useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
## mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME && \
# Set up necessary directories and permissions
RUN mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
##&& \
## chown -R stirlingpdfuser:stirlingpdfgroup /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /customFiles && \
## chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/tesseract-ocr-original && \
# Set font cache and permissions
fc-cache -f -v && \
chmod +x /scripts/*
## chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
## chmod +x /scripts/init.sh
EXPOSE 8080
# Set user and run command
##USER stirlingpdfuser
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]
# Main stage
FROM alpine:3.19.1
# JDK for app
RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \
apk add --no-cache \
ca-certificates \
tzdata \
tini \
bash \
curl \
openjdk17-jre \
# Doc conversion
libreoffice@testing \
# OCR MY PDF (unpaper for descew and other advanced featues)
ocrmypdf \
tesseract-ocr-data-eng \
# CV
py3-opencv \
# python3/pip
python3 && \
wget https://bootstrap.pypa.io/get-pip.py -qO - | python3 - --break-system-packages --no-cache-dir --upgrade && \
# uno unoconv and HTML
pip install --break-system-packages --no-cache-dir --upgrade unoconv WeasyPrint && \
mv /usr/share/tessdata /usr/share/tessdata-original
ARG VERSION_TAG
# Set Environment Variables
ENV DOCKER_ENABLE_SECURITY=false \
HOME=/home/stirlingpdfuser \
VERSION_TAG=$VERSION_TAG \
JAVA_TOOL_OPTIONS="$JAVA_TOOL_OPTIONS -XX:MaxRAMPercentage=75"
# PUID=1000 \
# PGID=1000 \
# UMASK=022 \
# Copy necessary files
COPY scripts /scripts
COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto
COPY build/libs/*.jar app.jar
# Create user and group
##RUN groupadd -g $PGID stirlingpdfgroup && \
## useradd -u $PUID -g stirlingpdfgroup -s /bin/sh stirlingpdfuser && \
## mkdir -p $HOME && chown stirlingpdfuser:stirlingpdfgroup $HOME && \
# Set up necessary directories and permissions
RUN mkdir -p /configs /logs /customFiles /pipeline/watchedFolders /pipeline/finishedFolders && \
##&& \
## chown -R stirlingpdfuser:stirlingpdfgroup /scripts /usr/share/fonts/opentype/noto /usr/share/tesseract-ocr /configs /customFiles && \
## chown -R stirlingpdfuser:stirlingpdfgroup /usr/share/tesseract-ocr-original && \
# Set font cache and permissions
fc-cache -f -v && \
chmod +x /scripts/*
## chown stirlingpdfuser:stirlingpdfgroup /app.jar && \
## chmod +x /scripts/init.sh
EXPOSE 8080
# Set user and run command
##USER stirlingpdfuser
ENTRYPOINT ["tini", "--", "/scripts/init.sh"]
CMD ["java", "-Dfile.encoding=UTF-8", "-jar", "/app.jar"]

View file

@ -1,46 +1,46 @@
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
| crop | ✔️ | | | | | | | | | ✔️ | |
| extract-page | ✔️ | | | | | | | | | ✔️ | |
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| Operation | PageOps | Convert | Security | Other | CLI | Python | OpenCV | LibreOffice | OCRmyPDF | Java | Javascript |
|---------------------|---------|---------|----------|-------|------|--------|--------|-------------|----------|----------|------------|
| adjust-contrast | ✔️ | | | | | | | | | | ✔️ |
| auto-split-pdf | ✔️ | | | | | | | | | ✔️ | |
| crop | ✔️ | | | | | | | | | ✔️ | |
| extract-page | ✔️ | | | | | | | | | ✔️ | |
| merge-pdfs | ✔️ | | | | | | | | | ✔️ | |
| multi-page-layout | ✔️ | | | | | | | | | ✔️ | |
| pdf-organizer | ✔️ | | | | | | | | | ✔️ | ✔️ |
| pdf-to-single-page | ✔️ | | | | | | | | | ✔️ | |
| remove-pages | ✔️ | | | | | | | | | ✔️ | |
| rotate-pdf | ✔️ | | | | | | | | | ✔️ | |
| scale-pages | ✔️ | | | | | | | | | ✔️ | |
| split-pdfs | ✔️ | | | | | | | | | ✔️ | |
| file-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| img-to-pdf | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-html | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-img | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-pdfa | | ✔️ | | | ✔️ | | | | ✔️ | | |
| pdf-to-markdown | | ✔️ | | | | | | | | ✔️ | |
| pdf-to-presentation | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-text | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-word | | ✔️ | | | ✔️ | | | ✔️ | | | |
| pdf-to-xml | | ✔️ | | | ✔️ | | | ✔️ | | | |
| xlsx-to-pdf | | ✔️ | | | ✔️ | | | ✔️ | | | |
| add-password | | | ✔️ | | | | | | | ✔️ | |
| add-watermark | | | ✔️ | | | | | | | ✔️ | |
| cert-sign | | | ✔️ | | | | | | | ✔️ | |
| change-permissions | | | ✔️ | | | | | | | ✔️ | |
| remove-password | | | ✔️ | | | | | | | ✔️ | |
| sanitize-pdf | | | ✔️ | | | | | | | ✔️ | |
| add-image | | | | ✔️ | | | | | | ✔️ | |
| add-page-numbers | | | | ✔️ | | | | | | ✔️ | |
| auto-rename | | | | ✔️ | | | | | | ✔️ | |
| change-metadata | | | | ✔️ | | | | | | ✔️ | |
| compare | | | | ✔️ | | | | | | | ✔️ |
| compress-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| extract-image-scans | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| extract-images | | | | ✔️ | | | | | | ✔️ | |
| flatten | | | | ✔️ | | | | | | | ✔️ |
| get-info-on-pdf | | | | ✔️ | | | | | | ✔️ | |
| ocr-pdf | | | | ✔️ | ✔️ | | | | ✔️ | | |
| remove-blanks | | | | ✔️ | ✔️ | ✔️ | ✔️ | | | | |
| repair | | | | ✔️ | ✔️ | | | ✔️ | | | |
| show-javascript | | | | ✔️ | | | | | | | ✔️ |
| sign | | | | ✔️ | | | | | | | ✔️ |

View file

@ -9,13 +9,13 @@ Fork Stirling-PDF and make a new branch out of Main
Then add reference to the language in the navbar by adding a new language entry to the dropdown
https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/templates/fragments/languages.html
and add a flag svg file to
and add a flag svg file to
https://github.com/Stirling-Tools/Stirling-PDF/tree/main/src/main/resources/static/images/flags
Any SVG flags are fine, i got most of mine from [here](https://flagicons.lipis.dev/)
If your language isnt represented by a flag just find whichever closely matches it, such as for Arabic i chose Saudi Arabia
For example to add Polish you would add
For example to add Polish you would add
```html
<a class="dropdown-item lang_dropdown-item" href="" data-language-code="pl_PL">
<img src="images/flags/pl.svg" alt="icon" width="20" height="15"> Polski
@ -23,7 +23,7 @@ For example to add Polish you would add
```
The data-language-code is the code used to reference the file in the next step.
Start by copying the existing english property file
Start by copying the existing english property file
[https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/src/main/resources/messages_en_GB.properties)

View file

@ -7,7 +7,7 @@ Please update your tesseract docker volume path version from 4.00 to 5
## How does the OCR Work
Stirling-PDF uses [OCRmyPDF](https://github.com/ocrmypdf/OCRmyPDF) which in turn uses tesseract for its text recognition.
All credit goes to them for this awesome work!
All credit goes to them for this awesome work!
## Language Packs
@ -27,7 +27,7 @@ Depending on your requirements, you can choose the appropriate language pack for
#### Docker
If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs.
If you are using Docker, you need to expose the Tesseract tessdata directory as a volume in order to use the additional language packs.
#### Docker Compose
Modify your `docker-compose.yml` file to include the following volume configuration:

88
Jenkinsfile vendored
View file

@ -1,45 +1,45 @@
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod 755 gradlew'
sh './gradlew build'
}
}
stage('Docker Build') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
sh "docker build -t $image ."
}
}
}
stage('Docker Push') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "docker push $image"
}
}
}
}
stage('Helm Push') {
steps {
script {
//TODO: Read chartVersion from Chart.yaml
def chartVersion = '1.0.0'
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "helm package chart/stirling-pdf"
sh "helm push stirling-pdf-chart-1.0.0.tgz oci://registry-1.docker.io/frooodle"
}
}
}
}
}
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'chmod 755 gradlew'
sh './gradlew build'
}
}
stage('Docker Build') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
sh "docker build -t $image ."
}
}
}
stage('Docker Push') {
steps {
script {
def appVersion = sh(returnStdout: true, script: './gradlew printVersion -q').trim()
def image = "frooodle/s-pdf:$appVersion"
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "docker push $image"
}
}
}
}
stage('Helm Push') {
steps {
script {
//TODO: Read chartVersion from Chart.yaml
def chartVersion = '1.0.0'
withCredentials([string(credentialsId: 'docker_hub_access_token', variable: 'DOCKER_HUB_ACCESS_TOKEN')]) {
sh "docker login --username frooodle --password $DOCKER_HUB_ACCESS_TOKEN"
sh "helm package chart/stirling-pdf"
sh "helm push stirling-pdf-chart-1.0.0.tgz oci://registry-1.docker.io/frooodle"
}
}
}
}
}
}

View file

@ -45,7 +45,7 @@ sudo apt-get update
sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ java-17-openjdk python3 python3-pip
```
For Fedora-based systems use this command:
For Fedora-based systems use this command:
```bash
sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-17-openjdk python3 python3-pip
@ -95,14 +95,14 @@ For Debian-based systems, you can use the following command:
```bash
sudo apt-get install -y libreoffice-writer libreoffice-calc libreoffice-impress unpaper ocrmypdf
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
For Fedora:
```bash
sudo dnf install -y libreoffice-writer libreoffice-calc libreoffice-impress unpaper ocrmypdf
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
### Step 4: Clone and Build Stirling-PDF
@ -140,7 +140,7 @@ Manual:
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata`
3.
3.
Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
**IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED.
@ -269,5 +269,5 @@ You can do this in the terminal by using the `export` command or -D arguements t
```bash
export APP_HOME_NAME="Stirling PDF"
or
-DAPP_HOME_NAME="Stirling PDF"
-DAPP_HOME_NAME="Stirling PDF"
```

View file

@ -1,64 +1,64 @@
|Technology | Ultra-Lite | Lite | Full |
|----------------|:----------:|:----:|:----:|
| Java | ✔️ | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ | ✔️ |
| Libre | | ✔️ | ✔️ |
| Python | | | ✔️ |
| OpenCV | | | ✔️ |
| OCRmyPDF | | | ✔️ |
Operation | Ultra-Lite | Lite | Full
--------------------|------------|------|-----
add-page-numbers | ✔️ | ✔️ | ✔️
add-password | ✔️ | ✔️ | ✔️
add-image | ✔️ | ✔️ | ✔️
add-watermark | ✔️ | ✔️ | ✔️
adjust-contrast | ✔️ | ✔️ | ✔️
auto-split-pdf | ✔️ | ✔️ | ✔️
auto-redact | ✔️ | ✔️ | ✔️
auto-rename | ✔️ | ✔️ | ✔️
cert-sign | ✔️ | ✔️ | ✔️
crop | ✔️ | ✔️ | ✔️
change-metadata | ✔️ | ✔️ | ✔️
change-permissions | ✔️ | ✔️ | ✔️
compare | ✔️ | ✔️ | ✔️
extract-page | ✔️ | ✔️ | ✔️
extract-images | ✔️ | ✔️ | ✔️
flatten | ✔️ | ✔️ | ✔️
get-info-on-pdf | ✔️ | ✔️ | ✔️
img-to-pdf | ✔️ | ✔️ | ✔️
markdown-to-pdf | ✔️ | ✔️ | ✔️
merge-pdfs | ✔️ | ✔️ | ✔️
multi-page-layout | ✔️ | ✔️ | ✔️
overlay-pdf | ✔️ | ✔️ | ✔️
pdf-organizer | ✔️ | ✔️ | ✔️
pdf-to-csv | ✔️ | ✔️ | ✔️
pdf-to-img | ✔️ | ✔️ | ✔️
pdf-to-single-page | ✔️ | ✔️ | ✔️
remove-pages | ✔️ | ✔️ | ✔️
remove-password | ✔️ | ✔️ | ✔️
rotate-pdf | ✔️ | ✔️ | ✔️
sanitize-pdf | ✔️ | ✔️ | ✔️
scale-pages | ✔️ | ✔️ | ✔️
sign | ✔️ | ✔️ | ✔️
show-javascript | ✔️ | ✔️ | ✔️
split-by-size-or-count | ✔️ | ✔️ | ✔️
split-pdf-by-sections | ✔️ | ✔️ | ✔️
split-pdfs | ✔️ | ✔️ | ✔️
file-to-pdf | | ✔️ | ✔️
pdf-to-html | | ✔️ | ✔️
pdf-to-presentation | | ✔️ | ✔️
pdf-to-text | | ✔️ | ✔️
pdf-to-word | | ✔️ | ✔️
pdf-to-xml | | ✔️ | ✔️
repair | | ✔️ | ✔️
xlsx-to-pdf | | ✔️ | ✔️
compress-pdf | | | ✔️
extract-image-scans | | | ✔️
ocr-pdf | | | ✔️
pdf-to-pdfa | | | ✔️
remove-blanks | | | ✔️
|Technology | Ultra-Lite | Lite | Full |
|----------------|:----------:|:----:|:----:|
| Java | ✔️ | ✔️ | ✔️ |
| JavaScript | ✔️ | ✔️ | ✔️ |
| Libre | | ✔️ | ✔️ |
| Python | | | ✔️ |
| OpenCV | | | ✔️ |
| OCRmyPDF | | | ✔️ |
Operation | Ultra-Lite | Lite | Full
--------------------|------------|------|-----
add-page-numbers | ✔️ | ✔️ | ✔️
add-password | ✔️ | ✔️ | ✔️
add-image | ✔️ | ✔️ | ✔️
add-watermark | ✔️ | ✔️ | ✔️
adjust-contrast | ✔️ | ✔️ | ✔️
auto-split-pdf | ✔️ | ✔️ | ✔️
auto-redact | ✔️ | ✔️ | ✔️
auto-rename | ✔️ | ✔️ | ✔️
cert-sign | ✔️ | ✔️ | ✔️
crop | ✔️ | ✔️ | ✔️
change-metadata | ✔️ | ✔️ | ✔️
change-permissions | ✔️ | ✔️ | ✔️
compare | ✔️ | ✔️ | ✔️
extract-page | ✔️ | ✔️ | ✔️
extract-images | ✔️ | ✔️ | ✔️
flatten | ✔️ | ✔️ | ✔️
get-info-on-pdf | ✔️ | ✔️ | ✔️
img-to-pdf | ✔️ | ✔️ | ✔️
markdown-to-pdf | ✔️ | ✔️ | ✔️
merge-pdfs | ✔️ | ✔️ | ✔️
multi-page-layout | ✔️ | ✔️ | ✔️
overlay-pdf | ✔️ | ✔️ | ✔️
pdf-organizer | ✔️ | ✔️ | ✔️
pdf-to-csv | ✔️ | ✔️ | ✔️
pdf-to-img | ✔️ | ✔️ | ✔️
pdf-to-single-page | ✔️ | ✔️ | ✔️
remove-pages | ✔️ | ✔️ | ✔️
remove-password | ✔️ | ✔️ | ✔️
rotate-pdf | ✔️ | ✔️ | ✔️
sanitize-pdf | ✔️ | ✔️ | ✔️
scale-pages | ✔️ | ✔️ | ✔️
sign | ✔️ | ✔️ | ✔️
show-javascript | ✔️ | ✔️ | ✔️
split-by-size-or-count | ✔️ | ✔️ | ✔️
split-pdf-by-sections | ✔️ | ✔️ | ✔️
split-pdfs | ✔️ | ✔️ | ✔️
file-to-pdf | | ✔️ | ✔️
pdf-to-html | | ✔️ | ✔️
pdf-to-presentation | | ✔️ | ✔️
pdf-to-text | | ✔️ | ✔️
pdf-to-word | | ✔️ | ✔️
pdf-to-xml | | ✔️ | ✔️
repair | | ✔️ | ✔️
xlsx-to-pdf | | ✔️ | ✔️
compress-pdf | | | ✔️
extract-image-scans | | | ✔️
ocr-pdf | | | ✔️
pdf-to-pdfa | | | ✔️
remove-blanks | | | ✔️

View file

@ -92,7 +92,7 @@ dependencies {
implementation 'org.springframework:spring-webmvc:6.1.2'
implementation("io.github.pixee:java-security-toolkit:1.1.2")
implementation 'org.yaml:snakeyaml:2.2'
implementation 'org.springframework.boot:spring-boot-starter-web:3.2.2'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.2.2'
@ -101,7 +101,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security:3.2.2'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.2"
//2.2.x requires rebuild of DB file.. need migration path
implementation "com.h2database:h2:2.1.214"
}
@ -138,15 +138,15 @@ dependencies {
implementation ('com.opencsv:opencsv:5.9') {
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation ('org.apache.pdfbox:pdfbox:3.0.1'){
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation ('org.apache.pdfbox:xmpbox:3.0.1'){
exclude group: 'commons-logging', module: 'commons-logging'
}
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.2'

View file

@ -43,6 +43,6 @@ spec:
name: http
{{- end }}
protocol: TCP
selector:
{{- include "stirlingpdf.selectorLabels" . | nindent 4 }}

View file

@ -19,8 +19,8 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs173">
<linearGradient
id="XMLID_5_"
gradientUnits="userSpaceOnUse"
@ -37,7 +37,7 @@
style="stop-color:#C2C2C9"
id="stop158" />
</linearGradient>
</defs><sodipodi:namedview
id="namedview171"
pagecolor="#ffffff"

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

182
gradlew.bat vendored
View file

@ -1,91 +1,91 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View file

@ -4,7 +4,7 @@ if [ "$DOCKER_ENABLE_SECURITY" = "true" ] && [ "$VERSION_TAG" != "alpha" ]; then
if [ ! -f app-security.jar ]; then
echo "Trying to download from: https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar"
curl -L -o app-security.jar https://github.com/Stirling-Tools/Stirling-PDF/releases/download/v$VERSION_TAG/Stirling-PDF-with-login.jar
# If the first download attempt failed, try with the 'v' prefix
if [ $? -ne 0 ]; then
echo "Trying to download from: https://github.com/Stirling-Tools/Stirling-PDF/releases/download/$VERSION_TAG/Stirling-PDF-with-login.jar"

View file

@ -2,7 +2,7 @@ import argparse
import sys
import cv2
import numpy as np
import os
import os
def find_photo_boundaries(image, background_color, tolerance=30, min_area=10000, min_contour_area=500):
mask = cv2.inRange(image, background_color - tolerance, background_color + tolerance)
@ -49,9 +49,9 @@ def auto_rotate(image, angle_threshold=1):
angles = []
for rho, theta in lines[:, 0]:
angles.append((theta * 180) / np.pi - 90)
angle = np.median(angles)
if abs(angle) < angle_threshold:
return image
@ -65,16 +65,16 @@ def auto_rotate(image, angle_threshold=1):
def crop_borders(image, border_color, tolerance=30):
mask = cv2.inRange(image, border_color - tolerance, border_color + tolerance)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(contours) == 0:
return image
largest_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(largest_contour)
return image[y:y+h, x:x+w]
def split_photos(input_file, output_directory, tolerance=30, min_area=10000, min_contour_area=500, angle_threshold=10, border_size=0):
image = cv2.imread(input_file)
background_color = estimate_background_color(image)
@ -110,7 +110,7 @@ if __name__ == "__main__":
parser.add_argument("--min_contour_area", type=int, default=500, help="Sets the minimum contour area threshold for a photo (default: 500).")
parser.add_argument("--angle_threshold", type=int, default=10, help="Sets the minimum absolute angle required for the image to be rotated (default: 10).")
parser.add_argument("--border_size", type=int, default=0, help="Sets the size of the border added and removed to prevent white borders in the output (default: 0).")
args = parser.parse_args()
split_photos(args.input_file, args.output_directory, tolerance=args.tolerance, min_area=args.min_area, min_contour_area=args.min_contour_area, angle_threshold=args.angle_threshold, border_size=args.border_size)

View file

@ -22,7 +22,7 @@ server.servlet.context-path=${SYSTEM_ROOTURIPATH:/}
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.encoding=UTF-8
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m}
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000}

View file

@ -1,6 +1,6 @@
____ _____ ___ ____ _ ___ _ _ ____ ____ ____ _____
____ _____ ___ ____ _ ___ _ _ ____ ____ ____ _____
/ ___|_ _|_ _| _ \| | |_ _| \ | |/ ___| | _ \| _ \| ___|
\___ \ | | | || |_) | | | || \| | | _ _____| |_) | | | | |_
___) || | | || _ <| |___ | || |\ | |_| |_____| __/| |_| | _|
|____/ |_| |___|_| \_\_____|___|_| \_|\____| |_| |____/|_|
\___ \ | | | || |_) | | | || \| | | _ _____| |_) | | | | |_
___) || | | || _ <| |___ | || |\ | |_| |_____| __/| |_| | _|
|____/ |_| |___|_| \_\_____|___|_| \_|\____| |_| |____/|_|
Powered by Spring Boot ${spring-boot.version}

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Дезинфектирай PDF
sanitizePDF.header=Дезинфектира PDF файл
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Задава минималния праг на
ScannerImageSplit.selectText.9=Размер на рамката:
ScannerImageSplit.selectText.10=Задава размера на добавената и премахната граница, за да предотврати бели граници към изхода (по подразбиране: 1).
#OCR
ocr.title=OCR / Почистване на сканиране
ocr.header=Почистващи сканирания / OCR (оптично разпознаване на знаци)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Автоматично завъртане на PDF
imageToPDF.selectText.3=Файлова логика с много (Активирано само ако работите с множество изображения)
imageToPDF.selectText.4=Сливане към един PDF
imageToPDF.selectText.5=Преобразуване към отделни PDF файлове
#pdfToImage
pdfToImage.title=PDF към Изображение
pdfToImage.header=PDF към Изображение

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 PDF
sanitizePDF.header=\u0391\u03C0\u03BF\u03BB\u03CD\u03BC\u03B1\u03BD\u03C3\u03B7 \u03B5\u03BD\u03CC\u03C2 PDF \u03B1\u03C1\u03C7\u03B5\u03AF\u03BF\u03C5
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=\u03A1\u03C5\u03B8\u03BC\u03AF\u03B6\u03B5\u03B9
ScannerImageSplit.selectText.9=\u039C\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2:
ScannerImageSplit.selectText.10=\u039F\u03C1\u03AF\u03B6\u03B5\u03B9 \u03C4\u03BF \u03BC\u03AD\u03B3\u03B5\u03B8\u03BF\u03C2 \u03C4\u03BF\u03C5 \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03BF\u03C2 \u03C0\u03BF\u03C5 \u03C0\u03C1\u03BF\u03C3\u03C4\u03AF\u03B8\u03B5\u03C4\u03B1\u03B9 \u03BA\u03B1\u03B9 \u03B1\u03C6\u03B1\u03B9\u03C1\u03B5\u03AF\u03C4\u03B1\u03B9 \u03B3\u03B9\u03B1 \u03BD\u03B1 \u03B1\u03C0\u03BF\u03C4\u03C1\u03AD\u03C0\u03BF\u03BD\u03C4\u03B1\u03B9 \u03BB\u03B5\u03C5\u03BA\u03AC \u03C0\u03B5\u03C1\u03B9\u03B3\u03C1\u03AC\u03BC\u03BC\u03B1\u03C4\u03B1 \u03C3\u03C4\u03B7\u03BD \u03AD\u03BE\u03BF\u03B4\u03BF (\u03C0\u03C1\u03BF\u03B5\u03C0\u03B9\u03BB\u03BF\u03B3\u03AE: 1).
#OCR
ocr.title=\u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD (OCR) / \u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup
ocr.header=\u03A3\u03B1\u03C1\u03CE\u03C3\u03B5\u03B9\u03C2 Cleanup / OCR (Optical Character Recognition - \u039F\u03C0\u03C4\u03B9\u03BA\u03AE \u03B1\u03BD\u03B1\u03B3\u03BD\u03CE\u03C1\u03B9\u03C3\u03B7 \u03C7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1\u03C9\u03BD)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=\u0391\u03C5\u03C4\u03CC\u03BC\u03B1\u03C4\u03B7 \u03C0\
imageToPDF.selectText.3=\u039B\u03BF\u03B3\u03B9\u03BA\u03AE \u03C0\u03BF\u03BB\u03BB\u03CE\u03BD \u03B1\u03C1\u03C7\u03B5\u03AF\u03C9\u03BD (\u0395\u03BD\u03B5\u03C1\u03B3\u03BF\u03C0\u03BF\u03B9\u03B5\u03AF\u03C4\u03B1\u03B9 \u03BC\u03CC\u03BD\u03BF \u03B5\u03AC\u03BD \u03B5\u03C1\u03B3\u03AC\u03B6\u03B5\u03C3\u03C4\u03B5 \u03BC\u03B5 \u03C0\u03BF\u03BB\u03BB\u03AD\u03C2 \u03B5\u03B9\u03BA\u03CC\u03BD\u03B5\u03C2)
imageToPDF.selectText.4=\u03A3\u03C5\u03B3\u03C7\u03CE\u03BD\u03B5\u03C5\u03C3\u03B7 \u03C3\u03B5 \u03AD\u03BD\u03B1 PDF
imageToPDF.selectText.5=\u039C\u03B5\u03C4\u03B1\u03C4\u03C1\u03BF\u03C0\u03AE \u03C3\u03B5 \u03BE\u03B5\u03C7\u03C9\u03C1\u03B9\u03C3\u03C4\u03AC \u03B1\u03C1\u03C7\u03B5\u03AF\u03B1 PDF
#pdfToImage
pdfToImage.title=PDF \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1
pdfToImage.header=PDF \u03C3\u03B5 \u0395\u03B9\u03BA\u03CC\u03BD\u03B1

View file

@ -26,7 +26,7 @@ downloadPdf=Download PDF
text=Text
font=Font
selectFillter=-- Select --
pageNum=Page Number
pageNum=Page Number
sizes.small=Small
sizes.medium=Medium
sizes.large=Large
@ -172,7 +172,7 @@ merge.tags=merge,Page operations,Back end,server side
home.split.title=Split
home.split.desc=Split PDFs into multiple documents
split.tags=Page operations,divide,Multi Page,cut,server side
split.tags=Page operations,divide,Multi Page,cut,server side
home.rotate.title=Rotate
home.rotate.desc=Easily rotate your PDFs.
@ -313,7 +313,7 @@ home.add-page-numbers.desc=Add Page numbers throughout a document in a set locat
add-page-numbers.tags=paginate,label,organize,index
home.auto-rename.title=Auto Rename PDF File
home.auto-rename.desc=Auto renames a PDF file based on its detected header
home.auto-rename.desc=Auto renames a PDF file based on its detected header
auto-rename.tags=auto-detect,header-based,organize,relabel
home.adjust-contrast.title=Adjust Colors/Contrast
@ -498,7 +498,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitize PDF
sanitizePDF.header=Sanitize a PDF file
@ -584,18 +584,18 @@ scalePages.submit=Submit
#certSign
certSign.title=Certificate Signing
certSign.header=Sign a PDF with your certificate (Work in progress)
certSign.selectPDF=Select a PDF File for Signing:
certSign.selectPDF=Select a PDF File for Signing:
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below.
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
certSign.selectKey=Select Your Private Key File (PKCS#8 format, could be .pem or .der):
certSign.selectCert=Select Your Certificate File (X.509 format, could be .pem or .der):
certSign.selectP12=Select Your PKCS#12 Keystore File (.p12 or .pfx) (Optional, If provided, it should contain your private key and certificate):
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore):
certSign.certType=Certificate Type
certSign.password=Enter Your Keystore or Private Key Password (If Any):
certSign.password=Enter Your Keystore or Private Key Password (If Any):
certSign.showSig=Show Signature
certSign.reason=Reason
certSign.location=Location
certSign.name=Name
certSign.name=Name
certSign.submit=Sign PDF
@ -657,7 +657,7 @@ ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a pho
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).
#OCR
ocr.title=OCR / Scan Cleanup
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
@ -701,7 +701,7 @@ compress.selectText.1=Manual Mode - From 1 to 4
compress.selectText.2=Optimization level:
compress.selectText.3=4 (Terrible for text images)
compress.selectText.4=Auto mode - Auto adjusts quality to get PDF to exact size
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
compress.selectText.5=Expected PDF Size (e.g. 25MB, 10.8MB, 25KB)
compress.submit=Compress
@ -776,8 +776,8 @@ imageToPDF.selectText.2=Auto rotate PDF
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
imageToPDF.selectText.4=Merge into single PDF
imageToPDF.selectText.5=Convert to separate PDFs
#pdfToImage
pdfToImage.title=PDF to Image
pdfToImage.header=PDF to Image

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitize PDF
sanitizePDF.header=Sanitize a PDF file
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a pho
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).
#OCR
ocr.title=OCR / Scan Cleanup
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Auto rotate PDF
imageToPDF.selectText.3=Multi file logic (Only enabled if working with multiple images)
imageToPDF.selectText.4=Merge into single PDF
imageToPDF.selectText.5=Convert to separate PDFs
#pdfToImage
pdfToImage.title=PDF to Image
pdfToImage.header=PDF to Image

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=पीडीएफ़ को सफाई करें
sanitizePDF.header=एक पीडीएफ़ फ़ाइल को सफाई करें
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=फोटो के लिए न्यूनत
ScannerImageSplit.selectText.9=बॉर्डर का आकार:
ScannerImageSplit.selectText.10=निकालने और जोड़ने के लिए जोड़ा जाने वाला बॉर्डर का आकार सेट करता है ताकि आउटपुट में सफेद बॉर्डर न आए (डिफ़ॉल्ट: 1)।
#OCR
ocr.title=OCR / स्कैन सफाई
ocr.header=स्कैन सफाई / OCR (ऑप्टिकल कैरेक्टर रिकग्निशन)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=पीडीएफ को ऑटो रोटेट क
imageToPDF.selectText.3=मल्टी फ़ाइल तर्क (केवल यदि कई छवियों के साथ काम किया जा रहा है)
imageToPDF.selectText.4=एक ही पीडीएफ में मर्ज करें
imageToPDF.selectText.5=अलग-अलग पीडीएफ में परिवर्तित करें
#pdfToImage
pdfToImage.title=पीडीएफ से छवि
pdfToImage.header=पीडीएफ से छवि

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=PDF tisztítása
sanitizePDF.header=PDF fájl megtisztítása
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=A fotók minimális kontúrterületének beállí
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).
#OCR
ocr.title=OCR / szkennelés tisztázása
ocr.header=Szkennelés tisztázása / OCR (Optikai karakterfelismerés)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Automatikus forgatás PDF
imageToPDF.selectText.3=Több fájl logika (csak akkor engedélyezett, ha több képpel dolgozik)
imageToPDF.selectText.4=Egyesítse egyetlen PDF-fé
imageToPDF.selectText.5=Átalakítás különálló PDF-fé
#pdfToImage
pdfToImage.title=PDF képpé alakítása
pdfToImage.header=PDF képpé alakítása

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Bersihkan PDF
sanitizePDF.header=Membersihkan berkas PDF
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Menetapkan ambang batas area kontur minimum untuk
ScannerImageSplit.selectText.9=Ukuran Batas:
ScannerImageSplit.selectText.10=Menetapkan ukuran batas yang ditambahkan dan dihapus untuk mencegah batas putih pada output (default: 1).
#OCR
ocr.title=OCR / Pembersihan Pindaian
ocr.header=Pemindaian Pembersihan / OCR (Pengenalan Karakter Optik)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Putar PDF secara otomatis
imageToPDF.selectText.3=Logika multi berkas (Hanya diaktifkan jika bekerja dengan banyak gambar)
imageToPDF.selectText.4=Gabungkan menjadi satu PDF
imageToPDF.selectText.5=Mengonversi ke PDF yang terpisah
#pdfToImage
pdfToImage.title=PDF ke Gambar
pdfToImage.header=PDF ke Gambar

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Y coördinaat overschrijven
AddStampRequest.customMargin=Aangepaste marge
AddStampRequest.customColor=Aangepaste tekstkleur
AddStampRequest.submit=Indienen
#sanitizePDF
sanitizePDF.title=PDF opschonen
sanitizePDF.header=Een PDF-bestand opschonen
@ -519,7 +519,7 @@ addPageNumbers.selectText.4=Startnummer
addPageNumbers.selectText.5=Pagina's om te nummeren
addPageNumbers.selectText.6=Aangepaste tekst
addPageNumbers.customTextDesc=Aangepaste tekst
addPageNumbers.numberPagesDesc=Welke pagina's genummerd moeten worden, standaard 'all', accepteert ook 1-5 of 2,5,9 etc
addPageNumbers.numberPagesDesc=Welke pagina's genummerd moeten worden, standaard 'all', accepteert ook 1-5 of 2,5,9 etc
addPageNumbers.customNumberDesc=Standaard {n}, accepteert ook 'Pagina {n} van {total}', 'Tekst-{n}', '{filename}-{n}
addPageNumbers.submit=Paginanummers toevoegen
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Stelt de minimale contour oppervlakte drempel in
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).
#OCR
ocr.title=OCR / Scan opruimen
ocr.header=Scans opruimen / OCR (Optical Character Recognition)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=PDF automatisch draaien
imageToPDF.selectText.3=Meervoudige bestandslogica (Alleen ingeschakeld bij werken met meerdere afbeeldingen)
imageToPDF.selectText.4=Voeg samen in één PDF
imageToPDF.selectText.5=Zet om naar afzonderlijke PDF's
#pdfToImage
pdfToImage.title=PDF naar afbeelding
pdfToImage.header=PDF naar afbeelding

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitizar PDF
sanitizePDF.header=Sanitizar um arquivo PDF
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Define o limite mínimo da área de contorno para
ScannerImageSplit.selectText.9=Tamanho da Borda:
ScannerImageSplit.selectText.10=Define o tamanho da borda adicionada e removida para evitar bordas brancas na saída (padrão: 1).
#OCR
ocr.title=OCR / Limpeza de Digitalização
ocr.header=OCR / Limpeza de Digitalização (Reconhecimento Óptico de Caracteres)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Girar Automaticamente
imageToPDF.selectText.3=Lógica de Vários Arquivos (Ativada apenas ao trabalhar com várias imagens)
imageToPDF.selectText.4=Mesclar em um Único PDF
imageToPDF.selectText.5=Converter em PDFs Separados
#pdfToImage
pdfToImage.title=PDF para Imagem
pdfToImage.header=Converter PDF para Imagem

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitize PDF
sanitizePDF.header=Sanitize a PDF file
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Stabilește pragul minim de arie a conturului pen
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).
#OCR
ocr.title=OCR / Curățare scanare
ocr.header=Curățare scanări / OCR (Recunoaștere optică a caracterelor)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Rotire automată a PDF-ului
imageToPDF.selectText.3=Logica pentru mai multe fișiere (activată numai dacă se lucrează cu mai multe imagini)
imageToPDF.selectText.4=Unifică într-un singur PDF
imageToPDF.selectText.5=Convertă în PDF-uri separate
#pdfToImage
pdfToImage.title=PDF în Imagine
pdfToImage.header=PDF în Imagine

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=Sanitizacija PDF-a
sanitizePDF.header=Sanitizacija PDF fajla
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Postavlja minimalni prag površine konture za fot
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).
#OCR
ocr.title=OCR / Čišćenje skeniranja
ocr.header=Čišćenje skeniranja / OCR (Optičko prepoznavanje znakova)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=Automatsko rotiranje PDF-a
imageToPDF.selectText.3=Logika za više fajlova (Omogućeno samo ako radite sa više slika)
imageToPDF.selectText.4=Spoji u jedan PDF
imageToPDF.selectText.5=Konvertuj u odvojene PDF-ove
#pdfToImage
pdfToImage.title=PDF u sliku
pdfToImage.header=PDF u sliku

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=PDF'i Temizle
sanitizePDF.header=PDF dosyasını temizle
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=Bir fotoğraf için minimum kontur alanı eşiği
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).
#OCR
ocr.title=OCR / Tarama Temizleme
ocr.header=Taramaları Temizle / OCR (Optik Karakter Tanıma)
@ -775,8 +775,8 @@ imageToPDF.selectText.2=PDF'yi otomatik döndür
imageToPDF.selectText.3=Çoklu dosya mantığı (Yalnızca birden fazla resimle çalışırken etkinleştirilir)
imageToPDF.selectText.4=Tek bir PDF'e birleştir
imageToPDF.selectText.5=Ayrı PDF'lere dönüştür
#pdfToImage
pdfToImage.title=PDF'den Resme
pdfToImage.header=PDF'den Resme

File diff suppressed because it is too large Load diff

View file

@ -497,7 +497,7 @@ AddStampRequest.overrideY=Override Y Coordinate
AddStampRequest.customMargin=Custom Margin
AddStampRequest.customColor=Custom Text Color
AddStampRequest.submit=Submit
#sanitizePDF
sanitizePDF.title=清理 PDF
sanitizePDF.header=清理 PDF 檔案
@ -656,7 +656,7 @@ ScannerImageSplit.selectText.8=設定照片的最小輪廓區域閾值
ScannerImageSplit.selectText.9=邊框大小:
ScannerImageSplit.selectText.10=設定新增和移除的邊框大小以防止輸出中的白色邊框預設1
#OCR
ocr.title=OCR / 掃描清理
ocr.header=清理掃描 / OCR光學字元識別
@ -775,8 +775,8 @@ imageToPDF.selectText.2=自動旋轉 PDF
imageToPDF.selectText.3=多文件邏輯(僅在處理多個影像時啟用)
imageToPDF.selectText.4=合併為單一 PDF
imageToPDF.selectText.5=轉換為單獨的 PDF
#pdfToImage
pdfToImage.title=PDF 轉圖片
pdfToImage.header=PDF 轉圖片

View file

@ -7,15 +7,15 @@ security:
csrfDisabled: true
loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
system:
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
customApplications:
bookAndHtmlFormatsInstalled: false # Installs Calibre for book format conversion (For non docker it must be manually downloaded but will need to be true to show in UI)
#ui:
# appName: exampleAppName # Application's visible name
# homeDescription: I am a description # Short description or tagline shown on homepage.

View file

@ -1,135 +1,135 @@
/* Dark Mode Styles */
body, select, textarea {
--body-background-color: 51, 51, 51;
--base-font-color: 255, 255, 255;
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.card {
background-color: rgb(var(--body-background-color)) !important;
border: 1px solid #999;
color: rgb(var(--base-font-color)) !important;
}
a {
color: #add8e6;
}
a:hover {
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
}
.dark-card {
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.jumbotron {
background-color: #222; /* or any other dark color */
color: rgb(var(--base-font-color)) !important; /* or any other light color */
}
.list-group {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
.list-group-item {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
#support-section {
background-color: #444 !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: rgb(var(--base-font-color)) !important;
}
.favorite-icon img {
filter: brightness(0) invert(1) !important;
}
table thead {
background-color: #333 !important;
border: 1px solid #444;
}
table th, table td {
border: 1px solid #444 !important;
color: white;
}
.btn {
background-color: #444 !important;
border: none;
color: #fff !important;
}
.btn-primary {
background-color: #007bff !important;
border: none;
color: #fff !important;
}
.btn-secondary {
background-color: #6c757d !important;
border: none;
color: #fff !important;
}
.btn-info {
background-color: #17a2b8 !important;
border: none;
color: #fff !important;
}
.btn-danger {
background-color: #dc3545 !important;
border: none;
color: #fff !important;
}
.btn-warning {
background-color: #ffc107 !important;
border: none;
color: #000 !important;
}
.btn-outline-secondary {
color: #fff !important;
border-color: #fff;
}
.btn-outline-secondary:hover {
background-color: #444 !important;
color: #007bff !important;
border-color: #007bff;
}
.blackwhite-icon {
filter: brightness(0) invert(1);
}
hr {
border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for <hr> */
}
.modal-content {
color: #fff !important;
border-color: #fff;
}
#global-buttons-container input {
background-color: #323948;
caret-color: #ffffff;
color: #ffffff;
}
#global-buttons-container input::placeholder {
color: #ffffff;
}
#global-buttons-container input:disabled::-webkit-input-placeholder { /* WebKit browsers */
color: #6E6865;
}
#global-buttons-container input:disabled:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #6E6865;
}
#global-buttons-container input:disabled::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #6E6865;
}
#global-buttons-container input:disabled:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #6E6865;
}
/* Dark Mode Styles */
body, select, textarea {
--body-background-color: 51, 51, 51;
--base-font-color: 255, 255, 255;
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.card {
background-color: rgb(var(--body-background-color)) !important;
border: 1px solid #999;
color: rgb(var(--base-font-color)) !important;
}
a {
color: #add8e6;
}
a:hover {
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
}
.dark-card {
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.jumbotron {
background-color: #222; /* or any other dark color */
color: rgb(var(--base-font-color)) !important; /* or any other light color */
}
.list-group {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
.list-group-item {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
#support-section {
background-color: #444 !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: rgb(var(--base-font-color)) !important;
}
.favorite-icon img {
filter: brightness(0) invert(1) !important;
}
table thead {
background-color: #333 !important;
border: 1px solid #444;
}
table th, table td {
border: 1px solid #444 !important;
color: white;
}
.btn {
background-color: #444 !important;
border: none;
color: #fff !important;
}
.btn-primary {
background-color: #007bff !important;
border: none;
color: #fff !important;
}
.btn-secondary {
background-color: #6c757d !important;
border: none;
color: #fff !important;
}
.btn-info {
background-color: #17a2b8 !important;
border: none;
color: #fff !important;
}
.btn-danger {
background-color: #dc3545 !important;
border: none;
color: #fff !important;
}
.btn-warning {
background-color: #ffc107 !important;
border: none;
color: #000 !important;
}
.btn-outline-secondary {
color: #fff !important;
border-color: #fff;
}
.btn-outline-secondary:hover {
background-color: #444 !important;
color: #007bff !important;
border-color: #007bff;
}
.blackwhite-icon {
filter: brightness(0) invert(1);
}
hr {
border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for <hr> */
}
.modal-content {
color: #fff !important;
border-color: #fff;
}
#global-buttons-container input {
background-color: #323948;
caret-color: #ffffff;
color: #ffffff;
}
#global-buttons-container input::placeholder {
color: #ffffff;
}
#global-buttons-container input:disabled::-webkit-input-placeholder { /* WebKit browsers */
color: #6E6865;
}
#global-buttons-container input:disabled:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #6E6865;
}
#global-buttons-container input:disabled::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #6E6865;
}
#global-buttons-container input:disabled:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #6E6865;
}

View file

@ -1,94 +1,94 @@
#page-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
#content-wrap {
flex: 1;
}
#footer {
bottom: 0;
width: 100%;
}
.navbar {
height: auto; /* Adjusts height automatically based on content */
white-space: nowrap; /* Prevents wrapping of navbar contents */
}
/* TODO enable later
.navbar .container {
max-width: 100%; //Allows the container to expand up to full width
margin-left: auto;
margin-right: auto;
}*/
html[lang-direction=ltr] * {
direction: ltr;
}
html[lang-direction=rtl] * {
direction: rtl;
text-align: right;
}
.ignore-rtl {
direction: ltr !important;
text-align: left !important;
}
.align-top {
position: absolute;
top: 0;
}
.align-center-right {
position: absolute;
right: 0;
top: 50%;
}
.align-center-left {
position: absolute;
left: 0;
top: 50%;
}
.align-bottom {
position: absolute;
bottom: 0;
}
.btn-group > label:first-of-type {
border-top-left-radius: 0.25rem !important;
border-bottom-left-radius: 0.25rem !important;
}
html[lang-direction="rtl"] input.form-check-input {
position: relative;
margin-left: 0px;
}
html[lang-direction="rtl"] label.form-check-label {
display: inline;
}
.margin-auto-parent {
width: 100%;
display: flex;
}
.margin-center {
margin: 0 auto;
}
#pdf-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.fixed-shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
}
.hidden {
display: none;
#page-container {
min-height: 100vh;
display: flex;
flex-direction: column;
}
#content-wrap {
flex: 1;
}
#footer {
bottom: 0;
width: 100%;
}
.navbar {
height: auto; /* Adjusts height automatically based on content */
white-space: nowrap; /* Prevents wrapping of navbar contents */
}
/* TODO enable later
.navbar .container {
max-width: 100%; //Allows the container to expand up to full width
margin-left: auto;
margin-right: auto;
}*/
html[lang-direction=ltr] * {
direction: ltr;
}
html[lang-direction=rtl] * {
direction: rtl;
text-align: right;
}
.ignore-rtl {
direction: ltr !important;
text-align: left !important;
}
.align-top {
position: absolute;
top: 0;
}
.align-center-right {
position: absolute;
right: 0;
top: 50%;
}
.align-center-left {
position: absolute;
left: 0;
top: 50%;
}
.align-bottom {
position: absolute;
bottom: 0;
}
.btn-group > label:first-of-type {
border-top-left-radius: 0.25rem !important;
border-bottom-left-radius: 0.25rem !important;
}
html[lang-direction="rtl"] input.form-check-input {
position: relative;
margin-left: 0px;
}
html[lang-direction="rtl"] label.form-check-label {
display: inline;
}
.margin-auto-parent {
width: 100%;
display: flex;
}
.margin-center {
margin: 0 auto;
}
#pdf-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.fixed-shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
width: 100%;
}
.shadow-canvas {
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.384);
}
.hidden {
display: none;
}

View file

@ -1,29 +1,29 @@
.list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.filename {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.arrows {
flex-shrink: 0;
display: flex;
justify-content: flex-end;
}
.arrows .btn {
margin: 0 3px;
}
.move-up span,
.move-down span {
font-weight: bold;
font-size: 1.2em;
}
.list-group-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.filename {
flex-grow: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 10px;
}
.arrows {
flex-shrink: 0;
display: flex;
justify-content: flex-end;
}
.arrows .btn {
margin: 0 3px;
}
.move-up span,
.move-down span {
font-weight: bold;
font-size: 1.2em;
}

View file

@ -32,7 +32,7 @@
translate: 0 -50%;
width: 80px;
height: 100%;
z-index: 1;
opacity: 0;
transition: opacity 0.2s;

View file

@ -34,4 +34,4 @@ body {
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: #ffffff !important;
}

View file

@ -16,7 +16,7 @@
background: 0 0;
border: 1px solid transparent;
color: rgb(var(--base-font-color));
border-top-left-radius: 0.25rem;
border-top-right-radius: 0.25rem;
}

View file

@ -19,8 +19,8 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs173">
<linearGradient
id="XMLID_5_"
gradientUnits="userSpaceOnUse"
@ -37,7 +37,7 @@
style="stop-color:#C2C2C9"
id="stop158" />
</linearGradient>
</defs><sodipodi:namedview
id="namedview171"
pagecolor="#ffffff"

Before

Width:  |  Height:  |  Size: 4 KiB

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -1,26 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1235" height="650" viewBox="0 0 7410 3900">
<rect width="7410" height="3900" fill="#b22234"/>
<path d="M0,450H7410m0,600H0m0,600H7410m0,600H0m0,600H7410m0,600H0" stroke="#fff" stroke-width="300"/>
<rect width="2964" height="2100" fill="#3c3b6e"/>
<g fill="#fff">
<g id="s18">
<g id="s9">
<g id="s5">
<g id="s4">
<path id="s" d="M247,90 317.534230,307.082039 132.873218,172.917961H361.126782L176.465770,307.082039z"/>
<use xlink:href="#s" y="420"/>
<use xlink:href="#s" y="840"/>
<use xlink:href="#s" y="1260"/>
</g>
<use xlink:href="#s" y="1680"/>
</g>
<use xlink:href="#s4" x="247" y="210"/>
</g>
<use xlink:href="#s9" x="494"/>
</g>
<use xlink:href="#s18" x="988"/>
<use xlink:href="#s9" x="1976"/>
<use xlink:href="#s5" x="2470"/>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1235" height="650" viewBox="0 0 7410 3900">
<rect width="7410" height="3900" fill="#b22234"/>
<path d="M0,450H7410m0,600H0m0,600H7410m0,600H0m0,600H7410m0,600H0" stroke="#fff" stroke-width="300"/>
<rect width="2964" height="2100" fill="#3c3b6e"/>
<g fill="#fff">
<g id="s18">
<g id="s9">
<g id="s5">
<g id="s4">
<path id="s" d="M247,90 317.534230,307.082039 132.873218,172.917961H361.126782L176.465770,307.082039z"/>
<use xlink:href="#s" y="420"/>
<use xlink:href="#s" y="840"/>
<use xlink:href="#s" y="1260"/>
</g>
<use xlink:href="#s" y="1680"/>
</g>
<use xlink:href="#s4" x="247" y="210"/>
</g>
<use xlink:href="#s9" x="494"/>
</g>
<use xlink:href="#s18" x="988"/>
<use xlink:href="#s9" x="1976"/>
<use xlink:href="#s5" x="2470"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 899 B

After

Width:  |  Height:  |  Size: 874 B

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="35px" height="35px" viewBox="0 -0.5 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Github-color</title>
<desc>Created with Sketch.</desc>
<defs>

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.1" id="Icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
<svg version="1.1" id="Icons" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 32 32" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}

Before

Width:  |  Height:  |  Size: 691 B

After

Width:  |  Height:  |  Size: 690 B

View file

@ -5,16 +5,16 @@ function showErrorBanner(message, stackTrace) {
document.querySelector("#errorContainer p").textContent = message;
document.querySelector("#traceContent").textContent = stackTrace;
}
let firstErrorOccurred = false;
let firstErrorOccurred = false;
$(document).ready(function() {
$('form').submit(async function(event) {
event.preventDefault();
firstErrorOccurred = false;
firstErrorOccurred = false;
const url = this.action;
const files = $('#fileInput-input')[0].files;
const formData = new FormData(this);
// Remove empty file entries
for (let [key, value] of formData.entries()) {
if (value instanceof File && !value.name) {
@ -113,7 +113,7 @@ async function handleResponse(blob, filename, considerViewOptions = false, isZip
const url = URL.createObjectURL(blob);
window.open(url, '_blank');
return;
}
}
}
if(!isZip){
downloadFile(blob, filename);
@ -152,20 +152,20 @@ async function submitMultiPdfForm(url, files) {
// Show the progress bar
$('#progressBarContainer').show();
// Initialize the progress bar
let progressBar = $('#progressBar');
progressBar.css('width', '0%');
progressBar.attr('aria-valuenow', 0);
progressBar.attr('aria-valuemax', files.length);
if (zipFiles) {
jszip = new JSZip();
}
// Get the form with the method attribute set to POST
let postForm = document.querySelector('form[method="POST"]');
// Get existing form data
let formData;
if (postForm) {
@ -191,11 +191,11 @@ async function submitMultiPdfForm(url, files) {
const promises = chunk.map(async file => {
let fileFormData = new FormData();
fileFormData.append('fileInput', file);
console.log(fileFormData);
console.log(fileFormData);
// Add other form data
for (let pair of formData.entries()) {
fileFormData.append(pair[0], pair[1]);
console.log(pair[0]+ ', ' + pair[1]);
console.log(pair[0]+ ', ' + pair[1]);
}
try {
@ -213,7 +213,7 @@ async function submitMultiPdfForm(url, files) {
}
});
await Promise.all(promises);
}
if (zipFiles) {

View file

@ -120,7 +120,7 @@ const DraggableUtils = {
newWidth = newWidth * scaleMultiplier;
newHeight = newHeight * scaleMultiplier;
}
createdCanvas.style.width = newWidth+"px";
createdCanvas.style.height = newHeight+"px";
@ -147,7 +147,7 @@ const DraggableUtils = {
if (!pagesMap) {
pagesMap = {};
}
const elements = [...this.boxDragContainer.querySelectorAll(".draggable-canvas")];
const draggablesData = elements.map(el => {return{element:el, offsetWidth:el.offsetWidth, offsetHeight:el.offsetHeight}});
elements.forEach(el => this.boxDragContainer.removeChild(el));
@ -164,7 +164,7 @@ const DraggableUtils = {
if (!pagesMap) {
return;
}
const draggablesData = pagesMap[this.pageIndex];
if (draggablesData) {
draggablesData.forEach(draggableData => this.boxDragContainer.appendChild(draggableData.element));
@ -177,7 +177,7 @@ const DraggableUtils = {
this.pdfDoc = pdfDocument ? pdfDocument : this.pdfDoc;
this.pageIndex = pageIdx;
// persist
// persist
const page = await this.pdfDoc.getPage(this.pageIndex+1);
// set the canvas size to the size of the page
@ -214,7 +214,7 @@ const DraggableUtils = {
},
parseTransform(element) {
},
async getOverlayedPdfDocument() {
const pdfBytes = await this.pdfDoc.getData();
@ -227,7 +227,7 @@ const DraggableUtils = {
continue;
}
console.log(typeof pageIdx);
const page = pdfDocModified.getPage(parseInt(pageIdx));
const draggablesData = pagesMap[pageIdx];
const offsetWidth = pagesMap[pageIdx+"-offsetWidth"];
@ -239,7 +239,7 @@ const DraggableUtils = {
const response = await fetch(draggableElement.toDataURL());
const draggableImgBytes = await response.arrayBuffer();
const pdfImageObject = await pdfDocModified.embedPng(draggableImgBytes);
// calculate the position in the pdf document
const tansform = draggableElement.style.transform.replace(/[^.,-\d]/g, '');
const transformComponents = tansform.split(",");
@ -261,7 +261,7 @@ const DraggableUtils = {
width: draggablePositionRelative.width * page.getWidth(),
height: draggablePositionRelative.height * page.getHeight(),
}
// draw the image
page.drawImage(pdfImageObject, {
x: draggablePositionPdf.x,

View file

@ -1,6 +1,6 @@
function updateFavoritesDropdown() {
var dropdown = document.querySelector('#favoritesDropdown');
// Check if dropdown exists
if (!dropdown) {
console.error('Dropdown element with ID "favoritesDropdown" not found!');

View file

@ -81,7 +81,7 @@ function setupFileInput(chooser) {
document.body.addEventListener('drop', dropListener);
$("#" + elementId).on("change", function(e) {
allFiles = Array.from(e.target.files);
allFiles = Array.from(e.target.files);
handleFileInputChange(this);
});

View file

@ -1,11 +1,11 @@
function initializeGame() {
const gameContainer = document.getElementById('game-container');
const player = document.getElementById('player');
let playerSize = gameContainer.clientWidth * 0.0625; // 5% of container width
player.style.width = playerSize + 'px';
player.style.height = playerSize + 'px';
let playerX = gameContainer.clientWidth / 2 - playerSize / 2;
let playerY = gameContainer.clientHeight * 0.1;
const scoreElement = document.getElementById('score');
@ -18,12 +18,12 @@ function initializeGame() {
let projectileHeight = gameContainer.clientHeight * 0.01667; // 1% of container height
let paused = false;
const fireRate = 200; // Time between shots in milliseconds
let lastProjectileTime = 0;
let lives = 3;
let highScore = localStorage.getItem('highScore') ? parseInt(localStorage.getItem('highScore')) : 0;
updateHighScore();
@ -195,7 +195,7 @@ function initializeGame() {
score = 0;
level = 1;
lives = 3;
gameOver = false;
updateScore();

View file

@ -7,7 +7,7 @@ function filterCards() {
var card = cards[i];
var title = card.querySelector('h5.card-title').innerText;
var text = card.querySelector('p.card-text').innerText;
// Get the navbar tags associated with the card
var navbarItem = document.querySelector(`a.dropdown-item[href="${card.id}"]`);
var navbarTags = navbarItem ? navbarItem.getAttribute('data-bs-tags') : '';

View file

@ -8,13 +8,13 @@ document.addEventListener('DOMContentLoaded', function() {
// Check if the dropdown contains the browser's language
const dropdownLangExists = document.querySelector(`.lang_dropdown-item[data-language-code="${browserLang}"]`);
// Set the default language to browser's language or 'en_GB' if not found in the dropdown
const defaultLocale = dropdownLangExists ? browserLang : 'en_GB';
const storedLocale = localStorage.getItem('languageCode') || defaultLocale;
const dropdownItems = document.querySelectorAll('.lang_dropdown-item');
for (let i = 0; i < dropdownItems.length; i++) {
@ -70,7 +70,7 @@ document.addEventListener('DOMContentLoaded', function() {
element.remove();
}
});
//Sort languages by alphabet
const list = Array.from(document.querySelector('.dropdown-menu[aria-labelledby="languageDropdown"]').children).filter(child => child.matches('a'));
list.sort(function(a, b) {

View file

@ -9,7 +9,7 @@ document.getElementById("fileInput-input").addEventListener("change", function()
});
/**
* @param {FileList} files
* @param {FileList} files
*/
function displayFiles(files) {
const list = document.getElementById("selectedFiles");

View file

@ -73,7 +73,7 @@ class DragDropManager {
stopDraggingPage() {
window.removeEventListener('mousemove', this.onDragEl);
this.wrapper.classList.remove('drag-manager_dragging-container');
this.wrapper.removeChild(this.endInsertionElement);
this.wrapper.removeChild(this.endInsertionElement);
window.removeEventListener('mouseup', this.stopDraggingPage)
this.draggedImageEl = undefined;
this.pageDragging = false;

View file

@ -1,5 +1,5 @@
class PdfActionsManager {
pageDirection;
pageDirection;
pagesContainer;
constructor(id) {
@ -23,7 +23,7 @@ class PdfActionsManager {
moveUpButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const sibling = imgContainer.previousSibling;
if (sibling) {
this.movePageTo(imgContainer, sibling, true);
@ -41,14 +41,14 @@ class PdfActionsManager {
rotateCCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
this.rotateElement(img, -90)
};
rotateCWButtonCallback(e) {
var imgContainer = this.getPageContainer(e.target);
const img = imgContainer.querySelector("img");
this.rotateElement(img, 90)
};
@ -93,7 +93,7 @@ class PdfActionsManager {
const buttonContainer = document.createElement('div');
buttonContainer.classList.add("pdf-actions_button-container", "hide-on-drag");
const moveUp = document.createElement('button');
moveUp.classList.add("pdf-actions_move-left-button","btn", "btn-secondary");
moveUp.innerHTML = `<i class="bi bi-arrow-${leftDirection}-short"></i>`;
@ -105,7 +105,7 @@ class PdfActionsManager {
moveDown.innerHTML = `<i class="bi bi-arrow-${rightDirection}-short"></i>`;
moveDown.onclick = this.moveDownButtonCallback;
buttonContainer.appendChild(moveDown);
const rotateCCW = document.createElement('button');
rotateCCW.classList.add("btn", "btn-secondary");
rotateCCW.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-counterclockwise" viewBox="0 0 16 16">
@ -136,12 +136,12 @@ class PdfActionsManager {
div.appendChild(buttonContainer);
const insertFileButtonContainer = document.createElement('div');
insertFileButtonContainer.classList.add(
"pdf-actions_insert-file-button-container",
leftDirection,
`align-center-${leftDirection}`);
const insertFileButton = document.createElement('button');
insertFileButton.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButton.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">
@ -150,16 +150,16 @@ class PdfActionsManager {
</svg>`;
insertFileButton.onclick = this.insertFileButtonCallback;
insertFileButtonContainer.appendChild(insertFileButton);
div.appendChild(insertFileButtonContainer);
// add this button to every element, but only show it on the last one :D
const insertFileButtonRightContainer = document.createElement('div');
insertFileButtonRightContainer.classList.add(
"pdf-actions_insert-file-button-container",
rightDirection,
`align-center-${rightDirection}`);
const insertFileButtonRight = document.createElement('button');
insertFileButtonRight.classList.add("btn", "btn-primary", "pdf-actions_insert-file-button");
insertFileButtonRight.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-plus" viewBox="0 0 16 16">

View file

@ -1,285 +1,285 @@
class PdfContainer {
fileName;
pagesContainer;
pagesContainerWrapper;
pdfAdapters;
downloadLink;
constructor(id, wrapperId, pdfAdapters) {
this.pagesContainer = document.getElementById(id)
this.pagesContainerWrapper = document.getElementById(wrapperId);
this.downloadLink = null;
this.movePageTo = this.movePageTo.bind(this);
this.addPdfs = this.addPdfs.bind(this);
this.addPdfsFromFiles = this.addPdfsFromFiles.bind(this);
this.rotateElement = this.rotateElement.bind(this);
this.rotateAll = this.rotateAll.bind(this);
this.exportPdf = this.exportPdf.bind(this);
this.updateFilename = this.updateFilename.bind(this);
this.setDownloadAttribute = this.setDownloadAttribute.bind(this);
this.preventIllegalChars = this.preventIllegalChars.bind(this);
this.pdfAdapters = pdfAdapters;
this.pdfAdapters.forEach(adapter => {
adapter.setActions({
movePageTo: this.movePageTo,
addPdfs: this.addPdfs,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename
})
})
window.addPdfs = this.addPdfs;
window.exportPdf = this.exportPdf;
window.rotateAll = this.rotateAll;
const filenameInput = document.getElementById('filename-input');
const downloadBtn = document.getElementById('export-button');
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = false;
filenameInput.innerText = "";
downloadBtn.disabled = true;
}
movePageTo(startElement, endElement, scrollTo = false) {
const childArray = Array.from(this.pagesContainer.childNodes);
const startIndex = childArray.indexOf(startElement);
const endIndex = childArray.indexOf(endElement);
this.pagesContainer.removeChild(startElement);
if(!endElement) {
this.pagesContainer.append(startElement);
} else {
this.pagesContainer.insertBefore(startElement, endElement);
}
if(scrollTo) {
const { width } = startElement.getBoundingClientRect();
const vector = (endIndex !== -1 && startIndex > endIndex)
? 0-width
: width;
this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector,
})
}
}
addPdfs(nextSiblingElement) {
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.setAttribute("accept", "application/pdf");
input.onchange = async(e) => {
const files = e.target.files;
this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
}
input.click();
}
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i=0; i < files.length; i++) {
await this.addPdfFile(files[i], nextSiblingElement);
}
document.querySelectorAll(".enable-on-file").forEach(element => {
element.disabled = false;
});
}
rotateElement(element, deg) {
var lastTransform = element.style.rotate;
if (!lastTransform) {
lastTransform = "0";
}
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ''));
const newAngle = lastAngle + deg;
element.style.rotate = newAngle + "deg";
}
async addPdfFile(file, nextSiblingElement) {
const { renderer, pdfDocument } = await this.loadFile(file);
for (var i=0; i < renderer.pageCount; i++) {
const div = document.createElement('div');
div.classList.add("page-container");
var img = document.createElement('img');
img.classList.add('page-image')
const imageSrc = await renderer.renderPage(i)
img.src = imageSrc;
img.pageIdx = i;
img.rend = renderer;
img.doc = pdfDocument;
div.appendChild(img);
this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div)
})
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}
async loadFile(file) {
var objectUrl = URL.createObjectURL(file);
var pdfDocument = await this.toPdfLib(objectUrl);
var renderer = await this.toRenderer(objectUrl);
return { renderer, pdfDocument };
}
async toRenderer(objectUrl) {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
pageCount: pdf.numPages,
renderPage: async function(pageIdx) {
const page = await this.document.getPage(pageIdx+1);
const canvas = document.createElement("canvas");
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
canvas.width = page.view[3];
canvas.height = page.view[2];
} else {
canvas.width = page.view[2];
canvas.height = page.view[3];
}
// render the page onto the canvas
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 })
};
await page.render(renderContext).promise;
return canvas.toDataURL();
}
};
}
async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes, { ignoreEncryption: true });
return pdfDoc;
}
rotateAll(deg) {
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
const img = this.pagesContainer.childNodes[i].querySelector("img");
if (!img) continue;
this.rotateElement(img, deg)
}
}
async exportPdf() {
const pdfDoc = await PDFLib.PDFDocument.create();
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
for (var i = 0; i < pageContainers.length; i++) {
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
const page = pages[0];
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
}
pdfDoc.addPage(page);
}
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(pdfBlob);
const downloadOption = localStorage.getItem('downloadOption');
const filenameInput = document.getElementById('filename-input');
let inputArr = filenameInput.value.split('.');
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
inputArr = inputArr.filter(n => n); // remove all empty strings, nulls or undefined
if (inputArr.length > 1) {
inputArr.pop(); // remove right part after last dot
}
filenameInput.value = inputArr.join('');
this.fileName = filenameInput.value;
}
if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf';
this.fileName = filenameInput.value;
}
if (downloadOption === 'sameWindow') {
// Open the file in the same window
window.location.href = url;
} else if (downloadOption === 'newWindow') {
// Open the file in a new window
window.open(url, '_blank');
} else {
// Download the file
this.downloadLink = document.createElement('a');
this.downloadLink.id = 'download-link';
this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName;
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
}
}
setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : 'managed.pdf');
}
updateFilename(fileName = "") {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
downloadBtn.disabled = pagesContainer.childElementCount === 0
if (!this.fileName) {
this.fileName = fileName;
}
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
preventIllegalChars(e) {
// const filenameInput = document.getElementById('filename-input');
//
// filenameInput.value = filenameInput.value.replace('.pdf', '');
//
// // prevent .
// if (filenameInput.value.includes('.')) {
// filenameInput.value.replace('.','');
// }
}
}
export default PdfContainer;
class PdfContainer {
fileName;
pagesContainer;
pagesContainerWrapper;
pdfAdapters;
downloadLink;
constructor(id, wrapperId, pdfAdapters) {
this.pagesContainer = document.getElementById(id)
this.pagesContainerWrapper = document.getElementById(wrapperId);
this.downloadLink = null;
this.movePageTo = this.movePageTo.bind(this);
this.addPdfs = this.addPdfs.bind(this);
this.addPdfsFromFiles = this.addPdfsFromFiles.bind(this);
this.rotateElement = this.rotateElement.bind(this);
this.rotateAll = this.rotateAll.bind(this);
this.exportPdf = this.exportPdf.bind(this);
this.updateFilename = this.updateFilename.bind(this);
this.setDownloadAttribute = this.setDownloadAttribute.bind(this);
this.preventIllegalChars = this.preventIllegalChars.bind(this);
this.pdfAdapters = pdfAdapters;
this.pdfAdapters.forEach(adapter => {
adapter.setActions({
movePageTo: this.movePageTo,
addPdfs: this.addPdfs,
rotateElement: this.rotateElement,
updateFilename: this.updateFilename
})
})
window.addPdfs = this.addPdfs;
window.exportPdf = this.exportPdf;
window.rotateAll = this.rotateAll;
const filenameInput = document.getElementById('filename-input');
const downloadBtn = document.getElementById('export-button');
filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = false;
filenameInput.innerText = "";
downloadBtn.disabled = true;
}
movePageTo(startElement, endElement, scrollTo = false) {
const childArray = Array.from(this.pagesContainer.childNodes);
const startIndex = childArray.indexOf(startElement);
const endIndex = childArray.indexOf(endElement);
this.pagesContainer.removeChild(startElement);
if(!endElement) {
this.pagesContainer.append(startElement);
} else {
this.pagesContainer.insertBefore(startElement, endElement);
}
if(scrollTo) {
const { width } = startElement.getBoundingClientRect();
const vector = (endIndex !== -1 && startIndex > endIndex)
? 0-width
: width;
this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector,
})
}
}
addPdfs(nextSiblingElement) {
var input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.setAttribute("accept", "application/pdf");
input.onchange = async(e) => {
const files = e.target.files;
this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
}
input.click();
}
async addPdfsFromFiles(files, nextSiblingElement) {
this.fileName = files[0].name;
for (var i=0; i < files.length; i++) {
await this.addPdfFile(files[i], nextSiblingElement);
}
document.querySelectorAll(".enable-on-file").forEach(element => {
element.disabled = false;
});
}
rotateElement(element, deg) {
var lastTransform = element.style.rotate;
if (!lastTransform) {
lastTransform = "0";
}
const lastAngle = parseInt(lastTransform.replace(/[^\d-]/g, ''));
const newAngle = lastAngle + deg;
element.style.rotate = newAngle + "deg";
}
async addPdfFile(file, nextSiblingElement) {
const { renderer, pdfDocument } = await this.loadFile(file);
for (var i=0; i < renderer.pageCount; i++) {
const div = document.createElement('div');
div.classList.add("page-container");
var img = document.createElement('img');
img.classList.add('page-image')
const imageSrc = await renderer.renderPage(i)
img.src = imageSrc;
img.pageIdx = i;
img.rend = renderer;
img.doc = pdfDocument;
div.appendChild(img);
this.pdfAdapters.forEach((adapter) => {
adapter.adapt?.(div)
})
if (nextSiblingElement) {
this.pagesContainer.insertBefore(div, nextSiblingElement);
} else {
this.pagesContainer.appendChild(div);
}
}
}
async loadFile(file) {
var objectUrl = URL.createObjectURL(file);
var pdfDocument = await this.toPdfLib(objectUrl);
var renderer = await this.toRenderer(objectUrl);
return { renderer, pdfDocument };
}
async toRenderer(objectUrl) {
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdfjs/pdf.worker.js'
const pdf = await pdfjsLib.getDocument(objectUrl).promise;
return {
document: pdf,
pageCount: pdf.numPages,
renderPage: async function(pageIdx) {
const page = await this.document.getPage(pageIdx+1);
const canvas = document.createElement("canvas");
// set the canvas size to the size of the page
if (page.rotate == 90 || page.rotate == 270) {
canvas.width = page.view[3];
canvas.height = page.view[2];
} else {
canvas.width = page.view[2];
canvas.height = page.view[3];
}
// render the page onto the canvas
var renderContext = {
canvasContext: canvas.getContext("2d"),
viewport: page.getViewport({ scale: 1 })
};
await page.render(renderContext).promise;
return canvas.toDataURL();
}
};
}
async toPdfLib(objectUrl) {
const existingPdfBytes = await fetch(objectUrl).then(res => res.arrayBuffer());
const pdfDoc = await PDFLib.PDFDocument.load(existingPdfBytes, { ignoreEncryption: true });
return pdfDoc;
}
rotateAll(deg) {
for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
const img = this.pagesContainer.childNodes[i].querySelector("img");
if (!img) continue;
this.rotateElement(img, deg)
}
}
async exportPdf() {
const pdfDoc = await PDFLib.PDFDocument.create();
const pageContainers = this.pagesContainer.querySelectorAll('.page-container'); // Select all .page-container elements
for (var i = 0; i < pageContainers.length; i++) {
const img = pageContainers[i].querySelector("img"); // Find the img element within each .page-container
if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
const page = pages[0];
const rotation = img.style.rotate;
if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
}
pdfDoc.addPage(page);
}
const pdfBytes = await pdfDoc.save();
const pdfBlob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(pdfBlob);
const downloadOption = localStorage.getItem('downloadOption');
const filenameInput = document.getElementById('filename-input');
let inputArr = filenameInput.value.split('.');
if (inputArr !== null && inputArr !== undefined && inputArr.length > 0) {
inputArr = inputArr.filter(n => n); // remove all empty strings, nulls or undefined
if (inputArr.length > 1) {
inputArr.pop(); // remove right part after last dot
}
filenameInput.value = inputArr.join('');
this.fileName = filenameInput.value;
}
if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf';
this.fileName = filenameInput.value;
}
if (downloadOption === 'sameWindow') {
// Open the file in the same window
window.location.href = url;
} else if (downloadOption === 'newWindow') {
// Open the file in a new window
window.open(url, '_blank');
} else {
// Download the file
this.downloadLink = document.createElement('a');
this.downloadLink.id = 'download-link';
this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName;
this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click();
}
}
setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.fileName ? this.fileName : 'managed.pdf');
}
updateFilename(fileName = "") {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
downloadBtn.disabled = pagesContainer.childElementCount === 0
if (!this.fileName) {
this.fileName = fileName;
}
if (!filenameInput.value) {
filenameInput.value = this.fileName;
}
}
preventIllegalChars(e) {
// const filenameInput = document.getElementById('filename-input');
//
// filenameInput.value = filenameInput.value.replace('.pdf', '');
//
// // prevent .
// if (filenameInput.value.includes('.')) {
// filenameInput.value.replace('.','');
// }
}
}
export default PdfContainer;

View file

@ -17,7 +17,7 @@ const scrollDivHorizontally = (id) => {
}
}
divToScrollHorizontally.addEventListener("wheel", function(e) {
e.preventDefault(); // prevent default mousewheel behavior

File diff suppressed because it is too large Load diff

View file

@ -1,75 +1,75 @@
// Toggle search bar when the search icon is clicked
document.querySelector('#search-icon').addEventListener('click', function(e) {
e.preventDefault();
var searchBar = document.querySelector('#navbarSearch');
searchBar.classList.toggle('show');
});
window.onload = function() {
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var dummyContainer = document.createElement('div');
dummyContainer.style.position = 'absolute';
dummyContainer.style.visibility = 'hidden';
dummyContainer.style.whiteSpace = 'nowrap'; // Ensure we measure full width
document.body.appendChild(dummyContainer);
var maxWidth = 0;
items.forEach(function(item) {
var clone = item.cloneNode(true);
dummyContainer.appendChild(clone);
var width = clone.offsetWidth;
if (width > maxWidth) {
maxWidth = width;
}
dummyContainer.removeChild(clone);
});
document.body.removeChild(dummyContainer);
// Store max width for later use
window.navItemMaxWidth = maxWidth;
};
// Show search results as user types in search box
document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
var searchText = e.target.value.toLowerCase();
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var resultsBox = document.querySelector('#searchResults');
// Clear any previous results
resultsBox.innerHTML = '';
items.forEach(function(item) {
var titleElement = item.querySelector('.icon-text');
var iconElement = item.querySelector('.icon');
var itemHref = item.getAttribute('href');
var tags = item.getAttribute('data-bs-tags') || ""; // If no tags, default to empty string
if (titleElement && iconElement && itemHref !== '#') {
var title = titleElement.innerText;
if ((title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
var result = document.createElement('a');
result.href = itemHref;
result.classList.add('dropdown-item');
var resultIcon = document.createElement('img');
resultIcon.src = iconElement.src;
resultIcon.alt = 'icon';
resultIcon.classList.add('icon');
result.appendChild(resultIcon);
var resultText = document.createElement('span');
resultText.textContent = title;
resultText.classList.add('icon-text');
result.appendChild(resultText);
resultsBox.appendChild(result);
}
}
});
// Set the width of the search results box to the maximum width
resultsBox.style.width = window.navItemMaxWidth + 'px';
});
// Toggle search bar when the search icon is clicked
document.querySelector('#search-icon').addEventListener('click', function(e) {
e.preventDefault();
var searchBar = document.querySelector('#navbarSearch');
searchBar.classList.toggle('show');
});
window.onload = function() {
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var dummyContainer = document.createElement('div');
dummyContainer.style.position = 'absolute';
dummyContainer.style.visibility = 'hidden';
dummyContainer.style.whiteSpace = 'nowrap'; // Ensure we measure full width
document.body.appendChild(dummyContainer);
var maxWidth = 0;
items.forEach(function(item) {
var clone = item.cloneNode(true);
dummyContainer.appendChild(clone);
var width = clone.offsetWidth;
if (width > maxWidth) {
maxWidth = width;
}
dummyContainer.removeChild(clone);
});
document.body.removeChild(dummyContainer);
// Store max width for later use
window.navItemMaxWidth = maxWidth;
};
// Show search results as user types in search box
document.querySelector('#navbarSearchInput').addEventListener('input', function(e) {
var searchText = e.target.value.toLowerCase();
var items = document.querySelectorAll('.dropdown-item, .nav-link');
var resultsBox = document.querySelector('#searchResults');
// Clear any previous results
resultsBox.innerHTML = '';
items.forEach(function(item) {
var titleElement = item.querySelector('.icon-text');
var iconElement = item.querySelector('.icon');
var itemHref = item.getAttribute('href');
var tags = item.getAttribute('data-bs-tags') || ""; // If no tags, default to empty string
if (titleElement && iconElement && itemHref !== '#') {
var title = titleElement.innerText;
if ((title.toLowerCase().indexOf(searchText) !== -1 || tags.toLowerCase().indexOf(searchText) !== -1) && !resultsBox.querySelector(`a[href="${item.getAttribute('href')}"]`)) {
var result = document.createElement('a');
result.href = itemHref;
result.classList.add('dropdown-item');
var resultIcon = document.createElement('img');
resultIcon.src = iconElement.src;
resultIcon.alt = 'icon';
resultIcon.classList.add('icon');
result.appendChild(resultIcon);
var resultText = document.createElement('span');
resultText.textContent = title;
resultText.classList.add('icon-text');
result.appendChild(resultText);
resultsBox.appendChild(result);
}
}
});
// Set the width of the search results box to the maximum width
resultsBox.style.width = window.navItemMaxWidth + 'px';
});

View file

@ -6,7 +6,7 @@ TabContainer = {
unloadedGroups.forEach(group => {
const containers = group.querySelectorAll(".tab-container");
const tabTitles = [...containers].map(c => c.getAttribute("title"));
const tabList = document.createElement("div");
tabList.classList.add("tab-buttons");
tabTitles.forEach(title => {

View file

@ -15,6 +15,6 @@
],
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"background_color": "#ffffff",
"theme_color": "#000000"
}

View file

@ -1,3 +1,3 @@
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
See ./LICENSEáCNS2-H

View file

@ -1,3 +1,3 @@
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
àRCopyright 1990-2009 Adobe Systems Incorporated.
All rights reserved.
See ./LICENSEá ETen-B5-H` ^

View file

@ -13,12 +13,12 @@
%%Copyright: Redistributions in binary form must reproduce the above
%%Copyright: copyright notice, this list of conditions and the following
%%Copyright: disclaimer in the documentation and/or other materials
%%Copyright: provided with the distribution.
%%Copyright: provided with the distribution.
%%Copyright:
%%Copyright: Neither the name of Adobe Systems Incorporated nor the names
%%Copyright: of its contributors may be used to endorse or promote
%%Copyright: products derived from this software without specific prior
%%Copyright: written permission.
%%Copyright: written permission.
%%Copyright:
%%Copyright: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
%%Copyright: CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,

View file

@ -1,4 +1,4 @@
<svg width="12" height="13" viewBox="0 0 12 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.375 7.625V11.875C5.375 12.0408 5.44085 12.1997 5.55806 12.3169C5.67527 12.4342 5.83424 12.5 6 12.5C6.16576 12.5 6.32473 12.4342 6.44194 12.3169C6.55915 12.1997 6.625 12.0408 6.625 11.875V7.625L7.125 7.125H11.375C11.5408 7.125 11.6997 7.05915 11.8169 6.94194C11.9342 6.82473 12 6.66576 12 6.5C12 6.33424 11.9342 6.17527 11.8169 6.05806C11.6997 5.94085 11.5408 5.875 11.375 5.875H7.125L6.625 5.375V1.125C6.625 0.95924 6.55915 0.800269 6.44194 0.683058C6.32473 0.565848 6.16576 0.5 6 0.5C5.83424 0.5 5.67527 0.565848 5.55806 0.683058C5.44085 0.800269 5.375 0.95924 5.375 1.125V5.375L4.875 5.875H0.625C0.45924 5.875 0.300269 5.94085 0.183058 6.05806C0.065848 6.17527 0 6.33424 0 6.5C0 6.66576 0.065848 6.82473 0.183058 6.94194C0.300269 7.05915 0.45924 7.125 0.625 7.125H4.762L5.375 7.625Z"
fill="black"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 931 B

After

Width:  |  Height:  |  Size: 930 B

View file

@ -1,4 +1,4 @@
<svg width="12" height="13" viewBox="0 0 12 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 0.5C5.21207 0.5 4.43185 0.655195 3.7039 0.956723C2.97595 1.25825 2.31451 1.70021 1.75736 2.25736C1.20021 2.81451 0.758251 3.47595 0.456723 4.2039C0.155195 4.93185 0 5.71207 0 6.5C0 7.28793 0.155195 8.06815 0.456723 8.7961C0.758251 9.52405 1.20021 10.1855 1.75736 10.7426C2.31451 11.2998 2.97595 11.7417 3.7039 12.0433C4.43185 12.3448 5.21207 12.5 6 12.5C7.5913 12.5 9.11742 11.8679 10.2426 10.7426C11.3679 9.61742 12 8.0913 12 6.5C12 4.9087 11.3679 3.38258 10.2426 2.25736C9.11742 1.13214 7.5913 0.5 6 0.5ZM5.06 8.9L2.9464 6.7856C2.85273 6.69171 2.80018 6.56446 2.80033 6.43183C2.80048 6.29921 2.85331 6.17207 2.9472 6.0784C3.04109 5.98473 3.16834 5.93218 3.30097 5.93233C3.43359 5.93248 3.56073 5.98531 3.6544 6.0792L5.3112 7.7368L8.3464 4.7008C8.44109 4.6109 8.56715 4.56153 8.69771 4.56322C8.82827 4.56492 8.95301 4.61754 9.04534 4.70986C9.13766 4.80219 9.19028 4.92693 9.19198 5.05749C9.19367 5.18805 9.1443 5.31411 9.0544 5.4088L5.5624 8.9H5.06Z"
fill="#FBFBFE"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -54,9 +54,9 @@ cursor_hand_tool_label=توڵامرازی دەستی
scroll_vertical.title=ناردنی ئەستوونی بەکاربێنە
scroll_vertical_label=ناردنی ئەستوونی
scroll_horizontal.title=ناردنی ئاسۆیی بەکاربێنە
scroll_horizontal_label=ناردنی ئاسۆیی
scroll_horizontal_label=ناردنی ئاسۆیی
scroll_wrapped.title=ناردنی لوولکراو بەکاربێنە
scroll_wrapped_label=ناردنی لوولکراو
scroll_wrapped_label=ناردنی لوولکراو
# Document properties dialog box
document_properties.title=تایبەتمەندییەکانی بەڵگەنامە...
document_properties_label=تایبەتمەندییەکانی بەڵگەنامە...

View file

@ -168,7 +168,7 @@ find_next_label=Upeigua
find_highlight=Embojekuaavepa
find_match_case_label=Ejesareko taiguasu/taimichĩre
find_match_diacritics_label=Diacrítico moñondive
find_entire_word_label=Ñeẽ oĩmbáva
find_entire_word_label=Ñeẽ oĩmbáva
find_reached_top=Ojehupyty kuatia ñepyrũ, okuejeýta kuatia paha guive
find_reached_bottom=Ojehupyty kuatia paha, okuejeýta kuatia ñepyrũ guive
# LOCALIZATION NOTE (find_match_count): The supported plural forms are

View file

@ -25,7 +25,7 @@ of_pages=nu {{pagesCount}}
# will be replaced by a number representing the currently visible page,
# respectively a number representing the total number of pages in the document.
page_of_pages=({{pageNumber}} nu {{pagesCount}})
zoom_out.title=Attuolynuot
zoom_out.title=Attuolynuot
zoom_out_label=Attuolynuot
zoom_in.title=Pītuvynuot
zoom_in_label=Pītuvynuot

View file

@ -204,7 +204,7 @@ page_scale_percent={{scale}}%
# Loading indicator messages
loading_error=Er is een fout opgetreden bij het laden van de PDF.
invalid_file_error=Ongeldig of beschadigd PDF-bestand.
missing_file_error=PDF-bestand ontbreekt.
missing_file_error=PDF-bestand ontbreekt.
unexpected_response_error=Onverwacht serverantwoord.
rendering_error=Er is een fout opgetreden bij het weergeven van de pagina.
# LOCALIZATION NOTE (annotation_date_string): "{{date}}" and "{{time}}" will be

View file

@ -35,7 +35,7 @@ presentation_mode_label=پریزنٹیشن موڈ
open_file.title=فائل کھولو
open_file_label=کھولو
print.title=چھاپو
print_label=چھاپو
print_label=چھاپو
save.title=ہتھیکڑا کرو
save_label=ہتھیکڑا کرو
# LOCALIZATION NOTE (download_button.title): used in Firefox for Android as a tooltip for the download button (“download” is a verb).

View file

@ -129,7 +129,7 @@ findbar_label=Narì'
find_input.title=Narì'
find_previous_label=Sa gachîn
find_next_label=Ne' ñaan
find_highlight=Daran' sa ña'an
find_highlight=Daran' sa ña'an
find_match_case_label=Match case
# LOCALIZATION NOTE (find_match_count): The supported plural forms are
# [one|two|few|many|other], with [other] as the default value.

View file

@ -26,7 +26,7 @@ however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply to
any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
@ -83,11 +83,11 @@ Software, subject to the following conditions:
Software.
TERMINATION
This license becomes null and void if any of the above conditions are not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,

View file

@ -11,7 +11,7 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
</div>
</div>
</div>

View file

@ -28,12 +28,12 @@
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'usernameExists'}" class="alert alert-danger">
<span th:text="#{usernameExistsMessage}">Default message if not found</span>
</div>
<!-- At the top of the user settings -->
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
@ -55,7 +55,7 @@
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
</div>
</form>
<hr> <!-- Separator Line -->
<!-- Change Password Form -->
@ -79,16 +79,16 @@
</form>
<hr>
<div class="card">
<div class="card-header" th:text="#{account.yourApiKey}">
</div>
<div class="card-body">
<div class="input-group mb-3">
<input type="password" class="form-control" id="apiKey" th:placeholder="#{account.yourApiKey}" readonly>
<div class="input-group-append">
<button class="btn btn-outline-secondary" id="copyBtn" type="button" onclick="copyToClipboard()">
<button class="btn btn-outline-secondary" id="copyBtn" type="button" onclick="copyToClipboard()">
<img class="blackwhite-icon" src="images/clipboard.svg" alt="Copy" style="height:20px;">
</button>
<button class="btn btn-outline-secondary" id="showBtn" type="button" onclick="showApiKey()">
@ -97,13 +97,13 @@
<button class="btn btn-outline-secondary" id="refreshBtn" type="button" onclick="refreshApiKey()">
<img class="blackwhite-icon" id="eyeIcon" src="images/arrow-clockwise.svg" alt="Refresh API-Key" style="height:20px;">
</button>
</div>
</div>
</div>
</div>
<script>
function copyToClipboard() {
const apiKeyElement = document.getElementById("apiKey");
@ -111,7 +111,7 @@
document.execCommand("copy");
}
function showApiKey() {
const apiKeyElement = document.getElementById("apiKey");
const copyBtn = document.getElementById("copyBtn");
@ -156,7 +156,7 @@
console.error('There was an error:', error);
}
}
function manageUIState(apiKey) {
const apiKeyElement = document.getElementById("apiKey");
const showBtn = document.getElementById("showBtn");
@ -165,7 +165,7 @@
if (apiKey && apiKey.trim().length > 0) {
apiKeyElement.value = apiKey;
showBtn.disabled = false;
copyBtn.disabled = true;
copyBtn.disabled = true;
} else {
apiKeyElement.value = "";
showBtn.disabled = true;
@ -173,10 +173,10 @@
}
}
document.addEventListener("DOMContentLoaded", function() {
const form = document.querySelector('form[action="api/v1/user/change-password"]');
form.addEventListener('submit', function(event) {
const newPassword = document.getElementById('newPassword').value;
const confirmNewPassword = document.getElementById('confirmNewPassword').value;
@ -188,10 +188,10 @@
});
});
</script>
<hr> <!-- Separator Line -->
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
<div class="container mt-4">
<h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3>
@ -226,10 +226,10 @@
text-align: center;
}
</style>
<script th:inline="javascript">
document.addEventListener("DOMContentLoaded", function() {
@ -299,12 +299,12 @@
</script>
<div class="mb-3 mt-4">
<a href="logout">
<button type="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</button>

View file

@ -12,13 +12,13 @@
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<!-- User Settings Title -->
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>
<table class="table">
<thead>
<tr>
@ -40,7 +40,7 @@
</tbody>
</table>
<h2 th:text="#{adminUserSettings.addUser}">Add New User</h2>
<div th:if="${param.messageType != null and param.messageType.size() > 0 and param.messageType[0] == 'usernameExists'}" class="alert alert-danger">
@ -69,7 +69,7 @@
<input type="checkbox" class="form-check-input" id="forceChange" name="forceChange">
<label class="form-check-label" for="forceChange" th:text="#{adminUserSettings.forceChange}">Force user to change username/password on login</label>
</div>
<!-- Add other fields as required -->
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
</form>

View file

@ -26,7 +26,7 @@
<p th:text="#{autoSplitPDF.formPrompt}"></p>
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="duplexMode" id="duplexMode">
<input type="checkbox" class="form-check-input" name="duplexMode" id="duplexMode">
<label class="ms-3" for="duplexMode" th:text=#{autoSplitPDF.duplexMode}></label>
</div>
<p><a th:href="@{files/Auto Splitter Divider (minimal).pdf}" download th:text="#{autoSplitPDF.dividerDownload1}"></a></p>

View file

@ -33,7 +33,7 @@
<!-- At the top of the user settings -->
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
<!-- Change Username Form -->
<h4></h4>
<h4 th:text="#{changeCreds.changeUserAndPassword}">Change Username and password</h4>
@ -58,11 +58,11 @@
<button type="submit" class="btn btn-primary" th:text="#{changeCreds.submit}">Change credentials!</button>
</div>
</form>
<script>
document.addEventListener("DOMContentLoaded", function() {
const form = document.querySelector('form[action="api/v1/user/change-username-and-password"]');
form.addEventListener('submit', function(event) {
const newPassword = document.getElementById('newPassword').value;
const confirmNewPassword = document.getElementById('confirmNewPassword').value;

View file

@ -1,30 +1,29 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{BookToPDF.title}, header=#{BookToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{BookToPDF.header}"></h2>
<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>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{BookToPDF.help}"></p>
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{BookToPDF.title}, header=#{BookToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{BookToPDF.header}"></h2>
<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>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{BookToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{BookToPDF.help}"></p>
<p class="mt-3" th:text="#{BookToPDF.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View file

@ -25,7 +25,7 @@
<p class="mt-3" th:text="#{fileToPDF.supportedFileTypes}"></p>
<p th:utext="#{fileToPDF.fileTypesList}"></p>
<a href="https://help.libreoffice.org/latest/en-US/text/shared/guide/supported_formats.html">https://help.libreoffice.org/latest/en-US/text/shared/guide/supported_formats.html</a>
</div>
</div>
</div>

View file

@ -1,36 +1,36 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{HTMLToPDF.title}, header=#{HTMLToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="mb-3">
<h2 th:text="#{HTMLToPDF.header}"></h2>
<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 class="mb-3">
<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" />
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{HTMLToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{HTMLToPDF.help}"></p>
<p class="mt-3" th:text="#{HTMLToPDF.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{HTMLToPDF.title}, header=#{HTMLToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="mb-3">
<h2 th:text="#{HTMLToPDF.header}"></h2>
<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 class="mb-3">
<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" />
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{HTMLToPDF.submit}"></button>
</form>
<p class="mt-3" th:text="#{HTMLToPDF.help}"></p>
<p class="mt-3" th:text="#{HTMLToPDF.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View file

@ -1,92 +1,88 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title}, header=#{imageToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{imageToPDF.header}"></h2>
<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 class="mb-3">
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
<select class="form-control" id="fitOption" name="fitOption">
<option value="fillPage" th:text="#{imageToPDF.fillPage}">Fill Page</option>
<option value="fitDocumentToImage" th:text="#{imageToPDF.fitDocumentToImage}">Fit Document to Image</option>
<option value="maintainAspectRatio" th:text="#{imageToPDF.maintainAspectRatio}">Maintain Aspect Ratio</option>
</select>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="autoRotate" id="autoRotate">
<label class="ms-3" for="autoRotate" th:text=#{imageToPDF.selectText.2}></label>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.colorType}"></label>
<select class="form-control" id="colorType" name="colorType">
<option value="color" th:text="#{pdfToImage.color}"></option>
<option value="greyscale" th:text="#{pdfToImage.grey}"></option>
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select>
</div>
<br>
<input type="hidden" id="override" name="override" value="multi">
<div class="mb-3">
<label th:text=#{imageToPDF.selectText.3}></label>
<select class="form-control" id="conversionType" name="conversionType" disabled>
<option value="merge" th:text=#{imageToPDF.selectText.4}></option>
<option value="convert" th:text=#{imageToPDF.selectText.5} selected></option>
</select>
</div>
<br> <br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{imageToPDF.submit}"></button>
<script>
$('#fileInput-input').on('change', function() {
var files = document.getElementById("fileInput-input").files;
var conversionType = document.getElementById("conversionType");
console.log("files.length=" + files.length)
if (files.length > 1) {
conversionType.disabled = false;
} else {
conversionType.disabled = true;
}
});
$('#conversionType').change(function() {
var selectedValue = $(this).val();
var override = document.getElementById("override");
console.log("selectedValue=" + selectedValue)
if (selectedValue === 'merge') {
override.value = "single";
} else if (selectedValue === 'convert') {
override.value = "multi";
}
});
</script>
</form>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{imageToPDF.title}, header=#{imageToPDF.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{imageToPDF.header}"></h2>
<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 class="mb-3">
<label for="fitOption" th:text="#{imageToPDF.selectLabel}">Fit Options</label>
<select class="form-control" id="fitOption" name="fitOption">
<option value="fillPage" th:text="#{imageToPDF.fillPage}">Fill Page</option>
<option value="fitDocumentToImage" th:text="#{imageToPDF.fitDocumentToImage}">Fit Document to Image</option>
<option value="maintainAspectRatio" th:text="#{imageToPDF.maintainAspectRatio}">Maintain Aspect Ratio</option>
</select>
</div>
<div class="form-check">
<input type="checkbox" class="form-check-input" name="autoRotate" id="autoRotate">
<label class="ms-3" for="autoRotate" th:text=#{imageToPDF.selectText.2}></label>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.colorType}"></label>
<select class="form-control" id="colorType" name="colorType">
<option value="color" th:text="#{pdfToImage.color}"></option>
<option value="greyscale" th:text="#{pdfToImage.grey}"></option>
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select>
</div>
<br>
<input type="hidden" id="override" name="override" value="multi">
<div class="mb-3">
<label th:text=#{imageToPDF.selectText.3}></label>
<select class="form-control" id="conversionType" name="conversionType" disabled>
<option value="merge" th:text=#{imageToPDF.selectText.4}></option>
<option value="convert" th:text=#{imageToPDF.selectText.5} selected></option>
</select>
</div>
<br> <br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{imageToPDF.submit}"></button>
<script>
$('#fileInput-input').on('change', function() {
var files = document.getElementById("fileInput-input").files;
var conversionType = document.getElementById("conversionType");
console.log("files.length=" + files.length)
if (files.length > 1) {
conversionType.disabled = false;
} else {
conversionType.disabled = true;
}
});
$('#conversionType').change(function() {
var selectedValue = $(this).val();
var override = document.getElementById("override");
console.log("selectedValue=" + selectedValue)
if (selectedValue === 'merge') {
override.value = "single";
} else if (selectedValue === 'convert') {
override.value = "multi";
}
});
</script>
</form>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View file

@ -1,29 +1,29 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{PDFToHTML.title}, header=#{PDFToHTML.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{PDFToHTML.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/html}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToHTML.submit}"></button>
</form>
<p class="mt-3" th:text="#{PDFToHTML.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{PDFToHTML.title}, header=#{PDFToHTML.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{PDFToHTML.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/html}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToHTML.submit}"></button>
</form>
<p class="mt-3" th:text="#{PDFToHTML.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View file

@ -1,61 +1,61 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{pdfToImage.title}, header=#{pdfToImage.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{pdfToImage.header}"></h2>
<p th:text="#{processTimeWarning}"></p>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/img}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{pdfToImage.selectText}"></label>
<select class="form-control" name="imageFormat">
<option value="png">PNG</option>
<option value="jpg">JPG</option>
<option value="gif">GIF</option>
<option value="tiff">TIFF</option>
<option value="bmp">BMP</option>
</select>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.singleOrMultiple}"></label>
<select class="form-control" name="singleOrMultiple">
<option value="multiple" th:text="#{pdfToImage.multi}"></option>
<option value="single" th:text="#{pdfToImage.single}"></option>
</select>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.colorType}"></label>
<select class="form-control" name="colorType">
<option value="color" th:text="#{pdfToImage.color}"></option>
<option value="greyscale" th:text="#{pdfToImage.grey}"></option>
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select>
</div>
<div class="mb-3">
<label for="dpi">DPI:</label>
<input type="number" name="dpi" class="form-control" id="dpi" min="1" step="1" value="300" required>
</div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfToImage.submit}"></button>
</form>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{pdfToImage.title}, header=#{pdfToImage.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{pdfToImage.header}"></h2>
<p th:text="#{processTimeWarning}"></p>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/img}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{pdfToImage.selectText}"></label>
<select class="form-control" name="imageFormat">
<option value="png">PNG</option>
<option value="jpg">JPG</option>
<option value="gif">GIF</option>
<option value="tiff">TIFF</option>
<option value="bmp">BMP</option>
</select>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.singleOrMultiple}"></label>
<select class="form-control" name="singleOrMultiple">
<option value="multiple" th:text="#{pdfToImage.multi}"></option>
<option value="single" th:text="#{pdfToImage.single}"></option>
</select>
</div>
<div class="mb-3">
<label th:text="#{pdfToImage.colorType}"></label>
<select class="form-control" name="colorType">
<option value="color" th:text="#{pdfToImage.color}"></option>
<option value="greyscale" th:text="#{pdfToImage.grey}"></option>
<option value="blackwhite" th:text="#{pdfToImage.blackwhite}"></option>
</select>
</div>
<div class="mb-3">
<label for="dpi">DPI:</label>
<input type="number" name="dpi" class="form-control" id="dpi" min="1" step="1" value="300" required>
</div>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{pdfToImage.submit}"></button>
</form>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
</body>
</html>

View file

@ -14,9 +14,9 @@
<h2 th:text="#{PDFToPresentation.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/presentation}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToPresentation.selectText.1}"></label>
<label th:text="#{PDFToPresentation.selectText.1}"></label>
<select class="form-control" name="outputFormat">
<option value="ppt">PPT</option>
<option value="pptx">PPTX</option>

View file

@ -1,35 +1,35 @@
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{PDFToText.title}, header=#{PDFToText.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{PDFToText.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/text}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToText.selectText.1}"></label>
<select class="form-control" name="outputFormat">
<option value="rtf">RTF</option>
<option value="txt">TXT</option>
</select>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
</form>
<p class="mt-3" th:text="#{PDFToText.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>
<!DOCTYPE html>
<html th:lang="${#locale.toString()}" th:lang-direction="#{language.direction}" xmlns:th="http://www.thymeleaf.org">
<th:block th:insert="~{fragments/common :: head(title=#{PDFToText.title}, header=#{PDFToText.header})}"></th:block>
<body>
<th:block th:insert="~{fragments/common :: game}"></th:block>
<div id="page-container">
<div id="content-wrap">
<div th:insert="~{fragments/navbar.html :: navbar}"></div>
<br> <br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6">
<h2 th:text="#{PDFToText.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/text}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToText.selectText.1}"></label>
<select class="form-control" name="outputFormat">
<option value="rtf">RTF</option>
<option value="txt">TXT</option>
</select>
</div>
<br>
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
</form>
<p class="mt-3" th:text="#{PDFToText.credit}"></p>
</div>
</div>
</div>
</div>
<div th:insert="~{fragments/footer.html :: footer}"></div>
</div>

View file

@ -14,9 +14,9 @@
<h2 th:text="#{PDFToWord.header}"></h2>
<form method="post" enctype="multipart/form-data" th:action="@{api/v1/convert/pdf/word}">
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf')}"></div>
<div class="mb-3">
<label th:text="#{PDFToWord.selectText.1}"></label>
<label th:text="#{PDFToWord.selectText.1}"></label>
<select class="form-control" name="outputFormat">
<option value="doc">Doc</option>
<option value="docx">DocX</option>

Some files were not shown because too many files have changed in this diff Show more