Merge branch 'main' into pipelineFixes

This commit is contained in:
Anthony Stirling 2024-01-28 17:41:17 +00:00 committed by GitHub
commit 0fbc461877
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 240 additions and 161 deletions

View file

@ -115,4 +115,4 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
return false; return false;
} }
} }

View file

@ -33,7 +33,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest; import stirling.software.SPDF.model.api.misc.RemoveBlankPagesRequest;
import stirling.software.SPDF.utils.PdfUtils; import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.ProcessExecutor; import stirling.software.SPDF.utils.ProcessExecutor;
import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult;
import stirling.software.SPDF.utils.WebResponseUtils; import stirling.software.SPDF.utils.WebResponseUtils;
@RestController @RestController
@ -85,7 +84,7 @@ public class BlankPageController {
List<String> command = List<String> command =
new ArrayList<>( new ArrayList<>(
Arrays.asList( Arrays.asList(
"python3", "python",
System.getProperty("user.dir") System.getProperty("user.dir")
+ "/scripts/detect-blank-pages.py", + "/scripts/detect-blank-pages.py",
tempFile.toString(), tempFile.toString(),
@ -94,18 +93,25 @@ public class BlankPageController {
"--white_percent", "--white_percent",
String.valueOf(whitePercent))); String.valueOf(whitePercent)));
Boolean blank = false;
// Run CLI command // Run CLI command
ProcessExecutorResult returnCode = try {
ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV) ProcessExecutor.getInstance(ProcessExecutor.Processes.PYTHON_OPENCV)
.runCommandWithOutputHandling(command); .runCommandWithOutputHandling(command);
} catch (IOException e) {
// From detect-blank-pages.py
// Return code 1: The image is considered blank.
// Return code 0: The image is not considered blank.
// Since the process returned with a failure code, it should be blank.
blank = true;
}
// does contain data if (blank) {
if (returnCode.getRc() == 0) { System.out.println("Skipping, Image was blank for page #" + pageIndex);
} else {
System.out.println( System.out.println(
"page " + pageIndex + " has image which is not blank"); "page " + pageIndex + " has image which is not blank");
pagesToKeepIndex.add(pageIndex); pagesToKeepIndex.add(pageIndex);
} else {
System.out.println("Skipping, Image was blank for page #" + pageIndex);
} }
} }
} }

View file

@ -1,4 +1,4 @@
########### ###########
# Generic # # Generic #
########### ###########
# the direction that the language is written (ltr=left to right, rtl = right to left) # the direction that the language is written (ltr=left to right, rtl = right to left)
@ -342,22 +342,22 @@ HTMLToPDF.tags=markup,web-content,transformation,convert
home.MarkdownToPDF.title=Markdown zu PDF home.MarkdownToPDF.title=Markdown zu PDF
home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF
MarkdownToPDF.tags=markup,web-content,transformation,convert MarkdownToPDF.tags=markup,web-content,transformation,konvertieren
home.getPdfInfo.title=Alle Informationen anzeigen home.getPdfInfo.title=Alle Informationen anzeigen
home.getPdfInfo.desc=Erfasst alle möglichen Informationen in einer PDF home.getPdfInfo.desc=Erfasst alle möglichen Informationen in einer PDF
getPdfInfo.tags=infomation,data,stats,statistics getPdfInfo.tags=infomation,daten,statistik
home.extractPage.title=Seite(n) extrahieren home.extractPage.title=Seite(n) extrahieren
home.extractPage.desc=Extrahiert ausgewählte Seiten aus einer PDF home.extractPage.desc=Extrahiert ausgewählte Seiten aus einer PDF
extractPage.tags=extract extractPage.tags=extrahieren
home.PdfToSinglePage.title=PDF zu einer Seite zusammenfassen home.PdfToSinglePage.title=PDF zu einer Seite zusammenfassen
home.PdfToSinglePage.desc=Fügt alle PDF-Seiten zu einer einzigen großen Seite zusammen home.PdfToSinglePage.desc=Fügt alle PDF-Seiten zu einer einzigen großen Seite zusammen
PdfToSinglePage.tags=single page PdfToSinglePage.tags=einzelseite
home.showJS.title=Javascript anzeigen home.showJS.title=Javascript anzeigen
@ -365,26 +365,26 @@ home.showJS.desc=Alle Javascript Funktionen in einer PDF anzeigen
showJS.tags=JS showJS.tags=JS
home.autoRedact.title=Automatisch zensieren/schwärzen home.autoRedact.title=Automatisch zensieren/schwärzen
home.autoRedact.desc=Automatisches zensierten (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text home.autoRedact.desc=Automatisches Zensieren (Schwärzen) von Text in einer PDF-Datei basierend auf dem eingegebenen Text
showJS.tags=JS showJS.tags=zensieren,schwärzen
home.tableExtraxt.title=Tabelle extrahieren home.tableExtraxt.title=Tabelle extrahieren
home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren home.tableExtraxt.desc=Tabelle aus PDF in CSV extrahieren
tableExtraxt.tags=CSV tableExtraxt.tags=CSV
home.autoSizeSplitPDF.title=Auto Split by Size/Count home.autoSizeSplitPDF.title=Teilen nach Größe/Anzahl
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count home.autoSizeSplitPDF.desc=Teilen Sie ein einzelnes PDF basierend auf Größe, Seitenanzahl oder Dokumentanzahl in mehrere Dokumente auf
autoSizeSplitPDF.tags=pdf,split,document,organization autoSizeSplitPDF.tags=pdf,teilen,dokument,organisation
home.overlay-pdfs.title=Overlay PDFs home.overlay-pdfs.title=PDF mit Overlay versehen
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF home.overlay-pdfs.desc=Überlagert eine PDF über eine andere PDF
overlay-pdfs.tags=Overlay overlay-pdfs.tags=overlay,überlagern
home.split-by-sections.title=Split PDF by Sections home.split-by-sections.title=PDF in Abschnitte teilen
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections home.split-by-sections.desc=Teilen Sie jede Seite einer PDF-Datei in kleinere horizontale und vertikale Abschnitte auf
split-by-sections.tags=Section Split, Divide, Customize split-by-sections.tags=abschnitte,teilen,bearbeiten
home.AddStampRequest.title=Add Stamp to PDF home.AddStampRequest.title=Add Stamp to PDF
home.AddStampRequest.desc=Add text or add image stamps at set locations home.AddStampRequest.desc=Add text or add image stamps at set locations
@ -415,7 +415,7 @@ autoRedact.useRegexLabel=Regex verwenden
autoRedact.wholeWordSearchLabel=Ganzes Wort suchen autoRedact.wholeWordSearchLabel=Ganzes Wort suchen
autoRedact.customPaddingLabel=Benutzerdefinierte Extra-Padding autoRedact.customPaddingLabel=Benutzerdefinierte Extra-Padding
autoRedact.convertPDFToImageLabel=PDF in PDF-Bild konvertieren (zum Entfernen von Text hinter dem Kasten) autoRedact.convertPDFToImageLabel=PDF in PDF-Bild konvertieren (zum Entfernen von Text hinter dem Kasten)
autoRedact.submitButton=zensieren autoRedact.submitButton=Zensieren
#showJS #showJS
@ -609,9 +609,9 @@ removeBlanks.submit=Leere Seiten entfernen
#removeAnnotations #removeAnnotations
removeAnnotations.title=Remove Annotations removeAnnotations.title=Kommentare entfernen
removeAnnotations.header=Remove Annotations removeAnnotations.header=Kommentare entfernen
removeAnnotations.submit=Remove removeAnnotations.submit=Entfernen
#compare #compare
@ -628,7 +628,7 @@ sign.header=PDFs signieren
sign.upload=Bild hochladen sign.upload=Bild hochladen
sign.draw=Signatur zeichnen sign.draw=Signatur zeichnen
sign.text=Texteingabe sign.text=Texteingabe
sign.clear=Klar sign.clear=Leeren
sign.add=Signieren sign.add=Signieren
@ -920,44 +920,44 @@ PDFToXML.submit=Konvertieren
#PDFToCSV #PDFToCSV
PDFToCSV.title=PDF zu CSV PDFToCSV.title=PDF zu CSV
PDFToCSV.header=PDF zu CSV PDFToCSV.header=PDF zu CSV
PDFToCSV.prompt=Choose page to extract table PDFToCSV.prompt=Seite mit der zu extrahierenden Tabelle wählen
PDFToCSV.submit=Extrakt PDFToCSV.submit=Extrahieren
#split-by-size-or-count #split-by-size-or-count
split-by-size-or-count.header=Split PDF by Size or Count split-by-size-or-count.header=PDF nach Größe oder Anzahl teilen
split-by-size-or-count.type.label=Select Split Type split-by-size-or-count.type.label=Teil-Modus wählen
split-by-size-or-count.type.size=By Size split-by-size-or-count.type.size=Nach Größe
split-by-size-or-count.type.pageCount=By Page Count split-by-size-or-count.type.pageCount=Nach Anzahl Seiten
split-by-size-or-count.type.docCount=By Document Count split-by-size-or-count.type.docCount=Nach Anzahl Dokumenten
split-by-size-or-count.value.label=Enter Value split-by-size-or-count.value.label=Wert eingeben
split-by-size-or-count.value.placeholder=Enter size (e.g., 2MB or 3KB) or count (e.g., 5) split-by-size-or-count.value.placeholder=Größe eingeben (z. B.: 2MB oder 3KB) oder Anzahl (z. B.: 5)
split-by-size-or-count.submit=Submit split-by-size-or-count.submit=Erstellen
#overlay-pdfs #overlay-pdfs
overlay-pdfs.header=Overlay PDF Files overlay-pdfs.header=PDF mit Overlay versehen
overlay-pdfs.baseFile.label=Select Base PDF File overlay-pdfs.baseFile.label=Basis-PDF-Datei auswählen
overlay-pdfs.overlayFiles.label=Select Overlay PDF Files overlay-pdfs.overlayFiles.label=Overlay-PDF-Datei auswählen
overlay-pdfs.mode.label=Select Overlay Mode overlay-pdfs.mode.label=Overlay-Modus auswählen
overlay-pdfs.mode.sequential=Sequential Overlay overlay-pdfs.mode.sequential=Sequentielles Overlay
overlay-pdfs.mode.interleaved=Interleaved Overlay overlay-pdfs.mode.interleaved=Verschachteltes Overlay
overlay-pdfs.mode.fixedRepeat=Fixed Repeat Overlay overlay-pdfs.mode.fixedRepeat=Feste-Wiederholung Overlay
overlay-pdfs.counts.label=Overlay Counts (for Fixed Repeat Mode) overlay-pdfs.counts.label=Overlay Anzahl (für Feste-Wiederholung)
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1) overlay-pdfs.counts.placeholder=Komma-separierte Anzahl eingeben (z. B.: 2,3,1)
overlay-pdfs.position.label=Select Overlay Position overlay-pdfs.position.label=Overlay Position auswählen
overlay-pdfs.position.foreground=Foreground overlay-pdfs.position.foreground=Vordergrund
overlay-pdfs.position.background=Background overlay-pdfs.position.background=Hintergrund
overlay-pdfs.submit=Submit overlay-pdfs.submit=Erstellen
#split-by-sections #split-by-sections
split-by-sections.title=Split PDF by Sections split-by-sections.title=PDF in Abschnitte teilen
split-by-sections.header=Split PDF into Sections split-by-sections.header=PDF in Abschnitte teilen
split-by-sections.horizontal.label=Horizontal Divisions split-by-sections.horizontal.label=Horizontale Teiler
split-by-sections.vertical.label=Vertical Divisions split-by-sections.vertical.label=Vertikale Teiler
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions split-by-sections.horizontal.placeholder=Anzahl horizontaler Teiler eingeben
split-by-sections.vertical.placeholder=Enter number of vertical divisions split-by-sections.vertical.placeholder=Anzahl vertikaler Teiler eingeben
split-by-sections.submit=Split PDF split-by-sections.submit=PDF teilen
#licenses #licenses
@ -968,4 +968,3 @@ licenses.module=Module
licenses.version=Version licenses.version=Version
licenses.license=License licenses.license=License

View file

@ -357,22 +357,29 @@
{ {
"moduleName": "org.apache.pdfbox:fontbox", "moduleName": "org.apache.pdfbox:fontbox",
"moduleUrl": "https://pdfbox.apache.org", "moduleUrl": "https://pdfbox.apache.org",
"moduleVersion": "2.0.30", "moduleVersion": "3.0.1",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.apache.pdfbox:pdfbox", "moduleName": "org.apache.pdfbox:pdfbox",
"moduleUrl": "https://pdfbox.apache.org", "moduleUrl": "https://pdfbox.apache.org",
"moduleVersion": "2.0.30", "moduleVersion": "3.0.1",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "org.apache.pdfbox:pdfbox-io",
"moduleUrl": "https://pdfbox.apache.org",
"moduleVersion": "3.0.1",
"moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
"moduleName": "org.apache.pdfbox:xmpbox", "moduleName": "org.apache.pdfbox:xmpbox",
"moduleUrl": "https://pdfbox.apache.org", "moduleUrl": "https://pdfbox.apache.org",
"moduleVersion": "2.0.30", "moduleVersion": "3.0.1",
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "Apache-2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt" "moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
}, },
{ {
@ -450,6 +457,12 @@
"moduleLicense": "BSD 2-Clause License", "moduleLicense": "BSD 2-Clause License",
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause" "moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
}, },
{
"moduleName": "org.commonmark:commonmark-ext-gfm-tables",
"moduleVersion": "0.21.0",
"moduleLicense": "BSD 2-Clause License",
"moduleLicenseUrl": "https://opensource.org/licenses/BSD-2-Clause"
},
{ {
"moduleName": "org.eclipse.angus:angus-activation", "moduleName": "org.eclipse.angus:angus-activation",
"moduleUrl": "https://www.eclipse.org", "moduleUrl": "https://www.eclipse.org",
@ -506,6 +519,52 @@
"moduleLicense": "Public Domain", "moduleLicense": "Public Domain",
"moduleLicenseUrl": "http://repository.jboss.org/licenses/cc0-1.0.txt" "moduleLicenseUrl": "http://repository.jboss.org/licenses/cc0-1.0.txt"
}, },
{
"moduleName": "org.junit.jupiter:junit-jupiter",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "5.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit.jupiter:junit-jupiter-api",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "5.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit.jupiter:junit-jupiter-engine",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "5.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit.jupiter:junit-jupiter-params",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "5.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit.platform:junit-platform-commons",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "1.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit.platform:junit-platform-engine",
"moduleUrl": "https://junit.org/junit5/",
"moduleVersion": "1.10.1",
"moduleLicense": "Eclipse Public License v2.0",
"moduleLicenseUrl": "https://www.eclipse.org/legal/epl-v20.html"
},
{
"moduleName": "org.junit:junit-bom",
"moduleVersion": "5.10.1"
},
{ {
"moduleName": "org.latencyutils:LatencyUtils", "moduleName": "org.latencyutils:LatencyUtils",
"moduleUrl": "http://latencyutils.github.io/LatencyUtils/", "moduleUrl": "http://latencyutils.github.io/LatencyUtils/",
@ -513,6 +572,13 @@
"moduleLicense": "Public Domain, per Creative Commons CC0", "moduleLicense": "Public Domain, per Creative Commons CC0",
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/" "moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
}, },
{
"moduleName": "org.opentest4j:opentest4j",
"moduleUrl": "https://github.com/ota4j-team/opentest4j",
"moduleVersion": "1.3.0",
"moduleLicense": "The Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{ {
"moduleName": "org.slf4j:jul-to-slf4j", "moduleName": "org.slf4j:jul-to-slf4j",
"moduleUrl": "http://www.slf4j.org", "moduleUrl": "http://www.slf4j.org",

View file

@ -26,6 +26,7 @@ class PdfContainer {
movePageTo: this.movePageTo, movePageTo: this.movePageTo,
addPdfs: this.addPdfs, addPdfs: this.addPdfs,
rotateElement: this.rotateElement, rotateElement: this.rotateElement,
updateFilename: this.updateFilename
}) })
}) })
@ -38,7 +39,7 @@ class PdfContainer {
filenameInput.onkeyup = this.updateFilename; filenameInput.onkeyup = this.updateFilename;
filenameInput.onkeydown = this.preventIllegalChars; filenameInput.onkeydown = this.preventIllegalChars;
filenameInput.disabled = true; filenameInput.disabled = false;
filenameInput.innerText = ""; filenameInput.innerText = "";
downloadBtn.disabled = true; downloadBtn.disabled = true;
} }
@ -59,7 +60,7 @@ class PdfContainer {
const vector = (endIndex !== -1 && startIndex > endIndex) const vector = (endIndex !== -1 && startIndex > endIndex)
? 0-width ? 0-width
: width; : width;
this.pagesContainerWrapper.scroll({ this.pagesContainerWrapper.scroll({
left: this.pagesContainerWrapper.scrollLeft + vector, left: this.pagesContainerWrapper.scrollLeft + vector,
}) })
@ -73,30 +74,9 @@ class PdfContainer {
input.setAttribute("accept", "application/pdf"); input.setAttribute("accept", "application/pdf");
input.onchange = async(e) => { input.onchange = async(e) => {
const files = e.target.files; const files = e.target.files;
if (files.length > 0) {
const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button');
filenameInput.disabled = false;
if (pagesContainer.childElementCount === 0) {
filenameInput.value = "";
this.filename = null;
downloadBtn.disabled = true;
} else {
this.filename = filenameInput.value;
}
if (this.filename === null || this.filename === undefined) {
filenameInput.value = files[0].name;
} else {
filenameInput.value = this.filename;
}
}
this.addPdfsFromFiles(files, nextSiblingElement); this.addPdfsFromFiles(files, nextSiblingElement);
this.updateFilename(files ? files[0].name : "");
} }
input.click(); input.click();
@ -197,7 +177,7 @@ class PdfContainer {
return pdfDoc; return pdfDoc;
} }
rotateAll(deg) { rotateAll(deg) {
for (var i=0; i<this.pagesContainer.childNodes.length; i++) { for (var i=0; i<this.pagesContainer.childNodes.length; i++) {
@ -215,13 +195,13 @@ class PdfContainer {
if (!img) continue; if (!img) continue;
const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx]) const pages = await pdfDoc.copyPages(img.doc, [img.pageIdx])
const page = pages[0]; const page = pages[0];
const rotation = img.style.rotate; const rotation = img.style.rotate;
if (rotation) { if (rotation) {
const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, '')); const rotationAngle = parseInt(rotation.replace(/[^\d-]/g, ''));
page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle)) page.setRotation(PDFLib.degrees(page.getRotation().angle + rotationAngle))
} }
pdfDoc.addPage(page); pdfDoc.addPage(page);
} }
const pdfBytes = await pdfDoc.save(); const pdfBytes = await pdfDoc.save();
@ -242,12 +222,12 @@ class PdfContainer {
} }
filenameInput.value = inputArr.join(''); filenameInput.value = inputArr.join('');
this.filename = filenameInput.value; this.fileName = filenameInput.value;
} }
if (!filenameInput.value.includes('.pdf')) { if (!filenameInput.value.includes('.pdf')) {
filenameInput.value = filenameInput.value + '.pdf'; filenameInput.value = filenameInput.value + '.pdf';
this.filename = filenameInput.value; this.fileName = filenameInput.value;
} }
if (downloadOption === 'sameWindow') { if (downloadOption === 'sameWindow') {
@ -263,7 +243,7 @@ class PdfContainer {
this.downloadLink.href = url; this.downloadLink.href = url;
// downloadLink.download = this.fileName ? this.fileName : 'managed.pdf'; // downloadLink.download = this.fileName ? this.fileName : 'managed.pdf';
// downloadLink.download = this.fileName; // downloadLink.download = this.fileName;
this.downloadLink.setAttribute('download', this.filename ? this.fileName : 'managed.pdf'); this.downloadLink.setAttribute('download', this.fileName ? this.fileName : 'managed.pdf');
this.downloadLink.setAttribute('target', '_blank'); this.downloadLink.setAttribute('target', '_blank');
this.downloadLink.onclick = this.setDownloadAttribute; this.downloadLink.onclick = this.setDownloadAttribute;
this.downloadLink.click(); this.downloadLink.click();
@ -271,20 +251,23 @@ class PdfContainer {
} }
setDownloadAttribute() { setDownloadAttribute() {
this.downloadLink.setAttribute("download", this.filename ? this.filename : 'managed.pdf'); this.downloadLink.setAttribute("download", this.fileName ? this.fileName : 'managed.pdf');
} }
updateFilename() { updateFilename(fileName = "") {
const filenameInput = document.getElementById('filename-input'); const filenameInput = document.getElementById('filename-input');
const pagesContainer = document.getElementById('pages-container');
const downloadBtn = document.getElementById('export-button'); const downloadBtn = document.getElementById('export-button');
if (filenameInput.value === "") { downloadBtn.disabled = pagesContainer.childElementCount === 0
downloadBtn.disabled = true;
return; if (!this.fileName) {
this.fileName = fileName;
} }
downloadBtn.disabled = false; if (!filenameInput.value) {
this.filename = filenameInput.value; filenameInput.value = this.fileName;
}
} }
preventIllegalChars(e) { preventIllegalChars(e) {

View file

@ -1,69 +1,94 @@
const addFileDragListener = (callback) => { class FileDragManager {
let overlay; overlay;
let dragCounter = 0; dragCounter;
updateFilename;
const dragenterListener = function() { constructor(cb = null) {
dragCounter++; this.dragCounter = 0;
if (!overlay) { this.setCallback(cb);
// Prevent default behavior for drag events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
this.dragenterListener = this.dragenterListener.bind(this);
this.dragleaveListener = this.dragleaveListener.bind(this);
this.dropListener = this.dropListener.bind(this);
document.body.addEventListener('dragenter', this.dragenterListener);
document.body.addEventListener('dragleave', this.dragleaveListener);
// Add drop event listener
document.body.addEventListener('drop', this.dropListener);
}
setActions({ updateFilename }) {
this.updateFilename = updateFilename;
}
setCallback(cb) {
if (cb) {
this.callback = cb;
} else {
this.callback = (files) => console.warn("FileDragManager not set");
}
}
dragenterListener() {
this.dragCounter++;
if (!this.overlay) {
// Create and show the overlay // Create and show the overlay
overlay = document.createElement('div'); this.overlay = document.createElement('div');
overlay.style.position = 'fixed'; this.overlay.style.position = 'fixed';
overlay.style.top = 0; this.overlay.style.top = 0;
overlay.style.left = 0; this.overlay.style.left = 0;
overlay.style.width = '100%'; this.overlay.style.width = '100%';
overlay.style.height = '100%'; this.overlay.style.height = '100%';
overlay.style.background = 'rgba(0, 0, 0, 0.5)'; this.overlay.style.background = 'rgba(0, 0, 0, 0.5)';
overlay.style.color = '#fff'; this.overlay.style.color = '#fff';
overlay.style.zIndex = '1000'; this.overlay.style.zIndex = '1000';
overlay.style.display = 'flex'; this.overlay.style.display = 'flex';
overlay.style.alignItems = 'center'; this.overlay.style.alignItems = 'center';
overlay.style.justifyContent = 'center'; this.overlay.style.justifyContent = 'center';
overlay.style.pointerEvents = 'none'; this.overlay.style.pointerEvents = 'none';
overlay.innerHTML = '<p>Drop files anywhere to upload</p>'; this.overlay.innerHTML = '<p>Drop files anywhere to upload</p>';
document.getElementById('content-wrap').appendChild(overlay); document.getElementById('content-wrap').appendChild(this.overlay);
} }
}; };
const dragleaveListener = function() { dragleaveListener() {
dragCounter--; this.dragCounter--;
if (dragCounter === 0) { if (this.dragCounter === 0) {
// Hide and remove the overlay // Hide and remove the overlay
if (overlay) { if (this.overlay) {
overlay.remove(); this.overlay.remove();
overlay = null; this.overlay = null;
} }
} }
}; };
const dropListener = function(e) { dropListener(e) {
const dt = e.dataTransfer; const dt = e.dataTransfer;
const files = dt.files; const files = dt.files;
callback(files).catch((err) => { this.callback(files).catch((err) => {
console.error(err); console.error(err);
//maybe //maybe
}).finally(() => { }).finally(() => {
if (overlay) { // Hide and remove the overlay
overlay.remove(); if (this.overlay) {
overlay = null; this.overlay.remove();
this.overlay = null;
} }
this.updateFilename(files ? files[0].name : "");
}); });
}; };
// Prevent default behavior for drag events
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
document.body.addEventListener(eventName, preventDefaults, false);
});
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
document.body.addEventListener('dragenter', dragenterListener);
document.body.addEventListener('dragleave', dragleaveListener);
// Add drop event listener
document.body.addEventListener('drop', dropListener);
} }
export default addFileDragListener; export default FileDragManager;

View file

@ -49,7 +49,7 @@
<path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" /> <path d="M8 4.466V.534a.25.25 0 0 0-.41-.192L5.23 2.308a.25.25 0 0 0 0 .384l2.36 1.966A.25.25 0 0 0 8 4.466z" />
</svg> </svg>
</button> </button>
<button class="btn btn-secondary enable-on-file" onclick="rotateAll(90)" disabled> <button class="btn btn-secondary enable-on-file" onclick="rotateAll(90)" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" /> <path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z" />
@ -79,13 +79,14 @@
import scrollDivHorizontally from "./js/multitool/horizontalScroll.js"; import scrollDivHorizontally from "./js/multitool/horizontalScroll.js";
import ImageHighlighter from "./js/multitool/ImageHighlighter.js"; import ImageHighlighter from "./js/multitool/ImageHighlighter.js";
import PdfActionsManager from './js/multitool/PdfActionsManager.js'; import PdfActionsManager from './js/multitool/PdfActionsManager.js';
import addFileInputListener from './js/multitool/fileInput.js'; import FileDragManager from './js/multitool/fileInput.js';
// enables drag and drop // enables drag and drop
const dragDropManager = new DragDropManager('drag-container', 'pages-container'); const dragDropManager = new DragDropManager('drag-container', 'pages-container');
// enables image highlight on click // enables image highlight on click
const imageHighlighter = new ImageHighlighter('image-highlighter'); const imageHighlighter = new ImageHighlighter('image-highlighter');
// enables the default action buttons on each pdf // enables the default action buttons on each pdf
const pdfActionsManager = new PdfActionsManager('pages-container'); const pdfActionsManager = new PdfActionsManager('pages-container');
const fileDragManager = new FileDragManager();
// Scroll the wrapper horizontally // Scroll the wrapper horizontally
scrollDivHorizontally('pages-container-wrapper'); scrollDivHorizontally('pages-container-wrapper');
@ -98,11 +99,11 @@
dragDropManager, dragDropManager,
imageHighlighter, imageHighlighter,
pdfActionsManager, pdfActionsManager,
fileDragManager
] ]
) )
addFileInputListener(async (files) => {
pdfContainer.addPdfsFromFiles(files); fileDragManager.setCallback(async (files) => pdfContainer.addPdfsFromFiles(files));
});
</script> </script>
<style> <style>
@ -186,7 +187,7 @@
.page-container { .page-container {
height:250px; height:250px;
display: flex; display: flex;
align-items: center; align-items: center;
flex-direction: column-reverse; flex-direction: column-reverse;
aspect-ratio: 1; aspect-ratio: 1;

View file

@ -30,7 +30,6 @@ See https://github.com/adobe-type-tools/cmap-resources
<!-- Bootstrap --> <!-- Bootstrap -->
<script src="js/thirdParty/popper.min.js"></script> <script src="js/thirdParty/popper.min.js"></script>
<script src="js/thirdParty/bootstrap.min.js"></script> <script src="js/thirdParty/bootstrap.min.js"></script>
<link rel="stylesheet" href="css/bootstrap.min.css">
<!-- This snippet is used in production (included from view-pdf.html) --> <!-- This snippet is used in production (included from view-pdf.html) -->
<link rel="resource" type="application/l10n" href="pdfjs/locale/locale.properties"> <link rel="resource" type="application/l10n" href="pdfjs/locale/locale.properties">