mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-12 17:52:13 +02:00
Merge branch 'main' into feature/#3403/analytics-accepts-cookies
This commit is contained in:
commit
d93f8b7a0d
@ -127,7 +127,7 @@ Stirling-PDF currently supports 39 languages!
|
|||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
|
@ -29,7 +29,7 @@ ext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "stirling.software"
|
group = "stirling.software"
|
||||||
version = "0.46.0"
|
version = "0.46.1"
|
||||||
|
|
||||||
java {
|
java {
|
||||||
// 17 is lowest but we support and recommend 21
|
// 17 is lowest but we support and recommend 21
|
||||||
|
@ -34,6 +34,11 @@ public class EEAppConfig {
|
|||||||
return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL;
|
return licenseKeyChecker.getPremiumLicenseEnabledResult() != License.NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "license")
|
||||||
|
public String licenseType() {
|
||||||
|
return licenseKeyChecker.getPremiumLicenseEnabledResult().name();
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "runningEE")
|
@Bean(name = "runningEE")
|
||||||
public boolean runningEnterprise() {
|
public boolean runningEnterprise() {
|
||||||
return licenseKeyChecker.getPremiumLicenseEnabledResult() == License.ENTERPRISE;
|
return licenseKeyChecker.getPremiumLicenseEnabledResult() == License.ENTERPRISE;
|
||||||
|
@ -5,6 +5,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -33,6 +35,8 @@ public class AppConfig {
|
|||||||
|
|
||||||
private final ApplicationProperties applicationProperties;
|
private final ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
private final Environment env;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(name = "system.customHTMLFiles", havingValue = "true")
|
@ConditionalOnProperty(name = "system.customHTMLFiles", havingValue = "true")
|
||||||
public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
|
public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
|
||||||
@ -193,4 +197,37 @@ public class AppConfig {
|
|||||||
public String uuid() {
|
public String uuid() {
|
||||||
return applicationProperties.getAutomaticallyGenerated().getUUID();
|
return applicationProperties.getAutomaticallyGenerated().getUUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "disablePixel")
|
||||||
|
public boolean disablePixel() {
|
||||||
|
return Boolean.getBoolean(env.getProperty("DISABLE_PIXEL"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "machineType")
|
||||||
|
public String determineMachineType() {
|
||||||
|
try {
|
||||||
|
boolean isDocker = runningInDocker();
|
||||||
|
boolean isKubernetes = System.getenv("KUBERNETES_SERVICE_HOST") != null;
|
||||||
|
boolean isBrowserOpen = "true".equalsIgnoreCase(env.getProperty("BROWSER_OPEN"));
|
||||||
|
|
||||||
|
if (isKubernetes) {
|
||||||
|
return "Kubernetes";
|
||||||
|
} else if (isDocker) {
|
||||||
|
return "Docker";
|
||||||
|
} else if (isBrowserOpen) {
|
||||||
|
String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
|
||||||
|
if (os.contains("win")) {
|
||||||
|
return "Client-windows";
|
||||||
|
} else if (os.contains("mac")) {
|
||||||
|
return "Client-mac";
|
||||||
|
} else {
|
||||||
|
return "Client-unix";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "Server-jar";
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +180,15 @@ public class AnalysisController {
|
|||||||
|
|
||||||
// Get permissions
|
// Get permissions
|
||||||
Map<String, Boolean> permissions = new HashMap<>();
|
Map<String, Boolean> permissions = new HashMap<>();
|
||||||
permissions.put("canPrint", document.getCurrentAccessPermission().canPrint());
|
permissions.put("preventPrinting", !document.getCurrentAccessPermission().canPrint());
|
||||||
permissions.put("canModify", document.getCurrentAccessPermission().canModify());
|
|
||||||
permissions.put(
|
permissions.put(
|
||||||
"canExtractContent",
|
"preventModify", !document.getCurrentAccessPermission().canModify());
|
||||||
document.getCurrentAccessPermission().canExtractContent());
|
|
||||||
permissions.put(
|
permissions.put(
|
||||||
"canModifyAnnotations",
|
"preventExtractContent",
|
||||||
document.getCurrentAccessPermission().canModifyAnnotations());
|
!document.getCurrentAccessPermission().canExtractContent());
|
||||||
|
permissions.put(
|
||||||
|
"preventModifyAnnotations",
|
||||||
|
!document.getCurrentAccessPermission().canModifyAnnotations());
|
||||||
|
|
||||||
securityInfo.put("permissions", permissions);
|
securityInfo.put("permissions", permissions);
|
||||||
} else {
|
} else {
|
||||||
|
@ -627,23 +627,30 @@ public class CompressController {
|
|||||||
// Scale factors for different optimization levels
|
// Scale factors for different optimization levels
|
||||||
private double getScaleFactorForLevel(int optimizeLevel) {
|
private double getScaleFactorForLevel(int optimizeLevel) {
|
||||||
return switch (optimizeLevel) {
|
return switch (optimizeLevel) {
|
||||||
case 4 -> 0.9; // 90% - lite compression
|
case 3 -> 0.85;
|
||||||
case 5 -> 0.8; // 80% - lite compression
|
case 4 -> 0.75;
|
||||||
case 6 -> 0.7; // 70% - lite compression
|
case 5 -> 0.65;
|
||||||
case 7 -> 0.6; // 60% - intense compression
|
case 6 -> 0.55;
|
||||||
case 8 -> 0.5; // 50% - intense compression
|
case 7 -> 0.45;
|
||||||
case 9, 10 -> 0.4; // 40% - intense compression
|
case 8 -> 0.35;
|
||||||
default -> 1.0; // No scaling for levels 1-3
|
case 9 -> 0.25;
|
||||||
|
case 10 -> 0.15;
|
||||||
|
default -> 1.0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// JPEG quality for different optimization levels
|
// JPEG quality for different optimization levels
|
||||||
private float getJpegQualityForLevel(int optimizeLevel) {
|
private float getJpegQualityForLevel(int optimizeLevel) {
|
||||||
return switch (optimizeLevel) {
|
return switch (optimizeLevel) {
|
||||||
case 7 -> 0.8f; // 80% quality
|
case 3 -> 0.85f;
|
||||||
case 8 -> 0.6f; // 60% quality
|
case 4 -> 0.80f;
|
||||||
case 9, 10 -> 0.4f; // 40% quality
|
case 5 -> 0.75f;
|
||||||
default -> 0.7f; // 70% quality for levels 1-6
|
case 6 -> 0.70f;
|
||||||
|
case 7 -> 0.60f;
|
||||||
|
case 8 -> 0.50f;
|
||||||
|
case 9 -> 0.35f;
|
||||||
|
case 10 -> 0.2f;
|
||||||
|
default -> 0.7f;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,7 +705,7 @@ public class CompressController {
|
|||||||
|
|
||||||
while (!sizeMet && optimizeLevel <= 9) {
|
while (!sizeMet && optimizeLevel <= 9) {
|
||||||
// Apply image compression for levels 4-9
|
// Apply image compression for levels 4-9
|
||||||
if ((optimizeLevel >= 4 || Boolean.TRUE.equals(convertToGrayscale))
|
if ((optimizeLevel >= 3 || Boolean.TRUE.equals(convertToGrayscale))
|
||||||
&& !imageCompressionApplied) {
|
&& !imageCompressionApplied) {
|
||||||
double scaleFactor = getScaleFactorForLevel(optimizeLevel);
|
double scaleFactor = getScaleFactorForLevel(optimizeLevel);
|
||||||
float jpegQuality = getJpegQualityForLevel(optimizeLevel);
|
float jpegQuality = getJpegQualityForLevel(optimizeLevel);
|
||||||
@ -790,10 +797,14 @@ public class CompressController {
|
|||||||
log.info("Pre-QPDF file size: {}", GeneralUtils.formatBytes(preQpdfSize));
|
log.info("Pre-QPDF file size: {}", GeneralUtils.formatBytes(preQpdfSize));
|
||||||
|
|
||||||
// Map optimization levels to QPDF compression levels
|
// Map optimization levels to QPDF compression levels
|
||||||
int qpdfCompressionLevel =
|
int qpdfCompressionLevel;
|
||||||
optimizeLevel <= 3
|
if (optimizeLevel == 1) {
|
||||||
? optimizeLevel * 3 // Level 1->3, 2->6, 3->9
|
qpdfCompressionLevel = 5;
|
||||||
: 9; // Max compression for levels 4-9
|
} else if (optimizeLevel == 2) {
|
||||||
|
qpdfCompressionLevel = 9;
|
||||||
|
} else {
|
||||||
|
qpdfCompressionLevel = 9;
|
||||||
|
}
|
||||||
|
|
||||||
// Create output file for QPDF
|
// Create output file for QPDF
|
||||||
Path qpdfOutputFile = Files.createTempFile("qpdf_output_", ".pdf");
|
Path qpdfOutputFile = Files.createTempFile("qpdf_output_", ".pdf");
|
||||||
|
@ -63,25 +63,25 @@ public class PasswordController {
|
|||||||
String ownerPassword = request.getOwnerPassword();
|
String ownerPassword = request.getOwnerPassword();
|
||||||
String password = request.getPassword();
|
String password = request.getPassword();
|
||||||
int keyLength = request.getKeyLength();
|
int keyLength = request.getKeyLength();
|
||||||
boolean canAssembleDocument = request.isCanAssembleDocument();
|
boolean preventAssembly = request.isPreventAssembly();
|
||||||
boolean canExtractContent = request.isCanExtractContent();
|
boolean preventExtractContent = request.isPreventExtractContent();
|
||||||
boolean canExtractForAccessibility = request.isCanExtractForAccessibility();
|
boolean preventExtractForAccessibility = request.isPreventExtractForAccessibility();
|
||||||
boolean canFillInForm = request.isCanFillInForm();
|
boolean preventFillInForm = request.isPreventFillInForm();
|
||||||
boolean canModify = request.isCanModify();
|
boolean preventModify = request.isPreventModify();
|
||||||
boolean canModifyAnnotations = request.isCanModifyAnnotations();
|
boolean preventModifyAnnotations = request.isPreventModifyAnnotations();
|
||||||
boolean canPrint = request.isCanPrint();
|
boolean preventPrinting = request.isPreventPrinting();
|
||||||
boolean canPrintFaithful = request.isCanPrintFaithful();
|
boolean preventPrintingFaithful = request.isPreventPrintingFaithful();
|
||||||
|
|
||||||
PDDocument document = pdfDocumentFactory.load(fileInput);
|
PDDocument document = pdfDocumentFactory.load(fileInput);
|
||||||
AccessPermission ap = new AccessPermission();
|
AccessPermission ap = new AccessPermission();
|
||||||
ap.setCanAssembleDocument(!canAssembleDocument);
|
ap.setCanAssembleDocument(!preventAssembly);
|
||||||
ap.setCanExtractContent(!canExtractContent);
|
ap.setCanExtractContent(!preventExtractContent);
|
||||||
ap.setCanExtractForAccessibility(!canExtractForAccessibility);
|
ap.setCanExtractForAccessibility(!preventExtractForAccessibility);
|
||||||
ap.setCanFillInForm(!canFillInForm);
|
ap.setCanFillInForm(!preventFillInForm);
|
||||||
ap.setCanModify(!canModify);
|
ap.setCanModify(!preventModify);
|
||||||
ap.setCanModifyAnnotations(!canModifyAnnotations);
|
ap.setCanModifyAnnotations(!preventModifyAnnotations);
|
||||||
ap.setCanPrint(!canPrint);
|
ap.setCanPrint(!preventPrinting);
|
||||||
ap.setCanPrintFaithful(!canPrintFaithful);
|
ap.setCanPrintFaithful(!preventPrintingFaithful);
|
||||||
StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, password, ap);
|
StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, password, ap);
|
||||||
|
|
||||||
if (!"".equals(ownerPassword) || !"".equals(password)) {
|
if (!"".equals(ownerPassword) || !"".equals(password)) {
|
||||||
|
@ -170,15 +170,16 @@ public class RedactController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Color decodeOrDefault(String hex, Color defaultColor) {
|
private Color decodeOrDefault(String hex, Color defaultColor) {
|
||||||
Color color = null;
|
|
||||||
try {
|
try {
|
||||||
color = Color.decode(hex);
|
if (hex != null && !hex.startsWith("#")) {
|
||||||
|
hex = "#" + hex;
|
||||||
|
}
|
||||||
|
return Color.decode(hex);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
color = defaultColor;
|
return defaultColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Integer> getPageNumbers(ManualRedactPdfRequest request, int pagesCount) {
|
private List<Integer> getPageNumbers(ManualRedactPdfRequest request, int pagesCount) {
|
||||||
String pageNumbersInput = request.getPageNumbers();
|
String pageNumbersInput = request.getPageNumbers();
|
||||||
|
@ -29,31 +29,29 @@ public class AddPasswordRequest extends PDFFile {
|
|||||||
defaultValue = "256")
|
defaultValue = "256")
|
||||||
private int keyLength = 256;
|
private int keyLength = 256;
|
||||||
|
|
||||||
@Schema(description = "Whether the document assembly is allowed", example = "false")
|
@Schema(description = "Whether document assembly is prevented", example = "false")
|
||||||
private boolean canAssembleDocument;
|
private boolean preventAssembly;
|
||||||
|
|
||||||
|
@Schema(description = "Whether content extraction is prevented", example = "false")
|
||||||
|
private boolean preventExtractContent;
|
||||||
|
|
||||||
@Schema(
|
@Schema(
|
||||||
description = "Whether content extraction for accessibility is allowed",
|
description = "Whether content extraction for accessibility is prevented",
|
||||||
example = "false")
|
example = "false")
|
||||||
private boolean canExtractContent;
|
private boolean preventExtractForAccessibility;
|
||||||
|
|
||||||
@Schema(
|
@Schema(description = "Whether form filling is prevented", example = "false")
|
||||||
description = "Whether content extraction for accessibility is allowed",
|
private boolean preventFillInForm;
|
||||||
example = "false")
|
|
||||||
private boolean canExtractForAccessibility;
|
|
||||||
|
|
||||||
@Schema(description = "Whether form filling is allowed", example = "false")
|
@Schema(description = "Whether document modification is prevented", example = "false")
|
||||||
private boolean canFillInForm;
|
private boolean preventModify;
|
||||||
|
|
||||||
@Schema(description = "Whether the document modification is allowed", example = "false")
|
@Schema(description = "Whether modification of annotations is prevented", example = "false")
|
||||||
private boolean canModify;
|
private boolean preventModifyAnnotations;
|
||||||
|
|
||||||
@Schema(description = "Whether modification of annotations is allowed", example = "false")
|
@Schema(description = "Whether printing of the document is prevented", example = "false")
|
||||||
private boolean canModifyAnnotations;
|
private boolean preventPrinting;
|
||||||
|
|
||||||
@Schema(description = "Whether printing of the document is allowed", example = "false")
|
@Schema(description = "Whether faithful printing is prevented", example = "false")
|
||||||
private boolean canPrint;
|
private boolean preventPrintingFaithful;
|
||||||
|
|
||||||
@Schema(description = "Whether faithful printing is allowed", example = "false")
|
|
||||||
private boolean canPrintFaithful;
|
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ public class RedactPdfRequest extends PDFFile {
|
|||||||
@Schema(description = "Whether to use whole word search", defaultValue = "false")
|
@Schema(description = "Whether to use whole word search", defaultValue = "false")
|
||||||
private boolean wholeWordSearch;
|
private boolean wholeWordSearch;
|
||||||
|
|
||||||
@Schema(description = "The color for redaction", defaultValue = "#000000")
|
@Schema(description = "Hexadecimal color code for redaction, e.g. #FF0000 or 000000", defaultValue = "#000000")
|
||||||
private String redactColor = "#000000";
|
private String redactColor = "#000000";
|
||||||
|
|
||||||
@Schema(description = "Custom padding for redaction", type = "number")
|
@Schema(description = "Custom padding for redaction", type = "number")
|
||||||
|
@ -517,13 +517,13 @@ home.showJS.title=Afficher le JavaScript
|
|||||||
home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
|
home.showJS.desc=Recherche et affiche tout JavaScript injecté dans un PDF.
|
||||||
showJS.tags=JS
|
showJS.tags=JS
|
||||||
|
|
||||||
home.autoRedact.title=Censure automatique
|
home.autoRedact.title=Caviardage automatique
|
||||||
home.autoRedact.desc=Censurer automatiquement les informations sensibles d'un PDF.
|
home.autoRedact.desc=Caviardez automatiquement les informations sensibles d'un PDF.
|
||||||
autoRedact.tags=caviarder,rédiger,censurer,redact,auto
|
autoRedact.tags=caviarder,redact,auto,Masquer,noircir,noir,marqueur,caché,rédiger,censurer
|
||||||
|
|
||||||
home.redact.title=Censure manuelle
|
home.redact.title=Caviardage manuel
|
||||||
home.redact.desc=Censurer un PDF en fonction de texte sélectionné, formes dessinées et/ou des pages sélectionnées.
|
home.redact.desc=Caviarder un PDF en fonction de texte sélectionné, formes dessinées et/ou des pages sélectionnées.
|
||||||
redact.tags=Redact,Hide,black out,black,marker,hidden,manual,caviarder,rédiger,censurer
|
redact.tags=Caviarder,Redact,Masquer,noircir,noir,marqueur,caché,rédiger,censurer
|
||||||
|
|
||||||
home.tableExtraxt.title=PDF en CSV
|
home.tableExtraxt.title=PDF en CSV
|
||||||
home.tableExtraxt.desc=Extrait les tableaux d'un PDF et les transforme en CSV.
|
home.tableExtraxt.desc=Extrait les tableaux d'un PDF et les transforme en CSV.
|
||||||
@ -624,31 +624,31 @@ autoRedact.convertPDFToImageLabel=Convertir un PDF en PDF-Image (utilisé pour s
|
|||||||
autoRedact.submitButton=Caviarder
|
autoRedact.submitButton=Caviarder
|
||||||
|
|
||||||
#redact
|
#redact
|
||||||
redact.title=Rédaction manuelle
|
redact.title=Caviardage manuel
|
||||||
redact.header=Rédaction manuelle
|
redact.header=Caviardage manuel
|
||||||
redact.submit=Rédiger
|
redact.submit=Caviarder
|
||||||
redact.textBasedRedaction=Rédaction en fonction de texte
|
redact.textBasedRedaction=Caviarder du texte
|
||||||
redact.pageBasedRedaction=Rédaction en fonction de pages
|
redact.pageBasedRedaction=Caviarder des pages
|
||||||
redact.convertPDFToImageLabel=Convertir en PDF-Image (pour supprimer le texte derrière le rectangle)
|
redact.convertPDFToImageLabel=Convertir en PDF-Image (pour supprimer le texte derrière le rectangle)
|
||||||
redact.pageRedactionNumbers.title=Pages
|
redact.pageRedactionNumbers.title=Pages
|
||||||
redact.pageRedactionNumbers.placeholder=(ex: 1,2,8 ou 4,7,12-16 ou 2n-1)
|
redact.pageRedactionNumbers.placeholder=(ex: 1,2,8 ou 4,7,12-16 ou 2n-1)
|
||||||
redact.redactionColor.title=Couleur
|
redact.redactionColor.title=Couleur
|
||||||
redact.export=Exporter
|
redact.export=Exporter
|
||||||
redact.upload=Téléverser
|
redact.upload=Téléverser
|
||||||
redact.boxRedaction=Dessiner le rectangle à rédiger
|
redact.boxRedaction=Tracer le rectangle à caviarder
|
||||||
redact.zoom=Zoom
|
redact.zoom=Zoom
|
||||||
redact.zoomIn=Zoom avant
|
redact.zoomIn=Zoom avant
|
||||||
redact.zoomOut=Zoom arrière
|
redact.zoomOut=Zoom arrière
|
||||||
redact.nextPage=Page suivante
|
redact.nextPage=Page suivante
|
||||||
redact.previousPage=Page précédente
|
redact.previousPage=Page précédente
|
||||||
redact.toggleSidebar=Toggle Sidebar
|
redact.toggleSidebar=Montrer la barre latérale
|
||||||
redact.showThumbnails=Afficher les miniatures
|
redact.showThumbnails=Afficher les miniatures
|
||||||
redact.showDocumentOutline=Montrer les contours du document (double-click pour agrandir/réduire tous les éléments)
|
redact.showDocumentOutline=Montrer les contours du document (double-click pour agrandir/réduire tous les éléments)
|
||||||
redact.showAttatchments=Montrer les éléments attachés
|
redact.showAttatchments=Montrer les éléments attachés
|
||||||
redact.showLayers=Montrer les calques (double-click pour réinitialiser tous les calques à l'état par défaut)
|
redact.showLayers=Montrer les calques (double-click pour réinitialiser tous les calques à l'état par défaut)
|
||||||
redact.colourPicker=Sélection de couleur
|
redact.colourPicker=Sélection de couleur
|
||||||
redact.findCurrentOutlineItem=Trouver l'élément de contour courrant
|
redact.findCurrentOutlineItem=Trouver l'élément de contour courrant
|
||||||
redact.applyChanges=Apply Changes
|
redact.applyChanges=Appliquer les changements
|
||||||
|
|
||||||
#showJS
|
#showJS
|
||||||
showJS.title=Afficher le JavaScript
|
showJS.title=Afficher le JavaScript
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#page-container {
|
#page-container {
|
||||||
min-height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
overflow-x: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
#content-wrap {
|
#content-wrap {
|
||||||
|
@ -162,6 +162,7 @@ html[dir="rtl"] .lang-dropdown-item-wrapper {
|
|||||||
text-wrap: wrap;
|
text-wrap: wrap;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
font-size: large;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-icon {
|
.close-icon {
|
||||||
@ -476,6 +477,9 @@ html[dir="rtl"] .dropdown-menu[data-bs-popper] {
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 30px;
|
gap: 30px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
width: 140%;
|
||||||
|
position: relative;
|
||||||
|
left: -20%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.feature-group {
|
.feature-group {
|
||||||
|
@ -299,21 +299,42 @@ document.getElementById("addOperationBtn").addEventListener("click", function ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listItem.innerHTML = `
|
let containerDiv = document.createElement("div");
|
||||||
<div class="d-flex justify-content-between align-items-center w-100">
|
containerDiv.className = "d-flex justify-content-between align-items-center w-100";
|
||||||
<div class="operationName">${selectedOperation}</div>
|
|
||||||
<div class="arrows d-flex">
|
let operationNameDiv = document.createElement("div");
|
||||||
<button class="btn btn-secondary move-up ms-1"><span class="material-symbols-rounded">arrow_upward</span></button>
|
operationNameDiv.className = "operationName";
|
||||||
<button class="btn btn-secondary move-down ms-1"><span class="material-symbols-rounded">arrow_downward</span></button>
|
operationNameDiv.textContent = selectedOperation;
|
||||||
<button class="btn ${hasSettings ? "btn-warning" : "btn-secondary"} pipelineSettings ms-1" ${
|
containerDiv.appendChild(operationNameDiv);
|
||||||
hasSettings ? "" : "disabled"
|
|
||||||
}>
|
let arrowsDiv = document.createElement("div");
|
||||||
<span class="material-symbols-rounded">settings</span>
|
arrowsDiv.className = "arrows d-flex";
|
||||||
</button>
|
|
||||||
<button class="btn btn-danger remove ms-1"><span class="material-symbols-rounded">close</span></button>
|
let moveUpButton = document.createElement("button");
|
||||||
</div>
|
moveUpButton.className = "btn btn-secondary move-up ms-1";
|
||||||
</div>
|
moveUpButton.innerHTML = '<span class="material-symbols-rounded">arrow_upward</span>';
|
||||||
`;
|
arrowsDiv.appendChild(moveUpButton);
|
||||||
|
|
||||||
|
let moveDownButton = document.createElement("button");
|
||||||
|
moveDownButton.className = "btn btn-secondary move-down ms-1";
|
||||||
|
moveDownButton.innerHTML = '<span class="material-symbols-rounded">arrow_downward</span>';
|
||||||
|
arrowsDiv.appendChild(moveDownButton);
|
||||||
|
|
||||||
|
let settingsButton = document.createElement("button");
|
||||||
|
settingsButton.className = `btn ${hasSettings ? "btn-warning" : "btn-secondary"} pipelineSettings ms-1`;
|
||||||
|
if (!hasSettings) {
|
||||||
|
settingsButton.disabled = true;
|
||||||
|
}
|
||||||
|
settingsButton.innerHTML = '<span class="material-symbols-rounded">settings</span>';
|
||||||
|
arrowsDiv.appendChild(settingsButton);
|
||||||
|
|
||||||
|
let removeButton = document.createElement("button");
|
||||||
|
removeButton.className = "btn btn-danger remove ms-1";
|
||||||
|
removeButton.innerHTML = '<span class="material-symbols-rounded">close</span>';
|
||||||
|
arrowsDiv.appendChild(removeButton);
|
||||||
|
|
||||||
|
containerDiv.appendChild(arrowsDiv);
|
||||||
|
listItem.appendChild(containerDiv);
|
||||||
|
|
||||||
pipelineList.appendChild(listItem);
|
pipelineList.appendChild(listItem);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ TabContainer = {
|
|||||||
tabList.classList.add('tab-buttons');
|
tabList.classList.add('tab-buttons');
|
||||||
tabTitles.forEach((title) => {
|
tabTitles.forEach((title) => {
|
||||||
const tabButton = document.createElement('button');
|
const tabButton = document.createElement('button');
|
||||||
tabButton.innerHTML = title;
|
tabButton.textContent = title;
|
||||||
tabButton.onclick = (e) => {
|
tabButton.onclick = (e) => {
|
||||||
this.setActiveTab(e.target);
|
this.setActiveTab(e.target);
|
||||||
};
|
};
|
||||||
|
@ -41,7 +41,13 @@
|
|||||||
<link rel="stylesheet" th:href="@{'/css/bootstrap-icons.min.css'}">
|
<link rel="stylesheet" th:href="@{'/css/bootstrap-icons.min.css'}">
|
||||||
|
|
||||||
<!-- Pixel, doesn't collect any PII-->
|
<!-- Pixel, doesn't collect any PII-->
|
||||||
<img referrerpolicy="no-referrer-when-downgrade" src="https://pixel.stirlingpdf.com/a.png?x-pxid=4f5fa02f-a065-4efb-bb2c-24509a4b6b92" style="position: absolute; visibility: hidden;"/>
|
<img th:if="${!@disablePixel}" referrerpolicy="no-referrer-when-downgrade"
|
||||||
|
th:src="'https://pixel.stirlingpdf.com/a.png?x-pxid=4f5fa02f-a065-4efb-bb2c-24509a4b6b92'
|
||||||
|
+ '&machineType=' + ${@machineType}
|
||||||
|
+ '&appVersion=' + ${@appVersion}
|
||||||
|
+ '&licenseType=' + ${@license}
|
||||||
|
+ '&loginEnabled=' + ${@loginEnabled}"
|
||||||
|
style="position: absolute; visibility: hidden;" />
|
||||||
|
|
||||||
<!-- Custom -->
|
<!-- Custom -->
|
||||||
<link rel="stylesheet" th:href="@{'/css/general.css'}">
|
<link rel="stylesheet" th:href="@{'/css/general.css'}">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div th:fragment="navbar" class="mx-auto" style="position: sticky; top:0; z-index:10000">
|
<div th:fragment="navbar" class="mx-auto" style="position: sticky; top:0; z-index:10000; width:100%">
|
||||||
<script th:src="@{'/js/languageSelection.js'}"></script>
|
<script th:src="@{'/js/languageSelection.js'}"></script>
|
||||||
<script th:src="@{'/js/navbar.js'}"></script>
|
<script th:src="@{'/js/navbar.js'}"></script>
|
||||||
<script th:src="@{'/js/additionalLanguageCode.js'}"></script>
|
<script th:src="@{'/js/additionalLanguageCode.js'}"></script>
|
||||||
|
@ -8,19 +8,17 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="page-container">
|
<div id="page-container">
|
||||||
<div id="content-wrap">
|
|
||||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||||
|
<div style="transform-origin: top;"
|
||||||
|
id="scale-wrap">
|
||||||
|
|
||||||
<br class="d-md-none">
|
<br class="d-md-none">
|
||||||
<!-- Features -->
|
<!-- Features -->
|
||||||
<script th:src="@{'/js/homecard.js'}"></script>
|
<script th:src="@{'/js/homecard.js'}"></script>
|
||||||
<div style="
|
<div style="
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;">
|
flex-direction: column;"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<br>
|
<br>
|
||||||
<div style="justify-content: center; display: flex;">
|
<div style="justify-content: center; display: flex;">
|
||||||
@ -45,7 +43,7 @@
|
|||||||
th:insert="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'organize')}">
|
th:insert="~{fragments/navbarEntry :: navbarEntry ('multi-tool', 'construction', 'home.multiTool.title', 'home.multiTool.desc', 'multiTool.tags', 'organize')}">
|
||||||
</div>
|
</div>
|
||||||
<div class="newfeature"
|
<div class="newfeature"
|
||||||
th:insert="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
|
th:insert="~{fragments/navbarEntry :: navbarEntry('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPDFs.tags', 'advance')}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -123,9 +121,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -222,6 +221,20 @@
|
|||||||
window.showSurvey = /*[[${showSurveyFromDocker}]]*/ true
|
window.showSurvey = /*[[${showSurveyFromDocker}]]*/ true
|
||||||
</script>
|
</script>
|
||||||
<script th:src="@{'/js/pages/home.js'}" th:inline="javascript"></script>
|
<script th:src="@{'/js/pages/home.js'}" th:inline="javascript"></script>
|
||||||
|
<script>
|
||||||
|
function applyScale() {
|
||||||
|
const baseWidth = 1440;
|
||||||
|
const baseHeight = 1000;
|
||||||
|
const scaleX = window.innerWidth / baseWidth;
|
||||||
|
const scaleY = window.innerHeight / baseHeight;
|
||||||
|
const scale = Math.max(0.9, Math.min(scaleX, scaleY)); // keep aspect ratio, honor minScale
|
||||||
|
const ui = document.getElementById('scale-wrap');
|
||||||
|
ui.style.transform = `scale(${scale*0.75})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('resize', applyScale);
|
||||||
|
window.addEventListener('load', applyScale);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
@ -41,36 +41,36 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="mb-2" th:text="#{addPassword.selectText.5}"></label>
|
<label class="mb-2" th:text="#{addPassword.selectText.5}"></label>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canAssembleDocument" name="canAssembleDocument">
|
<input type="checkbox" id="preventAssembly" name="preventAssembly">
|
||||||
<label for="canAssembleDocument" th:text="#{addPassword.selectText.6}"></label>
|
<label for="preventAssembly" th:text="#{addPassword.selectText.6}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canExtractContent" name="canExtractContent">
|
<input type="checkbox" id="preventExtractContent" name="preventExtractContent">
|
||||||
<label for="canExtractContent" th:text="#{addPassword.selectText.7}"></label>
|
<label for="preventExtractContent" th:text="#{addPassword.selectText.7}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canExtractForAccessibility" name="canExtractForAccessibility">
|
<input type="checkbox" id="preventExtractForAccessibility" name="preventExtractForAccessibility">
|
||||||
<label for="canExtractForAccessibility" th:text="#{addPassword.selectText.8}"></label>
|
<label for="preventExtractForAccessibility" th:text="#{addPassword.selectText.8}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canFillInForm" name="canFillInForm">
|
<input type="checkbox" id="preventFillInForm" name="preventFillInForm">
|
||||||
<label for="canFillInForm" th:text="#{addPassword.selectText.9}"></label>
|
<label for="preventFillInForm" th:text="#{addPassword.selectText.9}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canModify" name="canModify">
|
<input type="checkbox" id="preventModify" name="preventModify">
|
||||||
<label for="canModify" th:text="#{addPassword.selectText.10}"></label>
|
<label for="preventModify" th:text="#{addPassword.selectText.10}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canModifyAnnotations" name="canModifyAnnotations">
|
<input type="checkbox" id="preventModifyAnnotations" name="preventModifyAnnotations">
|
||||||
<label for="canModifyAnnotations" th:text="#{addPassword.selectText.11}"></label>
|
<label for="preventModifyAnnotations" th:text="#{addPassword.selectText.11}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canPrint" name="canPrint">
|
<input type="checkbox" id="preventPrinting" name="preventPrinting">
|
||||||
<label for="canPrint" th:text="#{addPassword.selectText.12}"></label>
|
<label for="preventPrinting" th:text="#{addPassword.selectText.12}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canPrintFaithful" name="canPrintFaithful">
|
<input type="checkbox" id="preventPrintingFaithful" name="preventPrintingFaithful">
|
||||||
<label for="canPrintFaithful" th:text="#{addPassword.selectText.13}"></label>
|
<label for="preventPrintingFaithful" th:text="#{addPassword.selectText.13}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
@ -25,36 +25,36 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="mb-2" th:text="#{permissions.selectText.2}"></label>
|
<label class="mb-2" th:text="#{permissions.selectText.2}"></label>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canAssembleDocument" name="canAssembleDocument">
|
<input type="checkbox" id="preventAssembly" name="preventAssembly">
|
||||||
<label for="canAssembleDocument" th:text="#{permissions.selectText.3}"></label>
|
<label for="preventAssembly" th:text="#{permissions.selectText.3}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canExtractContent" name="canExtractContent">
|
<input type="checkbox" id="preventExtractContent" name="preventExtractContent">
|
||||||
<label for="canExtractContent" th:text="#{permissions.selectText.4}"></label>
|
<label for="preventExtractContent" th:text="#{permissions.selectText.4}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canExtractForAccessibility" name="canExtractForAccessibility">
|
<input type="checkbox" id="preventExtractForAccessibility" name="preventExtractForAccessibility">
|
||||||
<label for="canExtractForAccessibility" th:text="#{permissions.selectText.5}"></label>
|
<label for="preventExtractForAccessibility" th:text="#{permissions.selectText.5}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canFillInForm" name="canFillInForm">
|
<input type="checkbox" id="preventFillInForm" name="preventFillInForm">
|
||||||
<label for="canFillInForm" th:text="#{permissions.selectText.6}"></label>
|
<label for="preventFillInForm" th:text="#{permissions.selectText.6}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canModify" name="canModify">
|
<input type="checkbox" id="preventModify" name="preventModify">
|
||||||
<label for="canModify" th:text="#{permissions.selectText.7}"></label>
|
<label for="preventModify" th:text="#{permissions.selectText.7}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canModifyAnnotations" name="canModifyAnnotations">
|
<input type="checkbox" id="preventModifyAnnotations" name="preventModifyAnnotations">
|
||||||
<label for="canModifyAnnotations" th:text="#{permissions.selectText.8}"></label>
|
<label for="preventModifyAnnotations" th:text="#{permissions.selectText.8}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canPrint" name="canPrint">
|
<input type="checkbox" id="preventPrinting" name="preventPrinting">
|
||||||
<label for="canPrint" th:text="#{permissions.selectText.9}"></label>
|
<label for="preventPrinting" th:text="#{permissions.selectText.9}"></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input type="checkbox" id="canPrintFaithful" name="canPrintFaithful">
|
<input type="checkbox" id="preventPrintingFaithful" name="preventPrintingFaithful">
|
||||||
<label for="canPrintFaithful" th:text="#{permissions.selectText.10}"></label>
|
<label for="preventPrintingFaithful" th:text="#{permissions.selectText.10}"></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
Loading…
Reference in New Issue
Block a user