mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-12 18:45:03 +00:00
Merge remote-tracking branch 'origin/main' into Team
This commit is contained in:
commit
1f69513972
60
README.md
60
README.md
@ -116,46 +116,46 @@ Stirling-PDF currently supports 40 languages!
|
||||
|
||||
| Language | Progress |
|
||||
| -------------------------------------------- | -------------------------------------- |
|
||||
| Arabic (العربية) (ar_AR) |  |
|
||||
| Arabic (العربية) (ar_AR) |  |
|
||||
| Azerbaijani (Azərbaycan Dili) (az_AZ) |  |
|
||||
| Basque (Euskara) (eu_ES) |  |
|
||||
| Bulgarian (Български) (bg_BG) |  |
|
||||
| Catalan (Català) (ca_CA) |  |
|
||||
| Croatian (Hrvatski) (hr_HR) |  |
|
||||
| Czech (Česky) (cs_CZ) |  |
|
||||
| Danish (Dansk) (da_DK) |  |
|
||||
| Dutch (Nederlands) (nl_NL) |  |
|
||||
| Bulgarian (Български) (bg_BG) |  |
|
||||
| Catalan (Català) (ca_CA) |  |
|
||||
| Croatian (Hrvatski) (hr_HR) |  |
|
||||
| Czech (Česky) (cs_CZ) |  |
|
||||
| Danish (Dansk) (da_DK) |  |
|
||||
| Dutch (Nederlands) (nl_NL) |  |
|
||||
| English (English) (en_GB) |  |
|
||||
| English (US) (en_US) |  |
|
||||
| French (Français) (fr_FR) |  |
|
||||
| German (Deutsch) (de_DE) |  |
|
||||
| Greek (Ελληνικά) (el_GR) |  |
|
||||
| French (Français) (fr_FR) |  |
|
||||
| German (Deutsch) (de_DE) |  |
|
||||
| Greek (Ελληνικά) (el_GR) |  |
|
||||
| Hindi (हिंदी) (hi_IN) |  |
|
||||
| Hungarian (Magyar) (hu_HU) |  |
|
||||
| Hungarian (Magyar) (hu_HU) |  |
|
||||
| Indonesian (Bahasa Indonesia) (id_ID) |  |
|
||||
| Irish (Gaeilge) (ga_IE) |  |
|
||||
| Italian (Italiano) (it_IT) |  |
|
||||
| Japanese (日本語) (ja_JP) |  |
|
||||
| Korean (한국어) (ko_KR) |  |
|
||||
| Norwegian (Norsk) (no_NB) |  |
|
||||
| Persian (فارسی) (fa_IR) |  |
|
||||
| Polish (Polski) (pl_PL) |  |
|
||||
| Portuguese (Português) (pt_PT) |  |
|
||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||
| Romanian (Română) (ro_RO) |  |
|
||||
| Russian (Русский) (ru_RU) |  |
|
||||
| Irish (Gaeilge) (ga_IE) |  |
|
||||
| Italian (Italiano) (it_IT) |  |
|
||||
| Japanese (日本語) (ja_JP) |  |
|
||||
| Korean (한국어) (ko_KR) |  |
|
||||
| Norwegian (Norsk) (no_NB) |  |
|
||||
| Persian (فارسی) (fa_IR) |  |
|
||||
| Polish (Polski) (pl_PL) |  |
|
||||
| Portuguese (Português) (pt_PT) |  |
|
||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||
| Romanian (Română) (ro_RO) |  |
|
||||
| Russian (Русский) (ru_RU) |  |
|
||||
| Serbian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||
| Slovakian (Slovensky) (sk_SK) |  |
|
||||
| Slovenian (Slovenščina) (sl_SI) |  |
|
||||
| Spanish (Español) (es_ES) |  |
|
||||
| Slovenian (Slovenščina) (sl_SI) |  |
|
||||
| Spanish (Español) (es_ES) |  |
|
||||
| Swedish (Svenska) (sv_SE) |  |
|
||||
| Thai (ไทย) (th_TH) |  |
|
||||
| Tibetan (བོད་ཡིག་) (bo_CN) |  |
|
||||
| Thai (ไทย) (th_TH) |  |
|
||||
| Tibetan (བོད་ཡིག་) (bo_CN) |  |
|
||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||
| Turkish (Türkçe) (tr_TR) |  |
|
||||
| Ukrainian (Українська) (uk_UA) |  |
|
||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||
| Turkish (Türkçe) (tr_TR) |  |
|
||||
| Ukrainian (Українська) (uk_UA) |  |
|
||||
| Vietnamese (Tiếng Việt) (vi_VN) |  |
|
||||
| Malayalam (മലയാളം) (ml_IN) |  |
|
||||
|
||||
## Stirling PDF Enterprise
|
||||
|
@ -87,6 +87,7 @@ subprojects {
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'com.diffplug.spotless'
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
java {
|
||||
@ -558,4 +559,4 @@ tasks.named('bootRun') {
|
||||
doFirst {
|
||||
println "Delegating to :stirling-pdf:bootRun"
|
||||
}
|
||||
}
|
||||
}
|
1
common/.gitignore
vendored
1
common/.gitignore
vendored
@ -194,4 +194,3 @@ id_ed25519.pub
|
||||
|
||||
# node_modules
|
||||
node_modules/
|
||||
*.mjs
|
||||
|
@ -11,4 +11,5 @@ dependencies {
|
||||
api 'jakarta.servlet:jakarta.servlet-api:6.1.0'
|
||||
api 'org.snakeyaml:snakeyaml-engine:2.9'
|
||||
api "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8"
|
||||
}
|
||||
api 'jakarta.mail:jakarta.mail-api:2.1.3'
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package stirling.software.common.model.api.converters;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import stirling.software.common.model.api.PDFFile;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EmlToPdfRequest extends PDFFile {
|
||||
|
||||
// fileInput is inherited from PDFFile
|
||||
|
||||
@Schema(
|
||||
description = "Include email attachments in the PDF output",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
example = "false")
|
||||
private boolean includeAttachments = false;
|
||||
|
||||
@Schema(
|
||||
description = "Maximum attachment size in MB to include (default 10MB, range: 1-100)",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
example = "10",
|
||||
minimum = "1",
|
||||
maximum = "100")
|
||||
private int maxAttachmentSizeMB = 10;
|
||||
|
||||
@Schema(
|
||||
description = "Download HTML intermediate file instead of PDF",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
example = "false")
|
||||
private boolean downloadHtml = false;
|
||||
|
||||
@Schema(
|
||||
description = "Include CC and BCC recipients in header (if available)",
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
example = "true")
|
||||
private boolean includeAllRecipients = true;
|
||||
}
|
1565
common/src/main/java/stirling/software/common/util/EmlToPdf.java
Normal file
1565
common/src/main/java/stirling/software/common/util/EmlToPdf.java
Normal file
File diff suppressed because it is too large
Load Diff
1
proprietary/.gitignore
vendored
1
proprietary/.gitignore
vendored
@ -194,4 +194,3 @@ id_ed25519.pub
|
||||
|
||||
# node_modules
|
||||
node_modules/
|
||||
*.mjs
|
||||
|
6
stirling-pdf/.gitignore
vendored
6
stirling-pdf/.gitignore
vendored
@ -123,8 +123,8 @@ SwaggerDoc.json
|
||||
*.tar.gz
|
||||
*.rar
|
||||
*.db
|
||||
/build
|
||||
/stirling-pdf/build/
|
||||
/build/*
|
||||
/stirling-pdf/build/*
|
||||
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
@ -193,4 +193,4 @@ id_ed25519.pub
|
||||
**/jcef-bundle/
|
||||
|
||||
# node_modules
|
||||
node_modules/
|
||||
node_modules/
|
@ -1,10 +1,10 @@
|
||||
apply plugin: 'org.springframework.boot'
|
||||
|
||||
|
||||
repositories {
|
||||
maven { url = 'https://build.shibboleth.net/maven/releases' }
|
||||
maven { url = 'https://maven.pkg.github.com/jcefmaven/jcefmaven' }
|
||||
}
|
||||
|
||||
configurations {
|
||||
developmentOnly
|
||||
runtimeClasspath {
|
||||
@ -101,4 +101,4 @@ jar {
|
||||
}
|
||||
|
||||
jar.dependsOn ':common:jar'
|
||||
jar.dependsOn ':proprietary:jar'
|
||||
jar.dependsOn ':proprietary:jar'
|
@ -80,4 +80,4 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
|
||||
HttpServletResponse response,
|
||||
Object handler,
|
||||
Exception ex) {}
|
||||
}
|
||||
}
|
@ -0,0 +1,303 @@
|
||||
package stirling.software.SPDF.config;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EndpointConfiguration {
|
||||
|
||||
private static final String REMOVE_BLANKS = "remove-blanks";
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private Map<String, Boolean> endpointStatuses = new ConcurrentHashMap<>();
|
||||
private Map<String, Set<String>> endpointGroups = new ConcurrentHashMap<>();
|
||||
private final boolean runningProOrHigher;
|
||||
|
||||
public EndpointConfiguration(
|
||||
ApplicationProperties applicationProperties,
|
||||
@Qualifier("runningProOrHigher") boolean runningProOrHigher) {
|
||||
this.applicationProperties = applicationProperties;
|
||||
this.runningProOrHigher = runningProOrHigher;
|
||||
init();
|
||||
processEnvironmentConfigs();
|
||||
}
|
||||
|
||||
public void enableEndpoint(String endpoint) {
|
||||
endpointStatuses.put(endpoint, true);
|
||||
}
|
||||
|
||||
public void disableEndpoint(String endpoint) {
|
||||
if (!endpointStatuses.containsKey(endpoint) || endpointStatuses.get(endpoint) != false) {
|
||||
log.debug("Disabling {}", endpoint);
|
||||
endpointStatuses.put(endpoint, false);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getEndpointStatuses() {
|
||||
return endpointStatuses;
|
||||
}
|
||||
|
||||
public boolean isEndpointEnabled(String endpoint) {
|
||||
if (endpoint.startsWith("/")) {
|
||||
endpoint = endpoint.substring(1);
|
||||
}
|
||||
return endpointStatuses.getOrDefault(endpoint, true);
|
||||
}
|
||||
|
||||
public boolean isGroupEnabled(String group) {
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints == null || endpoints.isEmpty()) {
|
||||
log.debug("Group '{}' does not exist or has no endpoints", group);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String endpoint : endpoints) {
|
||||
if (!isEndpointEnabled(endpoint)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addEndpointToGroup(String group, String endpoint) {
|
||||
endpointGroups.computeIfAbsent(group, k -> new HashSet<>()).add(endpoint);
|
||||
}
|
||||
|
||||
public void enableGroup(String group) {
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints != null) {
|
||||
for (String endpoint : endpoints) {
|
||||
enableEndpoint(endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void disableGroup(String group) {
|
||||
Set<String> endpoints = endpointGroups.get(group);
|
||||
if (endpoints != null) {
|
||||
for (String endpoint : endpoints) {
|
||||
disableEndpoint(endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void logDisabledEndpointsSummary() {
|
||||
List<String> disabledList =
|
||||
endpointStatuses.entrySet().stream()
|
||||
.filter(entry -> !entry.getValue()) // only get disabled endpoints (value
|
||||
// is false)
|
||||
.map(Map.Entry::getKey)
|
||||
.sorted()
|
||||
.toList();
|
||||
|
||||
if (!disabledList.isEmpty()) {
|
||||
log.info(
|
||||
"Total disabled endpoints: {}. Disabled endpoints: {}",
|
||||
disabledList.size(),
|
||||
String.join(", ", disabledList));
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
// Adding endpoints to "PageOps" group
|
||||
addEndpointToGroup("PageOps", "remove-pages");
|
||||
addEndpointToGroup("PageOps", "merge-pdfs");
|
||||
addEndpointToGroup("PageOps", "split-pdfs");
|
||||
addEndpointToGroup("PageOps", "pdf-organizer");
|
||||
addEndpointToGroup("PageOps", "rotate-pdf");
|
||||
addEndpointToGroup("PageOps", "multi-page-layout");
|
||||
addEndpointToGroup("PageOps", "scale-pages");
|
||||
addEndpointToGroup("PageOps", "adjust-contrast");
|
||||
addEndpointToGroup("PageOps", "crop");
|
||||
addEndpointToGroup("PageOps", "auto-split-pdf");
|
||||
addEndpointToGroup("PageOps", "extract-page");
|
||||
addEndpointToGroup("PageOps", "pdf-to-single-page");
|
||||
addEndpointToGroup("PageOps", "split-by-size-or-count");
|
||||
addEndpointToGroup("PageOps", "overlay-pdf");
|
||||
addEndpointToGroup("PageOps", "split-pdf-by-sections");
|
||||
|
||||
// Adding endpoints to "Convert" group
|
||||
addEndpointToGroup("Convert", "pdf-to-img");
|
||||
addEndpointToGroup("Convert", "img-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-pdfa");
|
||||
addEndpointToGroup("Convert", "file-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-word");
|
||||
addEndpointToGroup("Convert", "pdf-to-presentation");
|
||||
addEndpointToGroup("Convert", "pdf-to-text");
|
||||
addEndpointToGroup("Convert", "pdf-to-html");
|
||||
addEndpointToGroup("Convert", "pdf-to-xml");
|
||||
addEndpointToGroup("Convert", "html-to-pdf");
|
||||
addEndpointToGroup("Convert", "url-to-pdf");
|
||||
addEndpointToGroup("Convert", "markdown-to-pdf");
|
||||
addEndpointToGroup("Convert", "pdf-to-csv");
|
||||
addEndpointToGroup("Convert", "pdf-to-markdown");
|
||||
|
||||
// Adding endpoints to "Security" group
|
||||
addEndpointToGroup("Security", "add-password");
|
||||
addEndpointToGroup("Security", "remove-password");
|
||||
addEndpointToGroup("Security", "change-permissions");
|
||||
addEndpointToGroup("Security", "add-watermark");
|
||||
addEndpointToGroup("Security", "cert-sign");
|
||||
addEndpointToGroup("Security", "remove-cert-sign");
|
||||
addEndpointToGroup("Security", "sanitize-pdf");
|
||||
addEndpointToGroup("Security", "auto-redact");
|
||||
addEndpointToGroup("Security", "redact");
|
||||
|
||||
// Adding endpoints to "Other" group
|
||||
addEndpointToGroup("Other", "ocr-pdf");
|
||||
addEndpointToGroup("Other", "add-image");
|
||||
addEndpointToGroup("Other", "compress-pdf");
|
||||
addEndpointToGroup("Other", "extract-images");
|
||||
addEndpointToGroup("Other", "change-metadata");
|
||||
addEndpointToGroup("Other", "extract-image-scans");
|
||||
addEndpointToGroup("Other", "sign");
|
||||
addEndpointToGroup("Other", "flatten");
|
||||
addEndpointToGroup("Other", "repair");
|
||||
addEndpointToGroup("Other", "unlock-pdf-forms");
|
||||
addEndpointToGroup("Other", REMOVE_BLANKS);
|
||||
addEndpointToGroup("Other", "remove-annotations");
|
||||
addEndpointToGroup("Other", "compare");
|
||||
addEndpointToGroup("Other", "add-page-numbers");
|
||||
addEndpointToGroup("Other", "auto-rename");
|
||||
addEndpointToGroup("Other", "get-info-on-pdf");
|
||||
addEndpointToGroup("Other", "show-javascript");
|
||||
addEndpointToGroup("Other", "remove-image-pdf");
|
||||
|
||||
// CLI
|
||||
addEndpointToGroup("CLI", "compress-pdf");
|
||||
addEndpointToGroup("CLI", "extract-image-scans");
|
||||
addEndpointToGroup("CLI", "repair");
|
||||
addEndpointToGroup("CLI", "pdf-to-pdfa");
|
||||
addEndpointToGroup("CLI", "file-to-pdf");
|
||||
addEndpointToGroup("CLI", "pdf-to-word");
|
||||
addEndpointToGroup("CLI", "pdf-to-presentation");
|
||||
addEndpointToGroup("CLI", "pdf-to-html");
|
||||
addEndpointToGroup("CLI", "pdf-to-xml");
|
||||
addEndpointToGroup("CLI", "ocr-pdf");
|
||||
addEndpointToGroup("CLI", "html-to-pdf");
|
||||
addEndpointToGroup("CLI", "url-to-pdf");
|
||||
addEndpointToGroup("CLI", "pdf-to-rtf");
|
||||
|
||||
// python
|
||||
addEndpointToGroup("Python", "extract-image-scans");
|
||||
addEndpointToGroup("Python", "html-to-pdf");
|
||||
addEndpointToGroup("Python", "url-to-pdf");
|
||||
addEndpointToGroup("Python", "file-to-pdf");
|
||||
|
||||
// openCV
|
||||
addEndpointToGroup("OpenCV", "extract-image-scans");
|
||||
|
||||
// LibreOffice
|
||||
addEndpointToGroup("LibreOffice", "file-to-pdf");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-word");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-presentation");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-rtf");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-html");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-xml");
|
||||
addEndpointToGroup("LibreOffice", "pdf-to-pdfa");
|
||||
|
||||
// Unoconvert
|
||||
addEndpointToGroup("Unoconvert", "file-to-pdf");
|
||||
|
||||
addEndpointToGroup("tesseract", "ocr-pdf");
|
||||
|
||||
// Java
|
||||
addEndpointToGroup("Java", "merge-pdfs");
|
||||
addEndpointToGroup("Java", "remove-pages");
|
||||
addEndpointToGroup("Java", "split-pdfs");
|
||||
addEndpointToGroup("Java", "pdf-organizer");
|
||||
addEndpointToGroup("Java", "rotate-pdf");
|
||||
addEndpointToGroup("Java", "pdf-to-img");
|
||||
addEndpointToGroup("Java", "img-to-pdf");
|
||||
addEndpointToGroup("Java", "add-password");
|
||||
addEndpointToGroup("Java", "remove-password");
|
||||
addEndpointToGroup("Java", "change-permissions");
|
||||
addEndpointToGroup("Java", "add-watermark");
|
||||
addEndpointToGroup("Java", "add-image");
|
||||
addEndpointToGroup("Java", "extract-images");
|
||||
addEndpointToGroup("Java", "change-metadata");
|
||||
addEndpointToGroup("Java", "cert-sign");
|
||||
addEndpointToGroup("Java", "remove-cert-sign");
|
||||
addEndpointToGroup("Java", "multi-page-layout");
|
||||
addEndpointToGroup("Java", "scale-pages");
|
||||
addEndpointToGroup("Java", "add-page-numbers");
|
||||
addEndpointToGroup("Java", "auto-rename");
|
||||
addEndpointToGroup("Java", "auto-split-pdf");
|
||||
addEndpointToGroup("Java", "sanitize-pdf");
|
||||
addEndpointToGroup("Java", "crop");
|
||||
addEndpointToGroup("Java", "get-info-on-pdf");
|
||||
addEndpointToGroup("Java", "extract-page");
|
||||
addEndpointToGroup("Java", "pdf-to-single-page");
|
||||
addEndpointToGroup("Java", "markdown-to-pdf");
|
||||
addEndpointToGroup("Java", "show-javascript");
|
||||
addEndpointToGroup("Java", "auto-redact");
|
||||
addEndpointToGroup("Java", "redact");
|
||||
addEndpointToGroup("Java", "pdf-to-csv");
|
||||
addEndpointToGroup("Java", "split-by-size-or-count");
|
||||
addEndpointToGroup("Java", "overlay-pdf");
|
||||
addEndpointToGroup("Java", "split-pdf-by-sections");
|
||||
addEndpointToGroup("Java", REMOVE_BLANKS);
|
||||
addEndpointToGroup("Java", "pdf-to-text");
|
||||
addEndpointToGroup("Java", "remove-image-pdf");
|
||||
addEndpointToGroup("Java", "pdf-to-markdown");
|
||||
|
||||
// Javascript
|
||||
addEndpointToGroup("Javascript", "pdf-organizer");
|
||||
addEndpointToGroup("Javascript", "sign");
|
||||
addEndpointToGroup("Javascript", "compare");
|
||||
addEndpointToGroup("Javascript", "adjust-contrast");
|
||||
|
||||
// qpdf dependent endpoints
|
||||
addEndpointToGroup("qpdf", "repair");
|
||||
|
||||
// Weasyprint dependent endpoints
|
||||
addEndpointToGroup("Weasyprint", "html-to-pdf");
|
||||
addEndpointToGroup("Weasyprint", "url-to-pdf");
|
||||
addEndpointToGroup("Weasyprint", "markdown-to-pdf");
|
||||
|
||||
// Pdftohtml dependent endpoints
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-html");
|
||||
addEndpointToGroup("Pdftohtml", "pdf-to-markdown");
|
||||
}
|
||||
|
||||
private void processEnvironmentConfigs() {
|
||||
if (applicationProperties != null && applicationProperties.getEndpoints() != null) {
|
||||
List<String> endpointsToRemove = applicationProperties.getEndpoints().getToRemove();
|
||||
List<String> groupsToRemove = applicationProperties.getEndpoints().getGroupsToRemove();
|
||||
|
||||
if (endpointsToRemove != null) {
|
||||
for (String endpoint : endpointsToRemove) {
|
||||
disableEndpoint(endpoint.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if (groupsToRemove != null) {
|
||||
for (String group : groupsToRemove) {
|
||||
disableGroup(group.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!runningProOrHigher) {
|
||||
disableGroup("enterprise");
|
||||
}
|
||||
|
||||
if (!applicationProperties.getSystem().getEnableUrlToPDF()) {
|
||||
disableEndpoint("url-to-pdf");
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getEndpointsForGroup(String group) {
|
||||
return endpointGroups.getOrDefault(group, new HashSet<>());
|
||||
}
|
||||
}
|
@ -209,4 +209,4 @@ public class EndpointInspector implements ApplicationListener<ContextRefreshedEv
|
||||
}
|
||||
logger.info("=== END: All discovered GET endpoints ===");
|
||||
}
|
||||
}
|
||||
}
|
@ -8,14 +8,13 @@ import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.SPDF.service.EndpointConfigurationService;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class EndpointInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final EndpointConfigurationService endpointConfigurationService;
|
||||
private final EndpointConfiguration endpointConfiguration;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(
|
||||
@ -38,10 +37,10 @@ public class EndpointInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
|
||||
log.debug("Request endpoint: {}", requestEndpoint);
|
||||
isEnabled = endpointConfigurationService.isEndpointEnabled(requestEndpoint);
|
||||
isEnabled = endpointConfiguration.isEndpointEnabled(requestEndpoint);
|
||||
log.debug("Is endpoint enabled: {}", isEnabled);
|
||||
} else {
|
||||
isEnabled = endpointConfigurationService.isEndpointEnabled(requestURI);
|
||||
isEnabled = endpointConfiguration.isEndpointEnabled(requestURI);
|
||||
}
|
||||
|
||||
if (!isEnabled) {
|
||||
@ -50,4 +49,4 @@ public class EndpointInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -13,21 +13,20 @@ import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.SPDF.service.EndpointConfigurationService;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class ExternalAppDepConfig {
|
||||
|
||||
private final EndpointConfigurationService endpointConfigurationService;
|
||||
private final EndpointConfiguration endpointConfiguration;
|
||||
|
||||
private final String weasyprintPath;
|
||||
private final String unoconvPath;
|
||||
private final Map<String, List<String>> commandToGroupMapping;
|
||||
|
||||
public ExternalAppDepConfig(
|
||||
EndpointConfigurationService endpointConfigurationService, RuntimePathConfig runtimePathConfig) {
|
||||
this.endpointConfigurationService = endpointConfigurationService;
|
||||
EndpointConfiguration endpointConfiguration, RuntimePathConfig runtimePathConfig) {
|
||||
this.endpointConfiguration = endpointConfiguration;
|
||||
weasyprintPath = runtimePathConfig.getWeasyPrintPath();
|
||||
unoconvPath = runtimePathConfig.getUnoConvertPath();
|
||||
|
||||
@ -63,7 +62,7 @@ public class ExternalAppDepConfig {
|
||||
}
|
||||
|
||||
private List<String> getAffectedFeatures(String group) {
|
||||
return endpointConfigurationService.getEndpointsForGroup(group).stream()
|
||||
return endpointConfiguration.getEndpointsForGroup(group).stream()
|
||||
.map(endpoint -> formatEndpointAsFeature(endpoint))
|
||||
.toList();
|
||||
}
|
||||
@ -94,7 +93,7 @@ public class ExternalAppDepConfig {
|
||||
if (affectedGroups != null) {
|
||||
for (String group : affectedGroups) {
|
||||
List<String> affectedFeatures = getAffectedFeatures(group);
|
||||
endpointConfigurationService.disableGroup(group);
|
||||
endpointConfiguration.disableGroup(group);
|
||||
log.warn(
|
||||
"Missing dependency: {} - Disabling group: {} (Affected features: {})",
|
||||
command,
|
||||
@ -121,8 +120,8 @@ public class ExternalAppDepConfig {
|
||||
if (!pythonAvailable) {
|
||||
List<String> pythonFeatures = getAffectedFeatures("Python");
|
||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||
endpointConfigurationService.disableGroup("Python");
|
||||
endpointConfigurationService.disableGroup("OpenCV");
|
||||
endpointConfiguration.disableGroup("Python");
|
||||
endpointConfiguration.disableGroup("OpenCV");
|
||||
log.warn(
|
||||
"Missing dependency: Python - Disabling Python features: {} and OpenCV features: {}",
|
||||
String.join(", ", pythonFeatures),
|
||||
@ -140,20 +139,20 @@ public class ExternalAppDepConfig {
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode != 0) {
|
||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||
endpointConfigurationService.disableGroup("OpenCV");
|
||||
endpointConfiguration.disableGroup("OpenCV");
|
||||
log.warn(
|
||||
"OpenCV not available in Python - Disabling OpenCV features: {}",
|
||||
String.join(", ", openCVFeatures));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
List<String> openCVFeatures = getAffectedFeatures("OpenCV");
|
||||
endpointConfigurationService.disableGroup("OpenCV");
|
||||
endpointConfiguration.disableGroup("OpenCV");
|
||||
log.warn(
|
||||
"Error checking OpenCV: {} - Disabling OpenCV features: {}",
|
||||
e.getMessage(),
|
||||
String.join(", ", openCVFeatures));
|
||||
}
|
||||
}
|
||||
endpointConfigurationService.logDisabledEndpointsSummary();
|
||||
endpointConfiguration.logDisabledEndpointsSummary();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
// package stirling.software.SPDF.config.fingerprint;
|
||||
//
|
||||
// import java.security.MessageDigest;
|
||||
// import java.security.NoSuchAlgorithmException;
|
||||
//
|
||||
// import org.springframework.stereotype.Component;
|
||||
//
|
||||
// import jakarta.servlet.http.HttpServletRequest;
|
||||
//
|
||||
// @Component
|
||||
// public class FingerprintGenerator {
|
||||
//
|
||||
// public String generateFingerprint(HttpServletRequest request) {
|
||||
// if (request == null) {
|
||||
// return "";
|
||||
// }
|
||||
// StringBuilder fingerprintBuilder = new StringBuilder();
|
||||
//
|
||||
// // Add IP address
|
||||
// fingerprintBuilder.append(request.getRemoteAddr());
|
||||
//
|
||||
// // Add X-Forwarded-For header if present (for clients behind proxies)
|
||||
// String forwardedFor = request.getHeader("X-Forwarded-For");
|
||||
// if (forwardedFor != null) {
|
||||
// fingerprintBuilder.append(forwardedFor);
|
||||
// }
|
||||
//
|
||||
// // Add User-Agent
|
||||
// String userAgent = request.getHeader("User-Agent");
|
||||
// if (userAgent != null) {
|
||||
// fingerprintBuilder.append(userAgent);
|
||||
// }
|
||||
//
|
||||
// // Add Accept-Language header
|
||||
// String acceptLanguage = request.getHeader("Accept-Language");
|
||||
// if (acceptLanguage != null) {
|
||||
// fingerprintBuilder.append(acceptLanguage);
|
||||
// }
|
||||
//
|
||||
// // Add Accept header
|
||||
// String accept = request.getHeader("Accept");
|
||||
// if (accept != null) {
|
||||
// fingerprintBuilder.append(accept);
|
||||
// }
|
||||
//
|
||||
// // Add Connection header
|
||||
// String connection = request.getHeader("Connection");
|
||||
// if (connection != null) {
|
||||
// fingerprintBuilder.append(connection);
|
||||
// }
|
||||
//
|
||||
// // Add server port
|
||||
// fingerprintBuilder.append(request.getServerPort());
|
||||
//
|
||||
// // Add secure flag
|
||||
// fingerprintBuilder.append(request.isSecure());
|
||||
//
|
||||
// // Generate a hash of the fingerprint
|
||||
// return generateHash(fingerprintBuilder.toString());
|
||||
// }
|
||||
//
|
||||
// private String generateHash(String input) {
|
||||
// try {
|
||||
// MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
// byte[] hash = digest.digest(input.getBytes());
|
||||
// StringBuilder hexString = new StringBuilder();
|
||||
// for (byte b : hash) {
|
||||
// String hex = Integer.toHexString(0xff & b);
|
||||
// if (hex.length() == 1) hexString.append('0');
|
||||
// hexString.append(hex);
|
||||
// }
|
||||
// return hexString.toString();
|
||||
// } catch (NoSuchAlgorithmException e) {
|
||||
// throw new RuntimeException("Failed to generate fingerprint hash", e);
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -245,4 +245,4 @@ public class MergeController {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import stirling.software.SPDF.service.EndpointConfigurationService;
|
||||
import stirling.software.SPDF.config.EndpointConfiguration;
|
||||
import stirling.software.common.configuration.InstallationPathConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
@ -29,7 +29,7 @@ import stirling.software.common.util.GeneralUtils;
|
||||
public class SettingsController {
|
||||
|
||||
private final ApplicationProperties applicationProperties;
|
||||
private final EndpointConfigurationService endpointConfigurationService;
|
||||
private final EndpointConfiguration endpointConfiguration;
|
||||
|
||||
@PostMapping("/update-enable-analytics")
|
||||
@Hidden
|
||||
@ -48,6 +48,6 @@ public class SettingsController {
|
||||
@GetMapping("/get-endpoints-status")
|
||||
@Hidden
|
||||
public ResponseEntity<Map<String, Boolean>> getDisabledEndpoints() {
|
||||
return ResponseEntity.ok(endpointConfigurationService.getEndpointStatuses());
|
||||
return ResponseEntity.ok(endpointConfiguration.getEndpointStatuses());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
package stirling.software.SPDF.controller.api.converters;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.github.pixee.security.Filenames;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import stirling.software.common.configuration.RuntimePathConfig;
|
||||
import stirling.software.common.model.api.converters.EmlToPdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.EmlToPdf;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/convert")
|
||||
@Tag(name = "Convert", description = "Convert APIs")
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class ConvertEmlToPDF {
|
||||
|
||||
private final CustomPDFDocumentFactory pdfDocumentFactory;
|
||||
private final RuntimePathConfig runtimePathConfig;
|
||||
|
||||
@PostMapping(consumes = "multipart/form-data", value = "/eml/pdf")
|
||||
@Operation(
|
||||
summary = "Convert EML to PDF",
|
||||
description =
|
||||
"This endpoint converts EML (email) files to PDF format with extensive"
|
||||
+ " customization options. Features include font settings, image constraints, display modes, attachment handling,"
|
||||
+ " and HTML debug output. Input: EML file, Output: PDF"
|
||||
+ " or HTML file. Type: SISO")
|
||||
public ResponseEntity<byte[]> convertEmlToPdf(@ModelAttribute EmlToPdfRequest request) {
|
||||
|
||||
MultipartFile inputFile = request.getFileInput();
|
||||
String originalFilename = inputFile.getOriginalFilename();
|
||||
|
||||
// Validate input
|
||||
if (inputFile.isEmpty()) {
|
||||
log.error("No file provided for EML to PDF conversion.");
|
||||
return ResponseEntity.badRequest()
|
||||
.body("No file provided".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
if (originalFilename == null || originalFilename.trim().isEmpty()) {
|
||||
log.error("Filename is null or empty.");
|
||||
return ResponseEntity.badRequest()
|
||||
.body("Please provide a valid filename".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
// Validate file type - support EML
|
||||
String lowerFilename = originalFilename.toLowerCase();
|
||||
if (!lowerFilename.endsWith(".eml")) {
|
||||
log.error("Invalid file type for EML to PDF: {}", originalFilename);
|
||||
return ResponseEntity.badRequest()
|
||||
.body("Please upload a valid EML file".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
String baseFilename = Filenames.toSimpleFileName(originalFilename); // Use Filenames utility
|
||||
|
||||
try {
|
||||
byte[] fileBytes = inputFile.getBytes();
|
||||
|
||||
if (request.isDownloadHtml()) {
|
||||
try {
|
||||
String htmlContent = EmlToPdf.convertEmlToHtml(fileBytes, request);
|
||||
log.info("Successfully converted EML to HTML: {}", originalFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
htmlContent.getBytes(StandardCharsets.UTF_8),
|
||||
baseFilename + ".html",
|
||||
MediaType.TEXT_HTML);
|
||||
} catch (IOException | IllegalArgumentException e) {
|
||||
log.error("HTML conversion failed for {}", originalFilename, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(
|
||||
("HTML conversion failed: " + e.getMessage())
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert EML to PDF with enhanced options
|
||||
try {
|
||||
byte[] pdfBytes =
|
||||
EmlToPdf.convertEmlToPdf(
|
||||
runtimePathConfig.getWeasyPrintPath(), // Use configured WeasyPrint path
|
||||
request,
|
||||
fileBytes,
|
||||
originalFilename,
|
||||
false,
|
||||
pdfDocumentFactory);
|
||||
|
||||
if (pdfBytes == null || pdfBytes.length == 0) {
|
||||
log.error("PDF conversion failed - empty output for {}", originalFilename);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(
|
||||
"PDF conversion failed - empty output"
|
||||
.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
log.info("Successfully converted EML to PDF: {}", originalFilename);
|
||||
return WebResponseUtils.bytesToWebResponse(
|
||||
pdfBytes, baseFilename + ".pdf", MediaType.APPLICATION_PDF);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
log.error("EML to PDF conversion was interrupted for {}", originalFilename, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("Conversion was interrupted".getBytes(StandardCharsets.UTF_8));
|
||||
} catch (IllegalArgumentException e) {
|
||||
String errorMessage = buildErrorMessage(e, originalFilename);
|
||||
log.error("EML to PDF conversion failed for {}: {}", originalFilename, errorMessage, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
||||
} catch (RuntimeException e) {
|
||||
String errorMessage = buildErrorMessage(e, originalFilename);
|
||||
log.error("EML to PDF conversion failed for {}: {}", originalFilename, errorMessage, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body(errorMessage.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("File processing error for EML to PDF: {}", originalFilename, e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
.body("File processing error".getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
private static @NotNull String buildErrorMessage(Exception e, String originalFilename) {
|
||||
String errorMessage;
|
||||
if (e.getMessage() != null && e.getMessage().contains("Invalid EML")) {
|
||||
errorMessage =
|
||||
"Invalid EML file format. Please ensure you've uploaded a valid email"
|
||||
+ " file ("
|
||||
+ originalFilename
|
||||
+ ").";
|
||||
} else if (e.getMessage() != null && e.getMessage().contains("WeasyPrint")) {
|
||||
errorMessage =
|
||||
"PDF generation failed for "
|
||||
+ originalFilename
|
||||
+ ". This may be due to complex email formatting.";
|
||||
} else {
|
||||
errorMessage = "Conversion failed for " + originalFilename + ": " + e.getMessage();
|
||||
}
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
@ -49,13 +49,13 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import stirling.software.SPDF.config.EndpointConfiguration;
|
||||
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
import stirling.software.common.util.ProcessExecutor;
|
||||
import stirling.software.common.util.ProcessExecutor.ProcessExecutorResult;
|
||||
import stirling.software.common.util.WebResponseUtils;
|
||||
import stirling.software.SPDF.service.EndpointConfigurationService;
|
||||
import stirling.software.SPDF.model.api.misc.OptimizePdfRequest;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/misc")
|
||||
@ -68,9 +68,9 @@ public class CompressController {
|
||||
|
||||
public CompressController(
|
||||
CustomPDFDocumentFactory pdfDocumentFactory,
|
||||
EndpointConfigurationService endpointConfigurationService) {
|
||||
EndpointConfiguration endpointConfiguration) {
|
||||
this.pdfDocumentFactory = pdfDocumentFactory;
|
||||
this.qpdfEnabled = endpointConfigurationService.isGroupEnabled("qpdf");
|
||||
this.qpdfEnabled = endpointConfiguration.isGroupEnabled("qpdf");
|
||||
}
|
||||
|
||||
@Data
|
||||
@ -875,4 +875,4 @@ public class CompressController {
|
||||
}
|
||||
return Math.min(9, currentLevel + 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -121,4 +121,11 @@ public class ConverterWebController {
|
||||
model.addAttribute("currentPage", "pdf-to-pdfa");
|
||||
return "convert/pdf-to-pdfa";
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/eml-to-pdf")
|
||||
@Hidden
|
||||
public String convertEmlToPdfForm(Model model) {
|
||||
model.addAttribute("currentPage", "eml-to-pdf");
|
||||
return "convert/eml-to-pdf";
|
||||
}
|
||||
}
|
@ -350,4 +350,4 @@ public class GeneralWebController {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -39,4 +39,4 @@ public class MergePdfsRequest extends MultiplePDFFiles {
|
||||
requiredMode = Schema.RequiredMode.NOT_REQUIRED,
|
||||
defaultValue = "false")
|
||||
private boolean generateToc = false;
|
||||
}
|
||||
}
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML إلى PDF
|
||||
home.HTMLToPDF.desc=يحول أي ملف HTML أو ملف مضغوط يحتوي
|
||||
HTMLToPDF.tags=لغة الترميز,محتوى الويب,تحويل,تحويل
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown إلى PDF
|
||||
home.MarkdownToPDF.desc=يحول أي ملف Markdown إلى PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML-dən PDF-ə
|
||||
home.HTMLToPDF.desc=Hər hansı HTML faylını və ya ZİP-i PDF-ə çevirir
|
||||
HTMLToPDF.tags=işarələmə,veb-məzmun,çevirmə,dəyişmə
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown-dan PDF-ə
|
||||
home.MarkdownToPDF.desc=Hər hansı Markdown faylını PDF-ə çevirir
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML към PDF
|
||||
home.HTMLToPDF.desc=Преобразува всеки HTML файл или архив към PDF
|
||||
HTMLToPDF.tags=маркиране,уеб-съдържание,трансформация,преобразуване
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown към PDF
|
||||
home.MarkdownToPDF.desc=Преобразува всеки Markdown файл към PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML a PDF
|
||||
home.HTMLToPDF.desc=Converteix qualsevol fitxer HTML o arxiu comprimit a PDF
|
||||
HTMLToPDF.tags=marcatge,contingut web,transformació,convertir
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown a PDF
|
||||
home.MarkdownToPDF.desc=Converteix qualsevol fitxer Markdown a PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML na PDF
|
||||
home.HTMLToPDF.desc=Převádí libovolný HTML soubor nebo zip na PDF
|
||||
HTMLToPDF.tags=značkování,webový-obsah,transformace,převod
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown na PDF
|
||||
home.MarkdownToPDF.desc=Převádí libovolný Markdown soubor na PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML til PDF
|
||||
home.HTMLToPDF.desc=Konverterer enhver HTML-fil eller zip til PDF
|
||||
HTMLToPDF.tags=markup,webindhold,transformation,konvertér
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown til PDF
|
||||
home.MarkdownToPDF.desc=Konverterer enhver Markdown-fil til PDF
|
||||
|
@ -621,6 +621,22 @@ home.HTMLToPDF.title=HTML zu PDF
|
||||
home.HTMLToPDF.desc=Konvertiert jede HTML-Datei oder Zip-Archiv zu PDF
|
||||
HTMLToPDF.tags=markup,webinhalt,transformation,konvertierung
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown zu PDF
|
||||
home.MarkdownToPDF.desc=Konvertiert jede Markdown-Datei zu PDF
|
||||
|
@ -621,6 +621,22 @@ home.HTMLToPDF.title=HTML σε PDF
|
||||
home.HTMLToPDF.desc=Μετατρέπει οποιοδήποτε αρχείο HTML ή zip σε PDF
|
||||
HTMLToPDF.tags=markup,περιεχόμενο-web,μετατροπή,μετατροπή
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown σε PDF
|
||||
home.MarkdownToPDF.desc=Μετατρέπει οποιοδήποτε αρχείο Markdown σε PDF
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1012,6 +1012,905 @@ merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.generateToc=Generate table of contents in the merged file?
|
||||
|
||||
|
||||
#################
|
||||
# Analytics #
|
||||
#################
|
||||
analytics.title=Do you want make Stirling PDF better?
|
||||
analytics.paragraph1=Stirling PDF has opt in analytics to help us improve the product. We do not track any personal information or file contents.
|
||||
analytics.paragraph2=Please consider enabling analytics to help Stirling-PDF grow and to allow us to understand our users better.
|
||||
analytics.enable=Enable analytics
|
||||
analytics.disable=Disable analytics
|
||||
analytics.settings=You can change the settings for analytics in the config/settings.yml file
|
||||
|
||||
|
||||
#############
|
||||
# NAVBAR #
|
||||
#############
|
||||
navbar.favorite=Favorites
|
||||
navbar.recent=New and recently updated
|
||||
navbar.darkmode=Dark Mode
|
||||
navbar.language=Languages
|
||||
navbar.settings=Settings
|
||||
navbar.allTools=Tools
|
||||
navbar.multiTool=Multi Tool
|
||||
navbar.search=Search
|
||||
navbar.sections.organize=Organize
|
||||
navbar.sections.convertTo=Convert to PDF
|
||||
navbar.sections.convertFrom=Convert from PDF
|
||||
navbar.sections.security=Sign & Security
|
||||
navbar.sections.advance=Advanced
|
||||
navbar.sections.edit=View & Edit
|
||||
navbar.sections.popular=Popular
|
||||
|
||||
#############
|
||||
# SETTINGS #
|
||||
#############
|
||||
settings.title=Settings
|
||||
settings.update=Update available
|
||||
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
||||
settings.appVersion=App Version:
|
||||
settings.downloadOption.title=Choose download option (For single file non zip downloads):
|
||||
settings.downloadOption.1=Open in same window
|
||||
settings.downloadOption.2=Open in new window
|
||||
settings.downloadOption.3=Download file
|
||||
settings.zipThreshold=Zip files when the number of downloaded files exceeds
|
||||
settings.signOut=Sign Out
|
||||
settings.accountSettings=Account Settings
|
||||
settings.bored.help=Enables easter egg game
|
||||
settings.cacheInputs.name=Save form inputs
|
||||
settings.cacheInputs.help=Enable to store previously used inputs for future runs
|
||||
|
||||
changeCreds.title=Change Credentials
|
||||
changeCreds.header=Update Your Account Details
|
||||
changeCreds.changePassword=You are using default login credentials. Please enter a new password
|
||||
changeCreds.newUsername=New Username
|
||||
changeCreds.oldPassword=Current Password
|
||||
changeCreds.newPassword=New Password
|
||||
changeCreds.confirmNewPassword=Confirm New Password
|
||||
changeCreds.submit=Submit Changes
|
||||
|
||||
|
||||
|
||||
account.title=Account Settings
|
||||
account.accountSettings=Account Settings
|
||||
account.adminSettings=Admin Settings - View and Add Users
|
||||
account.userControlSettings=User Control Settings
|
||||
account.changeUsername=Change Username
|
||||
account.newUsername=New Username
|
||||
account.password=Confirmation Password
|
||||
account.oldPassword=Old password
|
||||
account.newPassword=New Password
|
||||
account.changePassword=Change Password
|
||||
account.confirmNewPassword=Confirm New Password
|
||||
account.signOut=Sign Out
|
||||
account.yourApiKey=Your API Key
|
||||
account.syncTitle=Sync browser settings with Account
|
||||
account.settingsCompare=Settings Comparison:
|
||||
account.property=Property
|
||||
account.webBrowserSettings=Web Browser Setting
|
||||
account.syncToBrowser=Sync Account -> Browser
|
||||
account.syncToAccount=Sync Account <- Browser
|
||||
|
||||
|
||||
adminUserSettings.title=User Control Settings
|
||||
adminUserSettings.header=Admin User Control Settings
|
||||
adminUserSettings.admin=Admin
|
||||
adminUserSettings.user=User
|
||||
adminUserSettings.addUser=Add New User
|
||||
adminUserSettings.deleteUser=Delete User
|
||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
||||
adminUserSettings.confirmChangeUserStatus=Should the user be disabled/enabled?
|
||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
||||
adminUserSettings.roles=Roles
|
||||
adminUserSettings.role=Role
|
||||
adminUserSettings.actions=Actions
|
||||
adminUserSettings.apiUser=Limited API User
|
||||
adminUserSettings.extraApiUser=Additional Limited API User
|
||||
adminUserSettings.webOnlyUser=Web Only User
|
||||
adminUserSettings.demoUser=Demo User (No custom settings)
|
||||
adminUserSettings.internalApiUser=Internal API User
|
||||
adminUserSettings.forceChange=Force user to change password on login
|
||||
adminUserSettings.submit=Save User
|
||||
adminUserSettings.changeUserRole=Change User's Role
|
||||
adminUserSettings.authenticated=Authenticated
|
||||
adminUserSettings.editOwnProfil=Edit own profile
|
||||
adminUserSettings.enabledUser=enabled user
|
||||
adminUserSettings.disabledUser=disabled user
|
||||
adminUserSettings.activeUsers=Active Users:
|
||||
adminUserSettings.disabledUsers=Disabled Users:
|
||||
adminUserSettings.totalUsers=Total Users:
|
||||
adminUserSettings.lastRequest=Last Request
|
||||
adminUserSettings.usage=View Usage
|
||||
|
||||
endpointStatistics.title=Endpoint Statistics
|
||||
endpointStatistics.header=Endpoint Statistics
|
||||
endpointStatistics.top10=Top 10
|
||||
endpointStatistics.top20=Top 20
|
||||
endpointStatistics.all=All
|
||||
endpointStatistics.refresh=Refresh
|
||||
endpointStatistics.includeHomepage=Include Homepage ('/')
|
||||
endpointStatistics.includeLoginPage=Include Login Page ('/login')
|
||||
endpointStatistics.totalEndpoints=Total Endpoints
|
||||
endpointStatistics.totalVisits=Total Visits
|
||||
endpointStatistics.showing=Showing
|
||||
endpointStatistics.selectedVisits=Selected Visits
|
||||
endpointStatistics.endpoint=Endpoint
|
||||
endpointStatistics.visits=Visits
|
||||
endpointStatistics.percentage=Percentage
|
||||
endpointStatistics.loading=Loading...
|
||||
endpointStatistics.failedToLoad=Failed to load endpoint data. Please try refreshing.
|
||||
endpointStatistics.home=Home
|
||||
endpointStatistics.login=Login
|
||||
endpointStatistics.top=Top
|
||||
endpointStatistics.numberOfVisits=Number of Visits
|
||||
endpointStatistics.visitsTooltip=Visits: {0} ({1}% of total)
|
||||
endpointStatistics.retry=Retry
|
||||
|
||||
database.title=Database Import/Export
|
||||
database.header=Database Import/Export
|
||||
database.fileName=File Name
|
||||
database.creationDate=Creation Date
|
||||
database.fileSize=File Size
|
||||
database.deleteBackupFile=Delete Backup File
|
||||
database.importBackupFile=Import Backup File
|
||||
database.createBackupFile=Create Backup File
|
||||
database.downloadBackupFile=Download Backup File
|
||||
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||
database.submit=Import Backup
|
||||
database.importIntoDatabaseSuccessed=Import into database successed
|
||||
database.backupCreated=Database backup successful
|
||||
database.fileNotFound=File not Found
|
||||
database.fileNullOrEmpty=File must not be null or empty
|
||||
database.failedImportFile=Failed Import File
|
||||
database.notSupported=This function is not available for your database connection.
|
||||
|
||||
session.expired=Your session has expired. Please refresh the page and try again.
|
||||
session.refreshPage=Refresh Page
|
||||
|
||||
#############
|
||||
# HOME-PAGE #
|
||||
#############
|
||||
home.desc=Your locally hosted one-stop-shop for all your PDF needs.
|
||||
home.searchBar=Search for features...
|
||||
|
||||
|
||||
home.viewPdf.title=View/Edit PDF
|
||||
home.viewPdf.desc=View, annotate, draw, add text or images
|
||||
viewPdf.tags=view,read,annotate,text,image,highlight,edit
|
||||
|
||||
home.setFavorites=Set Favourites
|
||||
home.hideFavorites=Hide Favourites
|
||||
home.showFavorites=Show Favourites
|
||||
home.legacyHomepage=Old homepage
|
||||
home.newHomePage=Try our new homepage!
|
||||
home.alphabetical=Alphabetical
|
||||
home.globalPopularity=Global Popularity
|
||||
home.sortBy=Sort by:
|
||||
|
||||
home.multiTool.title=PDF Multi Tool
|
||||
home.multiTool.desc=Merge, Rotate, Rearrange, Split, and Remove pages
|
||||
multiTool.tags=Multi Tool,Multi operation,UI,click drag,front end,client side,interactive,intractable,move,delete,migrate,divide
|
||||
|
||||
home.merge.title=Merge
|
||||
home.merge.desc=Easily merge multiple PDFs into one.
|
||||
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
|
||||
|
||||
home.rotate.title=Rotate
|
||||
home.rotate.desc=Easily rotate your PDFs.
|
||||
rotate.tags=server side
|
||||
|
||||
|
||||
home.imageToPdf.title=Image to PDF
|
||||
home.imageToPdf.desc=Convert a image (PNG, JPEG, GIF) to PDF.
|
||||
imageToPdf.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfToImage.title=PDF to Image
|
||||
home.pdfToImage.desc=Convert a PDF to a image. (PNG, JPEG, GIF)
|
||||
pdfToImage.tags=conversion,img,jpg,picture,photo
|
||||
|
||||
home.pdfOrganiser.title=Organize
|
||||
home.pdfOrganiser.desc=Remove/Rearrange pages in any order
|
||||
pdfOrganiser.tags=duplex,even,odd,sort,move
|
||||
|
||||
|
||||
home.addImage.title=Add image
|
||||
home.addImage.desc=Adds a image onto a set location on the PDF
|
||||
addImage.tags=img,jpg,picture,photo
|
||||
|
||||
home.watermark.title=Add Watermark
|
||||
home.watermark.desc=Add a custom watermark to your PDF document.
|
||||
watermark.tags=Text,repeating,label,own,copyright,trademark,img,jpg,picture,photo
|
||||
|
||||
home.permissions.title=Change Permissions
|
||||
home.permissions.desc=Change the permissions of your PDF document
|
||||
permissions.tags=read,write,edit,print
|
||||
|
||||
|
||||
home.removePages.title=Remove
|
||||
home.removePages.desc=Delete unwanted pages from your PDF document.
|
||||
removePages.tags=Remove pages,delete pages
|
||||
|
||||
home.addPassword.title=Add Password
|
||||
home.addPassword.desc=Encrypt your PDF document with a password.
|
||||
addPassword.tags=secure,security
|
||||
|
||||
home.removePassword.title=Remove Password
|
||||
home.removePassword.desc=Remove password protection from your PDF document.
|
||||
removePassword.tags=secure,Decrypt,security,unpassword,delete password
|
||||
|
||||
home.compressPdfs.title=Compress
|
||||
home.compressPdfs.desc=Compress PDFs to reduce their file size.
|
||||
compressPdfs.tags=squish,small,tiny
|
||||
|
||||
home.unlockPDFForms.title=Unlock PDF Forms
|
||||
home.unlockPDFForms.desc=Remove read-only property of form fields in a PDF document.
|
||||
unlockPDFForms.tags=remove,delete,form,field,readonly
|
||||
|
||||
home.changeMetadata.title=Change Metadata
|
||||
home.changeMetadata.desc=Change/Remove/Add metadata from a PDF document
|
||||
changeMetadata.tags=Title,author,date,creation,time,publisher,producer,stats
|
||||
|
||||
home.fileToPDF.title=Convert file to PDF
|
||||
home.fileToPDF.desc=Convert nearly any file to PDF (DOCX, PNG, XLS, PPT, TXT and more)
|
||||
fileToPDF.tags=transformation,format,document,picture,slide,text,conversion,office,docs,word,excel,powerpoint
|
||||
|
||||
home.ocr.title=OCR / Cleanup scans
|
||||
home.ocr.desc=Cleanup scans and detects text from images within a PDF and re-adds it as text.
|
||||
ocr.tags=recognition,text,image,scan,read,identify,detection,editable
|
||||
|
||||
home.extractImages.title=Extract Images
|
||||
home.extractImages.desc=Extracts all images from a PDF and saves them to zip
|
||||
extractImages.tags=picture,photo,save,archive,zip,capture,grab
|
||||
|
||||
home.pdfToPDFA.title=PDF to PDF/A
|
||||
home.pdfToPDFA.desc=Convert PDF to PDF/A for long-term storage
|
||||
pdfToPDFA.tags=archive,long-term,standard,conversion,storage,preservation
|
||||
|
||||
home.PDFToWord.title=PDF to Word
|
||||
home.PDFToWord.desc=Convert PDF to Word formats (DOC, DOCX and ODT)
|
||||
PDFToWord.tags=doc,docx,odt,word,transformation,format,conversion,office,microsoft,docfile
|
||||
|
||||
home.PDFToPresentation.title=PDF to Presentation
|
||||
home.PDFToPresentation.desc=Convert PDF to Presentation formats (PPT, PPTX and ODP)
|
||||
PDFToPresentation.tags=slides,show,office,microsoft
|
||||
|
||||
home.PDFToText.title=PDF to RTF (Text)
|
||||
home.PDFToText.desc=Convert PDF to Text or RTF format
|
||||
PDFToText.tags=richformat,richtextformat,rich text format
|
||||
|
||||
home.PDFToHTML.title=PDF to HTML
|
||||
home.PDFToHTML.desc=Convert PDF to HTML format
|
||||
PDFToHTML.tags=web content,browser friendly
|
||||
|
||||
|
||||
home.PDFToXML.title=PDF to XML
|
||||
home.PDFToXML.desc=Convert PDF to XML format
|
||||
PDFToXML.tags=data-extraction,structured-content,interop,transformation,convert
|
||||
|
||||
home.ScannerImageSplit.title=Detect/Split Scanned photos
|
||||
home.ScannerImageSplit.desc=Splits multiple photos from within a photo/PDF
|
||||
ScannerImageSplit.tags=separate,auto-detect,scans,multi-photo,organize
|
||||
|
||||
home.sign.title=Sign
|
||||
home.sign.desc=Adds signature to PDF by drawing, text or image
|
||||
sign.tags=authorize,initials,drawn-signature,text-sign,image-signature
|
||||
|
||||
home.flatten.title=Flatten
|
||||
home.flatten.desc=Remove all interactive elements and forms from a PDF
|
||||
flatten.tags=static,deactivate,non-interactive,streamline
|
||||
|
||||
home.repair.title=Repair
|
||||
home.repair.desc=Tries to repair a corrupt/broken PDF
|
||||
repair.tags=fix,restore,correction,recover
|
||||
|
||||
home.removeBlanks.title=Remove Blank pages
|
||||
home.removeBlanks.desc=Detects and removes blank pages from a document
|
||||
removeBlanks.tags=cleanup,streamline,non-content,organize
|
||||
|
||||
home.removeAnnotations.title=Remove Annotations
|
||||
home.removeAnnotations.desc=Removes all comments/annotations from a PDF
|
||||
removeAnnotations.tags=comments,highlight,notes,markup,remove
|
||||
|
||||
home.compare.title=Compare
|
||||
home.compare.desc=Compares and shows the differences between 2 PDF Documents
|
||||
compare.tags=differentiate,contrast,changes,analysis
|
||||
|
||||
home.certSign.title=Sign with Certificate
|
||||
home.certSign.desc=Signs a PDF with a Certificate/Key (PEM/P12)
|
||||
certSign.tags=authenticate,PEM,P12,official,encrypt
|
||||
|
||||
home.removeCertSign.title=Remove Certificate Sign
|
||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
||||
|
||||
home.pageLayout.title=Multi-Page Layout
|
||||
home.pageLayout.desc=Merge multiple pages of a PDF document into a single page
|
||||
pageLayout.tags=merge,composite,single-view,organize
|
||||
|
||||
home.scalePages.title=Adjust page size/scale
|
||||
home.scalePages.desc=Change the size/scale of a page and/or its contents.
|
||||
scalePages.tags=resize,modify,dimension,adapt
|
||||
|
||||
home.pipeline.title=Pipeline
|
||||
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
|
||||
pipeline.tags=automate,sequence,scripted,batch-process
|
||||
|
||||
home.add-page-numbers.title=Add Page Numbers
|
||||
home.add-page-numbers.desc=Add Page numbers throughout a document in a set location
|
||||
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
|
||||
auto-rename.tags=auto-detect,header-based,organize,relabel
|
||||
|
||||
home.adjust-contrast.title=Adjust Colors/Contrast
|
||||
home.adjust-contrast.desc=Adjust Contrast, Saturation and Brightness of a PDF
|
||||
adjust-contrast.tags=color-correction,tune,modify,enhance
|
||||
|
||||
home.crop.title=Crop PDF
|
||||
home.crop.desc=Crop a PDF to reduce its size (maintains text!)
|
||||
crop.tags=trim,shrink,edit,shape
|
||||
|
||||
home.autoSplitPDF.title=Auto Split Pages
|
||||
home.autoSplitPDF.desc=Auto Split Scanned PDF with physical scanned page splitter QR Code
|
||||
autoSplitPDF.tags=QR-based,separate,scan-segment,organize
|
||||
|
||||
home.sanitizePdf.title=Sanitize
|
||||
home.sanitizePdf.desc=Remove scripts and other elements from PDF files
|
||||
sanitizePdf.tags=clean,secure,safe,remove-threats
|
||||
|
||||
home.URLToPDF.title=URL/Website To PDF
|
||||
home.URLToPDF.desc=Converts any http(s)URL to PDF
|
||||
URLToPDF.tags=web-capture,save-page,web-to-doc,archive
|
||||
|
||||
home.HTMLToPDF.title=HTML to PDF
|
||||
home.HTMLToPDF.desc=Converts any HTML file or zip to PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown to PDF
|
||||
home.MarkdownToPDF.desc=Converts any Markdown file to PDF
|
||||
MarkdownToPDF.tags=markup,web-content,transformation,convert,md
|
||||
|
||||
home.PDFToMarkdown.title=PDF to Markdown
|
||||
home.PDFToMarkdown.desc=Converts any PDF to Markdown
|
||||
PDFToMarkdown.tags=markup,web-content,transformation,convert,md
|
||||
|
||||
home.getPdfInfo.title=Get ALL Info on PDF
|
||||
home.getPdfInfo.desc=Grabs any and all information possible on PDFs
|
||||
getPdfInfo.tags=infomation,data,stats,statistics
|
||||
|
||||
|
||||
home.extractPage.title=Extract page(s)
|
||||
home.extractPage.desc=Extracts select pages from PDF
|
||||
extractPage.tags=extract
|
||||
|
||||
|
||||
home.PdfToSinglePage.title=Single Large Page
|
||||
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
|
||||
PdfToSinglePage.tags=single page
|
||||
|
||||
|
||||
home.showJS.title=Show Javascript
|
||||
home.showJS.desc=Searches and displays any JS injected into a PDF
|
||||
showJS.tags=JS
|
||||
|
||||
home.autoRedact.title=Auto Redact
|
||||
home.autoRedact.desc=Auto Redacts(Blacks out) text in a PDF based on input text
|
||||
autoRedact.tags=Redact,Hide,black out,black,marker,hidden
|
||||
|
||||
home.redact.title=Manual Redaction
|
||||
home.redact.desc=Redacts a PDF based on selected text, drawn shapes and/or selected page(s)
|
||||
redact.tags=Redact,Hide,black out,black,marker,hidden,manual
|
||||
|
||||
home.tableExtraxt.title=PDF to CSV
|
||||
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV
|
||||
tableExtraxt.tags=CSV,Table Extraction,extract,convert
|
||||
|
||||
|
||||
home.autoSizeSplitPDF.title=Auto Split by Size/Count
|
||||
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count
|
||||
autoSizeSplitPDF.tags=pdf,split,document,organization
|
||||
|
||||
|
||||
home.overlay-pdfs.title=Overlay PDFs
|
||||
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF
|
||||
overlay-pdfs.tags=Overlay
|
||||
|
||||
home.split-by-sections.title=Split PDF by Sections
|
||||
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections
|
||||
split-by-sections.tags=Section Split, Divide, Customize
|
||||
|
||||
home.AddStampRequest.title=Add Stamp to PDF
|
||||
home.AddStampRequest.desc=Add text or add image stamps at set locations
|
||||
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize
|
||||
|
||||
|
||||
home.removeImagePdf.title=Remove image
|
||||
home.removeImagePdf.desc=Remove image from PDF to reduce file size
|
||||
removeImagePdf.tags=Remove Image,Page operations,Back end,server side
|
||||
|
||||
|
||||
home.splitPdfByChapters.title=Split PDF by Chapters
|
||||
home.splitPdfByChapters.desc=Split a PDF into multiple files based on its chapter structure.
|
||||
splitPdfByChapters.tags=split,chapters,bookmarks,organize
|
||||
|
||||
home.validateSignature.title=Validate PDF Signature
|
||||
home.validateSignature.desc=Verify digital signatures and certificates in PDF documents
|
||||
validateSignature.tags=signature,verify,validate,pdf,certificate,digital signature,Validate Signature,Validate certificate
|
||||
|
||||
#replace-invert-color
|
||||
replace-color.title=Replace-Invert-Color
|
||||
replace-color.header=Replace-Invert Color PDF
|
||||
home.replaceColorPdf.title=Replace and Invert Color
|
||||
home.replaceColorPdf.desc=Replace color for text and background in PDF and invert full color of pdf to reduce file size
|
||||
replaceColorPdf.tags=Replace Color,Page operations,Back end,server side
|
||||
replace-color.selectText.1=Replace or Invert color Options
|
||||
replace-color.selectText.2=Default(Default high contrast colors)
|
||||
replace-color.selectText.3=Custom(Customized colors)
|
||||
replace-color.selectText.4=Full-Invert(Invert all colors)
|
||||
replace-color.selectText.5=High contrast color options
|
||||
replace-color.selectText.6=white text on black background
|
||||
replace-color.selectText.7=Black text on white background
|
||||
replace-color.selectText.8=Yellow text on black background
|
||||
replace-color.selectText.9=Green text on black background
|
||||
replace-color.selectText.10=Choose text Color
|
||||
replace-color.selectText.11=Choose background Color
|
||||
replace-color.submit=Replace
|
||||
|
||||
|
||||
|
||||
###########################
|
||||
# #
|
||||
# WEB PAGES #
|
||||
# #
|
||||
###########################
|
||||
#login
|
||||
login.title=Sign in
|
||||
login.header=Sign in
|
||||
login.signin=Sign in
|
||||
login.rememberme=Remember me
|
||||
login.invalid=Invalid username or password.
|
||||
login.locked=Your account has been locked.
|
||||
login.signinTitle=Please sign in
|
||||
login.ssoSignIn=Login via Single Sign-on
|
||||
login.oAuth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
|
||||
login.oAuth2AdminBlockedUser=Registration or logging in of non-registered users is currently blocked. Please contact the administrator.
|
||||
login.oauth2RequestNotFound=Authorization request not found
|
||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
||||
login.oauth2invalidRequest=Invalid Request
|
||||
login.oauth2AccessDenied=Access Denied
|
||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
||||
login.oauth2InvalidIdToken=Invalid Id Token
|
||||
login.relyingPartyRegistrationNotFound=No relying party registration found
|
||||
login.userIsDisabled=User is deactivated, login is currently blocked with this username. Please contact the administrator.
|
||||
login.alreadyLoggedIn=You are already logged in to
|
||||
login.alreadyLoggedIn2=devices. Please log out of the devices and try again.
|
||||
login.toManySessions=You have too many active sessions
|
||||
login.logoutMessage=You have been logged out.
|
||||
|
||||
#auto-redact
|
||||
autoRedact.title=Auto Redact
|
||||
autoRedact.header=Auto Redact
|
||||
autoRedact.colorLabel=Color
|
||||
autoRedact.textsToRedactLabel=Text to Redact (line-separated)
|
||||
autoRedact.textsToRedactPlaceholder=e.g. \nConfidential \nTop-Secret
|
||||
autoRedact.useRegexLabel=Use Regex
|
||||
autoRedact.wholeWordSearchLabel=Whole Word Search
|
||||
autoRedact.customPaddingLabel=Custom Extra Padding
|
||||
autoRedact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
autoRedact.submitButton=Submit
|
||||
|
||||
#redact
|
||||
redact.title=Manual Redaction
|
||||
redact.header=Manual Redaction
|
||||
redact.submit=Redact
|
||||
redact.textBasedRedaction=Text based Redaction
|
||||
redact.pageBasedRedaction=Page-based Redaction
|
||||
redact.convertPDFToImageLabel=Convert PDF to PDF-Image (Used to remove text behind the box)
|
||||
redact.pageRedactionNumbers.title=Pages
|
||||
redact.pageRedactionNumbers.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
|
||||
redact.redactionColor.title=Redaction Color
|
||||
redact.export=Export
|
||||
redact.upload=Upload
|
||||
redact.boxRedaction=Box draw redaction
|
||||
redact.zoom=Zoom
|
||||
redact.zoomIn=Zoom in
|
||||
redact.zoomOut=Zoom out
|
||||
redact.nextPage=Next Page
|
||||
redact.previousPage=Previous Page
|
||||
redact.toggleSidebar=Toggle Sidebar
|
||||
redact.showThumbnails=Show Thumbnails
|
||||
redact.showDocumentOutline=Show Document Outline (double-click to expand/collapse all items)
|
||||
redact.showAttatchments=Show Attachments
|
||||
redact.showLayers=Show Layers (double-click to reset all layers to the default state)
|
||||
redact.colourPicker=Colour Picker
|
||||
redact.findCurrentOutlineItem=Find current outline item
|
||||
redact.applyChanges=Apply Changes
|
||||
|
||||
#showJS
|
||||
showJS.title=Show Javascript
|
||||
showJS.header=Show Javascript
|
||||
showJS.downloadJS=Download Javascript
|
||||
showJS.submit=Show
|
||||
|
||||
|
||||
#pdfToSinglePage
|
||||
pdfToSinglePage.title=PDF To Single Page
|
||||
pdfToSinglePage.header=PDF To Single Page
|
||||
pdfToSinglePage.submit=Convert To Single Page
|
||||
|
||||
|
||||
#pageExtracter
|
||||
pageExtracter.title=Extract Pages
|
||||
pageExtracter.header=Extract Pages
|
||||
pageExtracter.submit=Extract
|
||||
pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
|
||||
|
||||
|
||||
#getPdfInfo
|
||||
getPdfInfo.title=Get Info on PDF
|
||||
getPdfInfo.header=Get Info on PDF
|
||||
getPdfInfo.submit=Get Info
|
||||
getPdfInfo.downloadJson=Download JSON
|
||||
getPdfInfo.summary=PDF Summary
|
||||
getPdfInfo.summary.encrypted=This PDF is encrypted so may face issues with some applications
|
||||
getPdfInfo.summary.permissions=This PDF has {0} restricted permissions which may limit what you can do with it
|
||||
getPdfInfo.summary.compliance=This PDF complies with the {0} standard
|
||||
getPdfInfo.summary.basicInfo=Basic Information
|
||||
getPdfInfo.summary.docInfo=Document Information
|
||||
getPdfInfo.summary.encrypted.alert=Encrypted PDF - This document is password protected
|
||||
getPdfInfo.summary.not.encrypted.alert=Unencrypted PDF - No password protection
|
||||
getPdfInfo.summary.permissions.alert=Restricted Permissions - {0} actions are not allowed
|
||||
getPdfInfo.summary.all.permissions.alert=All Permissions Allowed
|
||||
getPdfInfo.summary.compliance.alert={0} Compliant
|
||||
getPdfInfo.summary.no.compliance.alert=No Compliance Standards
|
||||
getPdfInfo.summary.security.section=Security Status
|
||||
getPdfInfo.section.BasicInfo=Basic Information about the PDF document including file size, page count, and language
|
||||
getPdfInfo.section.Metadata=Document metadata including title, author, creation date and other document properties
|
||||
getPdfInfo.section.DocumentInfo=Technical details about the PDF document structure and version
|
||||
getPdfInfo.section.Compliancy=PDF standards compliance information (PDF/A, PDF/X, etc.)
|
||||
getPdfInfo.section.Encryption=Security and encryption details of the document
|
||||
getPdfInfo.section.Permissions=Document permission settings that control what actions can be performed
|
||||
getPdfInfo.section.Other=Additional document components like bookmarks, layers, and embedded files
|
||||
getPdfInfo.section.FormFields=Interactive form fields present in the document
|
||||
getPdfInfo.section.PerPageInfo=Detailed information about each page in the document
|
||||
|
||||
|
||||
#markdown-to-pdf
|
||||
MarkdownToPDF.title=Markdown To PDF
|
||||
MarkdownToPDF.header=Markdown To PDF
|
||||
MarkdownToPDF.submit=Convert
|
||||
MarkdownToPDF.help=Work in progress
|
||||
MarkdownToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#pdf-to-markdown
|
||||
PDFToMarkdown.title=PDF To Markdown
|
||||
PDFToMarkdown.header=PDF To Markdown
|
||||
PDFToMarkdown.submit=Convert
|
||||
|
||||
|
||||
#url-to-pdf
|
||||
URLToPDF.title=URL To PDF
|
||||
URLToPDF.header=URL To PDF
|
||||
URLToPDF.submit=Convert
|
||||
URLToPDF.credit=Uses WeasyPrint
|
||||
|
||||
|
||||
#html-to-pdf
|
||||
HTMLToPDF.title=HTML To PDF
|
||||
HTMLToPDF.header=HTML To PDF
|
||||
HTMLToPDF.help=Accepts HTML files and ZIPs containing html/css/images etc required
|
||||
HTMLToPDF.submit=Convert
|
||||
HTMLToPDF.credit=Uses WeasyPrint
|
||||
HTMLToPDF.zoom=Zoom level for displaying the website.
|
||||
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default)
|
||||
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default)
|
||||
HTMLToPDF.printBackground=Render the background of websites.
|
||||
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number)
|
||||
HTMLToPDF.cssMediaType=Change the CSS media type of the page.
|
||||
HTMLToPDF.none=None
|
||||
HTMLToPDF.print=Print
|
||||
HTMLToPDF.screen=Screen
|
||||
|
||||
|
||||
#AddStampRequest
|
||||
AddStampRequest.header=Stamp PDF
|
||||
AddStampRequest.title=Stamp PDF
|
||||
AddStampRequest.stampType=Stamp Type
|
||||
AddStampRequest.stampText=Stamp Text
|
||||
AddStampRequest.stampImage=Stamp Image
|
||||
AddStampRequest.alphabet=Alphabet
|
||||
AddStampRequest.fontSize=Font/Image Size
|
||||
AddStampRequest.rotation=Rotation
|
||||
AddStampRequest.opacity=Opacity
|
||||
AddStampRequest.position=Position
|
||||
AddStampRequest.overrideX=Override X Coordinate
|
||||
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
|
||||
sanitizePDF.selectText.1=Remove JavaScript actions
|
||||
sanitizePDF.selectText.2=Remove embedded files
|
||||
sanitizePDF.selectText.3=Remove XMP metadata
|
||||
sanitizePDF.selectText.4=Remove links
|
||||
sanitizePDF.selectText.5=Remove fonts
|
||||
sanitizePDF.selectText.6=Remove Document Info Metadata
|
||||
sanitizePDF.submit=Sanitize PDF
|
||||
|
||||
|
||||
#addPageNumbers
|
||||
addPageNumbers.title=Add Page Numbers
|
||||
addPageNumbers.header=Add Page Numbers
|
||||
addPageNumbers.selectText.1=Select PDF file:
|
||||
addPageNumbers.selectText.2=Margin Size
|
||||
addPageNumbers.selectText.3=Position
|
||||
addPageNumbers.selectText.4=Starting Number
|
||||
addPageNumbers.selectText.5=Pages to Number
|
||||
addPageNumbers.selectText.6=Custom Text
|
||||
addPageNumbers.customTextDesc=Custom Text
|
||||
addPageNumbers.numberPagesDesc=Which pages to number, default 'all', also accepts 1-5 or 2,5,9 etc
|
||||
addPageNumbers.customNumberDesc=Defaults to {n}, also accepts 'Page {n} of {total}', 'Text-{n}', '{filename}-{n}
|
||||
addPageNumbers.submit=Add Page Numbers
|
||||
|
||||
|
||||
#auto-rename
|
||||
auto-rename.title=Auto Rename
|
||||
auto-rename.header=Auto Rename PDF
|
||||
auto-rename.submit=Auto Rename
|
||||
|
||||
|
||||
#adjustContrast
|
||||
adjustContrast.title=Adjust Contrast
|
||||
adjustContrast.header=Adjust Contrast
|
||||
adjustContrast.contrast=Contrast:
|
||||
adjustContrast.brightness=Brightness:
|
||||
adjustContrast.saturation=Saturation:
|
||||
adjustContrast.download=Download
|
||||
|
||||
|
||||
#crop
|
||||
crop.title=Crop
|
||||
crop.header=Crop PDF
|
||||
crop.submit=Submit
|
||||
|
||||
|
||||
#autoSplitPDF
|
||||
autoSplitPDF.title=Auto Split PDF
|
||||
autoSplitPDF.header=Auto Split PDF
|
||||
autoSplitPDF.description=Print, Insert, Scan, upload, and let us auto-separate your documents. No manual work sorting needed.
|
||||
autoSplitPDF.selectText.1=Print out some divider sheets from below (Black and white is fine).
|
||||
autoSplitPDF.selectText.2=Scan all your documents at once by inserting the divider sheet between them.
|
||||
autoSplitPDF.selectText.3=Upload the single large scanned PDF file and let Stirling PDF handle the rest.
|
||||
autoSplitPDF.selectText.4=Divider pages are automatically detected and removed, guaranteeing a neat final document.
|
||||
autoSplitPDF.formPrompt=Submit PDF containing Stirling-PDF Page dividers:
|
||||
autoSplitPDF.duplexMode=Duplex Mode (Front and back scanning)
|
||||
autoSplitPDF.dividerDownload2=Download 'Auto Splitter Divider (with instructions).pdf'
|
||||
autoSplitPDF.submit=Submit
|
||||
|
||||
|
||||
#pipeline
|
||||
pipeline.title=Pipeline
|
||||
|
||||
|
||||
#pageLayout
|
||||
pageLayout.title=Multi Page Layout
|
||||
pageLayout.header=Multi Page Layout
|
||||
pageLayout.pagesPerSheet=Pages per sheet:
|
||||
pageLayout.addBorder=Add Borders
|
||||
pageLayout.submit=Submit
|
||||
|
||||
|
||||
#scalePages
|
||||
scalePages.title=Adjust page-scale
|
||||
scalePages.header=Adjust page-scale
|
||||
scalePages.pageSize=Size of a page of the document.
|
||||
scalePages.keepPageSize=Original Size
|
||||
scalePages.scaleFactor=Zoom level (crop) of a page.
|
||||
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.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.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.showSig=Show Signature
|
||||
certSign.reason=Reason
|
||||
certSign.location=Location
|
||||
certSign.name=Name
|
||||
certSign.showLogo=Show Logo
|
||||
certSign.submit=Sign PDF
|
||||
|
||||
|
||||
#removeCertSign
|
||||
removeCertSign.title=Remove Certificate Signature
|
||||
removeCertSign.header=Remove the digital certificate from the PDF
|
||||
removeCertSign.selectPDF=Select a PDF file:
|
||||
removeCertSign.submit=Remove Signature
|
||||
|
||||
|
||||
#removeBlanks
|
||||
removeBlanks.title=Remove Blanks
|
||||
removeBlanks.header=Remove Blank Pages
|
||||
removeBlanks.threshold=Pixel Whiteness Threshold:
|
||||
removeBlanks.thresholdDesc=Threshold for determining how white a white pixel must be to be classed as 'White'. 0 = Black, 255 pure white.
|
||||
removeBlanks.whitePercent=White Percent (%):
|
||||
removeBlanks.whitePercentDesc=Percent of page that must be 'white' pixels to be removed
|
||||
removeBlanks.submit=Remove Blanks
|
||||
|
||||
|
||||
#removeAnnotations
|
||||
removeAnnotations.title=Remove Annotations
|
||||
removeAnnotations.header=Remove Annotations
|
||||
removeAnnotations.submit=Remove
|
||||
|
||||
|
||||
#compare
|
||||
compare.title=Compare
|
||||
compare.header=Compare PDFs
|
||||
compare.highlightColor.1=Highlight Color 1:
|
||||
compare.highlightColor.2=Highlight Color 2:
|
||||
compare.document.1=Document 1
|
||||
compare.document.2=Document 2
|
||||
compare.submit=Compare
|
||||
compare.complex.message=One or both of the provided documents are large files, accuracy of comparison may be reduced
|
||||
compare.large.file.message=One or Both of the provided documents are too large to process
|
||||
compare.no.text.message=One or both of the selected PDFs have no text content. Please choose PDFs with text for comparison.
|
||||
|
||||
#sign
|
||||
sign.title=Sign
|
||||
sign.header=Sign PDFs
|
||||
sign.upload=Upload Image
|
||||
sign.draw=Draw Signature
|
||||
sign.text=Text Input
|
||||
sign.clear=Clear
|
||||
sign.add=Add
|
||||
sign.saved=Saved Signatures
|
||||
sign.save=Save Signature
|
||||
sign.personalSigs=Personal Signatures
|
||||
sign.sharedSigs=Shared Signatures
|
||||
sign.noSavedSigs=No saved signatures found
|
||||
sign.addToAll=Add to all pages
|
||||
sign.delete=Delete
|
||||
sign.first=First page
|
||||
sign.last=Last page
|
||||
sign.next=Next page
|
||||
sign.previous=Previous page
|
||||
sign.maintainRatio=Toggle maintain aspect ratio
|
||||
sign.undo=Undo
|
||||
sign.redo=Redo
|
||||
|
||||
#repair
|
||||
repair.title=Repair
|
||||
repair.header=Repair PDFs
|
||||
repair.submit=Repair
|
||||
|
||||
|
||||
#flatten
|
||||
flatten.title=Flatten
|
||||
flatten.header=Flatten PDFs
|
||||
flatten.flattenOnlyForms=Flatten only forms
|
||||
flatten.submit=Flatten
|
||||
|
||||
|
||||
#ScannerImageSplit
|
||||
ScannerImageSplit.selectText.1=Angle Threshold:
|
||||
ScannerImageSplit.selectText.2=Sets the minimum absolute angle required for the image to be rotated (default: 10).
|
||||
ScannerImageSplit.selectText.3=Tolerance:
|
||||
ScannerImageSplit.selectText.4=Determines the range of color variation around the estimated background color (default: 30).
|
||||
ScannerImageSplit.selectText.5=Minimum Area:
|
||||
ScannerImageSplit.selectText.6=Sets the minimum area threshold for a photo (default: 10000).
|
||||
ScannerImageSplit.selectText.7=Minimum Contour Area:
|
||||
ScannerImageSplit.selectText.8=Sets the minimum contour area threshold for a photo
|
||||
ScannerImageSplit.selectText.9=Border Size:
|
||||
ScannerImageSplit.selectText.10=Sets the size of the border added and removed to prevent white borders in the output (default: 1).
|
||||
ScannerImageSplit.info=Python is not installed. It is required to run.
|
||||
|
||||
|
||||
#OCR
|
||||
ocr.title=OCR / Scan Cleanup
|
||||
ocr.header=Cleanup Scans / OCR (Optical Character Recognition)
|
||||
ocr.selectText.1=Select languages that are to be detected within the PDF (Ones listed are the ones currently detected):
|
||||
ocr.selectText.2=Produce text file containing OCR text alongside the OCR'ed PDF
|
||||
ocr.selectText.3=Correct pages were scanned at a skewed angle by rotating them back into place
|
||||
ocr.selectText.4=Clean page so its less likely that OCR will find text in background noise. (No output change)
|
||||
ocr.selectText.5=Clean page so its less likely that OCR will find text in background noise, maintains cleanup in output.
|
||||
ocr.selectText.6=Ignores pages that have interactive text on them, only OCRs pages that are images
|
||||
ocr.selectText.7=Force OCR, will OCR Every page removing all original text elements
|
||||
ocr.selectText.8=Normal (Will error if PDF contains text)
|
||||
ocr.selectText.9=Additional Settings
|
||||
ocr.selectText.10=OCR Mode
|
||||
ocr.selectText.11=Remove images after OCR (Removes ALL images, only useful if part of conversion step)
|
||||
ocr.selectText.12=Render Type (Advanced)
|
||||
ocr.help=Please read this documentation on how to use this for other languages and/or use not in docker
|
||||
ocr.credit=This service uses qpdf and Tesseract for OCR.
|
||||
ocr.submit=Process PDF with OCR
|
||||
|
||||
|
||||
#extractImages
|
||||
extractImages.title=Extract Images
|
||||
extractImages.header=Extract Images
|
||||
extractImages.selectText=Select image format to convert extracted images to
|
||||
extractImages.allowDuplicates=Save duplicate images
|
||||
extractImages.submit=Extract
|
||||
|
||||
|
||||
#File to PDF
|
||||
fileToPDF.title=File to PDF
|
||||
fileToPDF.header=Convert any file to PDF
|
||||
fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion.
|
||||
fileToPDF.supportedFileTypesInfo=Supported File types
|
||||
fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation
|
||||
fileToPDF.submit=Convert to PDF
|
||||
|
||||
|
||||
#compress
|
||||
compress.title=Compress
|
||||
compress.header=Compress PDF
|
||||
compress.credit=This service uses qpdf for PDF Compress/Optimisation.
|
||||
compress.grayscale.label=Apply Grayscale for Compression
|
||||
compress.selectText.1=Compression Settings
|
||||
compress.selectText.1.1=1-3 PDF compression,</br> 4-6 lite image compression,</br> 7-9 intense image compression Will dramatically reduce image quality
|
||||
compress.selectText.2=Optimization level:
|
||||
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.submit=Compress
|
||||
|
||||
|
||||
#Add image
|
||||
addImage.title=Add Image
|
||||
addImage.header=Add image to PDF
|
||||
addImage.everyPage=Every Page?
|
||||
addImage.upload=Add image
|
||||
addImage.submit=Add image
|
||||
|
||||
|
||||
#merge
|
||||
merge.title=Merge
|
||||
merge.header=Merge multiple PDFs (2+)
|
||||
merge.sortByName=Sort by name
|
||||
merge.sortByDate=Sort by date
|
||||
merge.removeCertSign=Remove digital signature in the merged file?
|
||||
merge.submit=Merge
|
||||
|
||||
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML a PDF
|
||||
home.HTMLToPDF.desc=Convierte cualquier archivo HTML o ZIP a PDF
|
||||
HTMLToPDF.tags=margen,contenido web,transformación,convertir
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown a PDF
|
||||
home.MarkdownToPDF.desc=Convierte cualquier archivo Markdown a PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML PDF-ra
|
||||
home.HTMLToPDF.desc=Bihurtu edozein HTML edo zip fitxategi PDFra
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown PDF-ra
|
||||
home.MarkdownToPDF.desc=Bihurtu Markdown fitxategi guztiak PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML به PDF
|
||||
home.HTMLToPDF.desc=تبدیل هر فایل HTML یا زیپ به PDF
|
||||
HTMLToPDF.tags=مارکآپ،محتوای وب،تبدیل،تغییر
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=مارکداون به PDF
|
||||
home.MarkdownToPDF.desc=تبدیل هر فایل مارکداون به PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML en PDF
|
||||
home.HTMLToPDF.desc=Convertissez n'importe quel fichier HTML ou ZIP en PDF.
|
||||
HTMLToPDF.tags=html,markup,contenu Web,transformation,convert
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown en PDF
|
||||
home.MarkdownToPDF.desc=Convertissez n'importe quel fichier Markdown en PDF.
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML go PDF
|
||||
home.HTMLToPDF.desc=Tiontaíonn aon chomhad HTML nó zip go PDF
|
||||
HTMLToPDF.tags=marcáil, ábhar gréasáin, claochlú, tiontú
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Marcáil síos go PDF
|
||||
home.MarkdownToPDF.desc=Tiontaíonn aon chomhad Markdown go PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML से PDF
|
||||
home.HTMLToPDF.desc=किसी भी HTML फ़ाइल या zip को PDF में बदलें
|
||||
HTMLToPDF.tags=मार्कअप,वेब-सामग्री,रूपांतरण,बदलें
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown से PDF
|
||||
home.MarkdownToPDF.desc=किसी भी Markdown फ़ाइल को PDF में बदलें
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML u PDF
|
||||
home.HTMLToPDF.desc=Pretvara bilo koji HTML datoteku ili zip u PDF
|
||||
HTMLToPDF.tags=oznake,web-sadržaj,transformacija,konvertiranje
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown u PDF
|
||||
home.MarkdownToPDF.desc=Pretvara bilo koju Markdown datoteku u PDF
|
||||
|
@ -621,6 +621,22 @@ home.HTMLToPDF.title=HTML konvertálása PDF-be
|
||||
home.HTMLToPDF.desc=HTML fájl vagy ZIP konvertálása PDF-be
|
||||
HTMLToPDF.tags=jelölőnyelv,webtartalom,átalakítás,konvertálás
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown konvertálása PDF-be
|
||||
home.MarkdownToPDF.desc=Markdown fájl konvertálása PDF-be
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML ke PDF
|
||||
home.HTMLToPDF.desc=Mengonversi berkas HTML atau zip ke PDF
|
||||
HTMLToPDF.tags=markup, konten web, transformasi, konversi
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Penurunan harga ke PDF
|
||||
home.MarkdownToPDF.desc=Mengonversi berkas Markdown apa pun ke PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=Da HTML a PDF
|
||||
home.HTMLToPDF.desc=Converte qualsiasi file HTML o zip in PDF
|
||||
HTMLToPDF.tags=markup,contenuto web,trasformazione,conversione
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown in PDF
|
||||
home.MarkdownToPDF.desc=Converte qualsiasi file Markdown in PDF
|
||||
|
@ -621,6 +621,22 @@ home.HTMLToPDF.title=HTMLをPDFに変換
|
||||
home.HTMLToPDF.desc=HTMLファイルまたはzipをPDFに変換します。
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=MarkdownをPDFに変換
|
||||
home.MarkdownToPDF.desc=あらゆるMarkdownファイルをPDFに変換します。
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML을 PDF로
|
||||
home.HTMLToPDF.desc=HTML 파일이나 zip을 PDF로 변환
|
||||
HTMLToPDF.tags=마크업,웹-콘텐츠,변환,변환
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown을 PDF로
|
||||
home.MarkdownToPDF.desc=Markdown 파일을 PDF로 변환
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML PDF-ലേക്ക്
|
||||
home.HTMLToPDF.desc=ഏത് HTML ഫയലിനെയും അല്ലെങ്കിൽ സിപ്പിനെയും PDF-ലേക്ക് മാറ്റുന്നു
|
||||
HTMLToPDF.tags=മാർക്ക്അപ്പ്,വെബ്-ഉള്ളടക്കം,രൂപാന്തരം,പരിവർത്തനം ചെയ്യുക
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=മാർക്ക്ഡൗൺ PDF-ലേക്ക്
|
||||
home.MarkdownToPDF.desc=ഏത് മാർക്ക്ഡൗൺ ഫയലിനെയും PDF-ലേക്ക് മാറ്റുന്നു
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML naar PDF
|
||||
home.HTMLToPDF.desc=Zet HTML-bestand of zip om naar PDF
|
||||
HTMLToPDF.tags=markup,web-inhoud,transformatie,omzetten
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown naar PDF
|
||||
home.MarkdownToPDF.desc=Zet Markdown-bestand om naar PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML til PDF
|
||||
home.HTMLToPDF.desc=Konverter hvilken som helst HTML-fil eller zip til PDF
|
||||
HTMLToPDF.tags=markup,web-innhold,transformasjon,konverter
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown til PDF
|
||||
home.MarkdownToPDF.desc=Konverter hvilken som helst Markdown-fil til PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML do PDF
|
||||
home.HTMLToPDF.desc=Zapisuje podany plik HTML/ZIP do PDF
|
||||
HTMLToPDF.tags=znaczniki, treść internetowa, transformacja, konwertowanie
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown do PDF
|
||||
home.MarkdownToPDF.desc=Zapisuje dokument Markdown do PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML para PDF
|
||||
home.HTMLToPDF.desc=Converter qualquer arquivo HTML ou zip para PDF.
|
||||
HTMLToPDF.tags=marcação,conteúdo-web,transformação,converter
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown para PDF
|
||||
home.MarkdownToPDF.desc=Converte qualquer arquivo Markdown para PDF.
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML para PDF
|
||||
home.HTMLToPDF.desc=Converte qualquer ficheiro HTML ou zip para PDF
|
||||
HTMLToPDF.tags=marcação,conteúdo-web,transformação,converter
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown para PDF
|
||||
home.MarkdownToPDF.desc=Converte qualquer ficheiro Markdown para PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML în PDF
|
||||
home.HTMLToPDF.desc=Convertește orice fișier HTML sau zip în PDF
|
||||
HTMLToPDF.tags=markup,conținut-web,transformare,convertește
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown în PDF
|
||||
home.MarkdownToPDF.desc=Convertește orice fișier Markdown în PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML в PDF
|
||||
home.HTMLToPDF.desc=Преобразует любой HTML-файл или zip в PDF
|
||||
HTMLToPDF.tags=разметка,веб-контент,преобразование,конвертация
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown в PDF
|
||||
home.MarkdownToPDF.desc=Преобразует любой файл Markdown в PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML do PDF
|
||||
home.HTMLToPDF.desc=Konvertuje akýkoľvek HTML súbor alebo zip do PDF
|
||||
HTMLToPDF.tags=markup, webový obsah, transformácia, konvertovať
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown do PDF
|
||||
home.MarkdownToPDF.desc=Konvertuje akýkoľvek Markdown súbor do PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML v PDF
|
||||
home.HTMLToPDF.desc=Pretvori katero koli datoteko HTML ali zip v PDF
|
||||
HTMLToPDF.tags=markup,web-content,transformation,convert
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown v PDF
|
||||
home.MarkdownToPDF.desc=Pretvori katero koli datoteko Markdown v PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML u PDF
|
||||
home.HTMLToPDF.desc=Konvertuje bilo koji HTML fajl ili zip u PDF
|
||||
HTMLToPDF.tags=oznake,web-sadržaj,transformacija,konvertovanje
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown u PDF
|
||||
home.MarkdownToPDF.desc=Konvertuje bilo koji Markdown fajl u PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML till PDF
|
||||
home.HTMLToPDF.desc=Konverterar valfri HTML-fil eller zip till PDF
|
||||
HTMLToPDF.tags=markup,webbinnehåll,transformation,konvertera
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown till PDF
|
||||
home.MarkdownToPDF.desc=Konverterar valfri Markdown-fil till PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML เป็น PDF
|
||||
home.HTMLToPDF.desc=แปลงไฟล์ HTML หรือ zip เป็น PDF
|
||||
HTMLToPDF.tags=มาร์กอัป, เนื้อหาเว็บ, การแปลง, การแปลง
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown เป็น PDF
|
||||
home.MarkdownToPDF.desc=แปลงไฟล์ Markdown เป็น PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML'den PDF'e
|
||||
home.HTMLToPDF.desc=Herhangi bir HTML dosyasını veya zip'i PDF'e dönüştürür
|
||||
HTMLToPDF.tags=biçimlendirme,web-içeriği,dönüşüm,dönüştür
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown'dan PDF'e
|
||||
home.MarkdownToPDF.desc=Herhangi bir Markdown dosyasını PDF'e dönüştürür
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML в PDF
|
||||
home.HTMLToPDF.desc=Конвертує будь-який HTML-файл або zip-файл у PDF.
|
||||
HTMLToPDF.tags=розмітка,веб-контент,перетворення,конвертація
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown в PDF
|
||||
home.MarkdownToPDF.desc=Конвертує будь-який файл Markdown у PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML sang PDF
|
||||
home.HTMLToPDF.desc=Chuyển đổi bất kỳ tệp HTML hoặc zip nào thành PDF
|
||||
HTMLToPDF.tags=đánh dấu,nội dung web,chuyển đổi,chuyển
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown sang PDF
|
||||
home.MarkdownToPDF.desc=Chuyển đổi bất kỳ tệp Markdown nào thành PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML 转 PDF
|
||||
home.HTMLToPDF.desc=将任何 HTML 文件或 zip 文件转换为 PDF
|
||||
HTMLToPDF.tags=标记、网页内容、转换、转换
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown 转 PDF
|
||||
home.MarkdownToPDF.desc=将任何 Markdown 文件转换为 PDF
|
||||
|
@ -489,6 +489,22 @@ home.HTMLToPDF.title=HTML 轉 PDF
|
||||
home.HTMLToPDF.desc=將任何 HTML 檔案或壓縮檔轉換為 PDF
|
||||
HTMLToPDF.tags=標記,網頁內容,轉換,轉檔
|
||||
|
||||
#eml-to-pdf
|
||||
home.EMLToPDF.title=Email to PDF
|
||||
home.EMLToPDF.desc=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.tags=email,conversion,eml,message,transformation,convert,mail
|
||||
|
||||
EMLToPDF.title=Email To PDF
|
||||
EMLToPDF.header=Email To PDF
|
||||
EMLToPDF.submit=Convert
|
||||
EMLToPDF.downloadHtml=Download HTML intermediate file instead of PDF
|
||||
EMLToPDF.downloadHtmlHelp=This allows you to see the HTML version before PDF conversion and can help debug formatting issues
|
||||
EMLToPDF.includeAttachments=Include attachments in PDF
|
||||
EMLToPDF.maxAttachmentSize=Maximum attachment size (MB)
|
||||
EMLToPDF.help=Converts email (EML) files to PDF format including headers, body, and inline images
|
||||
EMLToPDF.troubleshootingTip1=Email to HTML is a more reliable process, so with batch-processing it is recommended to save both
|
||||
EMLToPDF.troubleshootingTip2=With a small number of Emails, if the PDF is malformed, you can download HTML and override some of the problematic HTML/CSS code.
|
||||
EMLToPDF.troubleshootingTip3=Embeddings, however, do not work with HTMLs
|
||||
|
||||
home.MarkdownToPDF.title=Markdown 轉 PDF
|
||||
home.MarkdownToPDF.desc=將任何 Markdown 檔案轉換為 PDF
|
||||
|
@ -467,5 +467,361 @@
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{account.title})}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon organize">settings_account_box</span>
|
||||
<span class="tool-header-text" th:text="#{account.accountSettings}">User Settings</span>
|
||||
</div>
|
||||
|
||||
<!-- User Settings Title -->
|
||||
<th:block th:if="${messageType}">
|
||||
<div class="alert alert-danger">
|
||||
<span th:text="#{${messageType}}">Default message if not found</span>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<!-- At the top of the user settings -->
|
||||
<h3 class="text-center"><span th:text="#{welcome} + ' ' + ${username}">User</span>!</h3>
|
||||
<th:block th:if="${error}">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<span th:text="${error}">Error Message</span>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
<!-- Change Username Form -->
|
||||
<th:block th:if="not ${oAuth2Login} or not ${saml2Login}">
|
||||
<h4 th:text="#{account.changeUsername}">Change Username?</h4>
|
||||
<form id="formsavechangeusername" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-username'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="newUsername" th:text="#{account.newUsername}">Change Username</label>
|
||||
<input type="text" class="form-control" name="newUsername" id="newUsername" th:placeholder="#{account.newUsername}">
|
||||
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="currentPasswordChangeUsername" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="currentPasswordChangeUsername" id="currentPasswordChangeUsername" th:placeholder="#{password}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changeUsername}">Change Username</button>
|
||||
</div>
|
||||
</form>
|
||||
</th:block>
|
||||
|
||||
<!-- Change Password Form -->
|
||||
<th:block th:if="not ${oAuth2Login} or not ${saml2Login}">
|
||||
<h4 th:text="#{account.changePassword}">Change Password?</h4>
|
||||
<form id="formsavechangepassword" class="bg-card mt-4 mb-4" th:action="@{'/api/v1/user/change-password'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="currentPassword" th:text="#{account.oldPassword}">Old Password</label>
|
||||
<input type="password" class="form-control" name="currentPassword" id="currentPassword" th:placeholder="#{account.oldPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="newPassword" th:text="#{account.newPassword}">New Password</label>
|
||||
<input type="password" class="form-control" name="newPassword" id="newPassword" th:placeholder="#{account.newPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="confirmNewPassword" th:text="#{account.confirmNewPassword}">Confirm New Password</label>
|
||||
<input type="password" class="form-control" name="confirmNewPassword" id="confirmNewPassword" th:placeholder="#{account.confirmNewPassword}">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<span id="confirmPasswordError" style="display: none;" th:text="#{confirmPasswordErrorMessage}">New Password and Confirm New Password must match.</span>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{account.changePassword}">Change Password</button>
|
||||
</div>
|
||||
</form>
|
||||
</th:block>
|
||||
|
||||
<!-- API Key Form -->
|
||||
<h4 th:text="#{account.yourApiKey}">API Key</h4>
|
||||
<div class="card mt-4 mb-4">
|
||||
<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-secondary" id="copyBtn" type="button" onclick="copyToClipboard()">
|
||||
<span class="material-symbols-rounded">
|
||||
content_copy
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-secondary" id="showBtn" type="button" onclick="showApiKey()">
|
||||
<span class="material-symbols-rounded" id="eyeIcon">
|
||||
visibility
|
||||
</span>
|
||||
</button>
|
||||
<button class="btn btn-secondary" id="refreshBtn" type="button" onclick="refreshApiKey()">
|
||||
<span class="material-symbols-rounded">
|
||||
refresh
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script th:inline="javascript">
|
||||
jQuery.validator.addMethod("usernamePattern", function(value, element) {
|
||||
// Regular expression for user name: Min. 3 characters, max. 50 characters
|
||||
const regexUsername = /^[a-zA-Z0-9](?!.*[-@._+]{2,})([a-zA-Z0-9@._+-]{1,48})[a-zA-Z0-9]$/;
|
||||
|
||||
// Regular expression for email addresses: Max. 320 characters, with RFC-like validation
|
||||
const regexEmail = /^(?=.{1,320}$)(?=.{1,64}@)[A-Za-z0-9](?:[A-Za-z0-9_.+-]*[A-Za-z0-9])?@[^-][A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*(?:\.[A-Za-z]{2,})$/;
|
||||
|
||||
// Check if the field is optional or meets the requirements
|
||||
return this.optional(element) || regexUsername.test(value) || regexEmail.test(value);
|
||||
}, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format");
|
||||
$(document).ready(function() {
|
||||
$.validator.addMethod("passwordMatch", function(value, element) {
|
||||
return $('#newPassword').val() === $('#confirmNewPassword').val();
|
||||
}, /*[[#{confirmPasswordErrorMessage}]]*/ "New Password and Confirm New Password must match.");
|
||||
$('#formsavechangepassword').validate({
|
||||
rules: {
|
||||
currentPassword: {
|
||||
required: true
|
||||
},
|
||||
newPassword: {
|
||||
required: true
|
||||
},
|
||||
confirmNewPassword: {
|
||||
required: true,
|
||||
passwordMatch: true
|
||||
},
|
||||
errorPlacement: function(error, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").text(error.text()).show();
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
success: function(label, element) {
|
||||
if ($(element).attr("name") === "newPassword" || $(element).attr("name") === "confirmNewPassword") {
|
||||
$("#confirmPasswordError").hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#formsavechangeusername').validate({
|
||||
rules: {
|
||||
newUsername: {
|
||||
required: true,
|
||||
usernamePattern: true
|
||||
},
|
||||
currentPasswordChangeUsername: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
newUsername: {
|
||||
usernamePattern: /*[[#{invalidUsernameMessage}]]*/ "Invalid username format"
|
||||
},
|
||||
},
|
||||
errorPlacement: function(error, element) {
|
||||
if (element.attr("name") === "newUsername") {
|
||||
$("#usernameError").text(error.text()).show();
|
||||
} else {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
success: function(label, element) {
|
||||
if ($(element).attr("name") === "newUsername") {
|
||||
$("#usernameError").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script th:inline="javascript">
|
||||
function copyToClipboard() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
apiKeyElement.select();
|
||||
document.execCommand("copy");
|
||||
}
|
||||
|
||||
function showApiKey() {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
const eyeIcon = document.getElementById("eyeIcon");
|
||||
if (apiKeyElement.type === "password") {
|
||||
apiKeyElement.type = "text";
|
||||
eyeIcon.textContent = "visibility_off";
|
||||
copyBtn.disabled = false; // Enable copy button when API key is visible
|
||||
} else {
|
||||
apiKeyElement.type = "password";
|
||||
eyeIcon.textContent = "visibility";
|
||||
copyBtn.disabled = true; // Disable copy button when API key is hidden
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
showApiKey();
|
||||
try {
|
||||
/*<![CDATA[*/
|
||||
const urlGetApiKey = /*[[@{/api/v1/user/get-api-key}]]*/ "/api/v1/user/get-api-key";
|
||||
/*]]>*/
|
||||
let response = await window.fetchWithCsrf(urlGetApiKey, { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
} else {
|
||||
manageUIState(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
});
|
||||
|
||||
async function refreshApiKey() {
|
||||
try {
|
||||
/*<![CDATA[*/
|
||||
const urlUpdateApiKey = /*[[@{/api/v1/user/update-api-key}]]*/ "/api/v1/user/update-api-key";
|
||||
/*]]>*/
|
||||
let response = await window.fetchWithCsrf(urlUpdateApiKey, { method: 'POST' });
|
||||
if (response.status === 200) {
|
||||
let apiKey = await response.text();
|
||||
manageUIState(apiKey);
|
||||
document.getElementById("apiKey").type = 'text';
|
||||
document.getElementById("copyBtn").disabled = false;
|
||||
} else {
|
||||
alert('Error refreshing API key.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('There was an error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function manageUIState(apiKey) {
|
||||
const apiKeyElement = document.getElementById("apiKey");
|
||||
const showBtn = document.getElementById("showBtn");
|
||||
const copyBtn = document.getElementById("copyBtn");
|
||||
|
||||
if (apiKey && apiKey.trim().length > 0) {
|
||||
apiKeyElement.value = apiKey;
|
||||
showBtn.disabled = false;
|
||||
copyBtn.disabled = false;
|
||||
} else {
|
||||
apiKeyElement.value = "";
|
||||
showBtn.disabled = true;
|
||||
copyBtn.disabled = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h4 th:text="#{account.syncTitle}">Sync browser settings with Account</h4>
|
||||
<div class="bg-card container mt-4">
|
||||
<h3 th:text="#{account.settingsCompare}">Settings Comparison:</h3>
|
||||
<table id="settingsTable" class="table table-bordered table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" th:text="#{account.property}">Property</th>
|
||||
<th scope="col" th:text="#{account.accountSettings}">Account Setting</th>
|
||||
<th scope="col" th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- This will be dynamically populated by JavaScript -->
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="buttons-container mt-3 text-center">
|
||||
<button id="syncToBrowser" class="btn btn-primary btn-sm" th:text="#{account.syncToBrowser}">Sync Account -> Browser</button>
|
||||
<button id="syncToAccount" class="btn btn-secondary btn-sm" th:text="#{account.syncToAccount}">Sync Account <- Browser</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener("DOMContentLoaded", async function() {
|
||||
const settingsTableBody = document.querySelector("#settingsTable tbody");
|
||||
|
||||
/*<![CDATA[*/
|
||||
var accountSettingsString = /*[[${settings}]]*/ {};
|
||||
/*]]>*/
|
||||
var accountSettings = JSON.parse(accountSettingsString);
|
||||
|
||||
let allKeys = new Set([...Object.keys(accountSettings), ...Object.keys(localStorage)]);
|
||||
|
||||
allKeys.forEach(key => {
|
||||
if(key === 'debug' || key === '0' || key === '1' || key.includes('pdfjs') || key.includes('posthog') || key.includes('pageViews')) return; // Ignoring specific keys
|
||||
|
||||
const accountValue = accountSettings[key] || '-';
|
||||
const browserValue = localStorage.getItem(key) || '-';
|
||||
|
||||
const row = settingsTableBody.insertRow();
|
||||
const propertyCell = row.insertCell(0);
|
||||
const accountCell = row.insertCell(1);
|
||||
const browserCell = row.insertCell(2);
|
||||
|
||||
propertyCell.textContent = key;
|
||||
accountCell.textContent = accountValue;
|
||||
browserCell.textContent = browserValue;
|
||||
});
|
||||
|
||||
document.getElementById('syncToBrowser').addEventListener('click', function() {
|
||||
// First, clear the local storage
|
||||
localStorage.clear();
|
||||
|
||||
// Then, set the account settings to local storage
|
||||
for (let key in accountSettings) {
|
||||
if(key !== 'debug' && key !== '0' && key !== '1' && !key.includes('pdfjs') && !key.includes('posthog') && !key.includes('pageViews')) { // Only sync non-ignored keys
|
||||
localStorage.setItem(key, accountSettings[key]);
|
||||
}
|
||||
}
|
||||
location.reload(); // Refresh the page after sync
|
||||
});
|
||||
|
||||
document.getElementById('syncToAccount').addEventListener('click', async function() {
|
||||
/*<![CDATA[*/
|
||||
const urlUpdateUserSettings = /*[[@{/api/v1/user/updateUserSettings}]]*/ "/api/v1/user/updateUserSettings";
|
||||
/*]]>*/
|
||||
|
||||
let settings = {};
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
if(key !== 'debug' && key !== '0' && key !== '1' && !key.includes('pdfjs') && !key.includes('posthog') && !key.includes('pageViews')) {
|
||||
settings[key] = localStorage.getItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await window.fetchWithCsrf(urlUpdateUserSettings, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(settings)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Error syncing settings to account');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
alert('Error syncing settings to account');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div class="mb-3 mt-4 text-center">
|
||||
<a th:href="@{'/logout'}" role="button" class="btn btn-danger" th:text="#{account.signOut}">Sign Out</a>
|
||||
<a th:if="${role == 'ROLE_ADMIN'}" class="btn btn-info" th:href="@{'/adminSettings'}" role="button" th:text="#{account.adminSettings}" target="_blank">Admin Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -457,4 +457,320 @@
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{adminUserSettings.title}, header=#{adminUserSettings.header})}"></th:block>
|
||||
<style>
|
||||
.active-user {
|
||||
color: green;
|
||||
text-shadow: 0 0 5px green;
|
||||
}
|
||||
|
||||
.text-overflow {
|
||||
max-width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/common :: game}"></th:block>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<br><br>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-9 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon organize">manage_accounts</span>
|
||||
<span class="tool-header-text" th:text="#{adminUserSettings.header}">Admin User Control Settings</span>
|
||||
</div>
|
||||
|
||||
<!-- User Settings Title -->
|
||||
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
|
||||
<a href="#"
|
||||
th:data-bs-toggle="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : 'modal'"
|
||||
th:data-bs-target="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? null : '#addUserModal'"
|
||||
th:class="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? 'btn btn-danger' : 'btn btn-outline-success'"
|
||||
th:title="${@runningProOrHigher && totalUsers >= maxPaidUsers} ? #{adminUserSettings.maxUsersReached} : #{adminUserSettings.addUser}">
|
||||
<span class="material-symbols-rounded">person_add</span>
|
||||
<span th:text="#{adminUserSettings.addUser}">Add New User</span>
|
||||
</a>
|
||||
|
||||
<a href="#"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#changeUserRoleModal"
|
||||
class="btn btn-outline-success"
|
||||
th:title="#{adminUserSettings.changeUserRole}">
|
||||
<span class="material-symbols-rounded">edit</span>
|
||||
<span th:text="#{adminUserSettings.changeUserRole}">Change User's Role</span>
|
||||
</a>
|
||||
|
||||
<a th:href="@{'/usage'}" th:if="${@runningEE}"
|
||||
class="btn btn-outline-success"
|
||||
th:title="#{adminUserSettings.usage}">
|
||||
<span class="material-symbols-rounded">analytics</span>
|
||||
<span th:text="#{adminUserSettings.usage}">Usage Statistics</span>
|
||||
</a>
|
||||
|
||||
<div class="my-4">
|
||||
<strong style="margin-left: 20px;" th:text="#{adminUserSettings.totalUsers}">Total Users:</strong>
|
||||
<span th:text="${totalUsers}"></span>
|
||||
<span th:if="${@runningProOrHigher}" th:text="'/'+${maxPaidUsers}"></span>
|
||||
|
||||
<strong style="margin-left: 20px;" th:text="#{adminUserSettings.activeUsers}">Active Users:</strong>
|
||||
<span th:text="${activeUsers}"></span>
|
||||
|
||||
<strong style="margin-left: 20px;" th:text="#{adminUserSettings.disabledUsers}">Disabled Users:</strong>
|
||||
<span th:text="${disabledUsers}"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div th:if="${addMessage}" class="p-3" style="background: var(--md-sys-color-outline-variant);border-radius: 2rem; text-align: center;">
|
||||
<div class="alert alert-danger mb-auto">
|
||||
<span th:text="#{${addMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
</div>
|
||||
<div th:if="${changeMessage}" class="p-3" style="background: var(--md-sys-color-outline-variant);border-radius: 2rem; text-align: center;">
|
||||
<div class="alert alert-danger mb-auto">
|
||||
<span th:text="#{${changeMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
</div>
|
||||
<div th:if="${deleteMessage}" class="alert alert-danger">
|
||||
<span th:text="#{${deleteMessage}}">Default message if not found</span>
|
||||
</div>
|
||||
<div class="bg-card mt-3 mb-3 table-responsive">
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">#</th>
|
||||
<th scope="col" th:title="#{username}" th:text="#{username}">Username</th>
|
||||
<th scope="col" th:title="#{adminUserSettings.roles}" th:text="#{adminUserSettings.roles}">Roles</th>
|
||||
<th scope="col" th:title="#{adminUserSettings.authenticated}" class="text-overflow" th:text="#{adminUserSettings.authenticated}">Authenticated</th>
|
||||
<th scope="col" th:title="#{adminUserSettings.lastRequest}" class="text-overflow" th:text="#{adminUserSettings.lastRequest}">Last Request</th>
|
||||
<th scope="col" th:title="#{adminUserSettings.actions}" th:text="#{adminUserSettings.actions}" colspan="2">Actions</th>
|
||||
<!-- <th scope="col"></th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="user : ${users}">
|
||||
<th scope="row" style="align-content: center;" th:text="${user.id}"></th>
|
||||
<td style="align-content: center;" th:text="${user.username}" th:classappend="${userSessions[user.username] ? 'active-user' : ''}"></td>
|
||||
<td style="align-content: center;" th:text="#{${user.roleName}}"></td>
|
||||
<td style="align-content: center;" th:text="${user.authenticationType}"></td>
|
||||
<td style="align-content: center;" th:text="${userLastRequest[user.username] != null ? #dates.format(userLastRequest[user.username], 'yyyy-MM-dd HH:mm:ss') : 'N/A'}"></td>
|
||||
<td style="align-content: center;">
|
||||
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDeleteUser()">
|
||||
<button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info btn-sm"><span class="material-symbols-rounded">person_remove</span></button>
|
||||
</form>
|
||||
<a th:if="${user.username == currentUsername}" th:title="#{adminUserSettings.editOwnProfil}" th:href="@{'/account'}" class="btn btn-outline-success btn-sm"><span class="material-symbols-rounded">edit</span></a>
|
||||
</td>
|
||||
<td style="align-content: center;">
|
||||
<form th:action="@{'/api/v1/user/admin/changeUserEnabled/' + ${user.username}}" method="post" onsubmit="return confirmChangeUserStatus()">
|
||||
<input type="hidden" name="enabled" th:value="!${user.enabled}" />
|
||||
<button type="submit" th:if="${user.enabled}" th:title="#{adminUserSettings.enabledUser}" class="btn btn-success btn-sm">
|
||||
<span class="material-symbols-rounded">person</span>
|
||||
</button>
|
||||
<button type="submit" th:unless="${user.enabled}" th:title="#{adminUserSettings.disabledUser}" class="btn btn-danger btn-sm">
|
||||
<span class="material-symbols-rounded">person_off</span>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p th:if="${!@runningProOrHigher}" th:text="#{enterpriseEdition.ssoAdvert}"></p>
|
||||
|
||||
<script th:inline="javascript">
|
||||
const delete_confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
|
||||
const change_confirm_text = /*[[#{adminUserSettings.confirmChangeUserStatus}]]*/ 'Should the user be disabled/enabled?';
|
||||
function confirmDeleteUser() {
|
||||
return confirm(delete_confirm_text);
|
||||
}
|
||||
function confirmChangeUserStatus() {
|
||||
return confirm(change_confirm_text);
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- change User role Modal start -->
|
||||
<div class="modal fade" id="changeUserRoleModal" tabindex="-1" aria-labelledby="changeUserRoleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h2 th:text="#{adminUserSettings.changeUserRole}">Change User's Role</h2>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span class="material-symbols-rounded">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{downgradeCurrentUserLongMessage}" th:text="#{help}">Help</button>
|
||||
<form th:action="@{'/api/v1/user/admin/changeRole'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" th:text="#{username}">Username</label>
|
||||
<select name="username" class="form-control" required>
|
||||
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
|
||||
<option th:each="user : ${users}" th:if="${user.username != currentUsername}" th:value="${user.username}" th:text="${user.username}">Username</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
|
||||
<select name="role" class="form-control" required>
|
||||
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
|
||||
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Add other fields as required -->
|
||||
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- change User role Modal end -->
|
||||
|
||||
<!-- Add User Modal start -->
|
||||
<div class="modal fade" id="addUserModal" tabindex="-1" aria-labelledby="addUserModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="addUserModalLabel" th:text="#{adminUserSettings.addUser}">Add New User</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
|
||||
<span class="material-symbols-rounded">close</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<button class="btn btn-outline-info" data-toggle="tooltip" data-placement="auto" th:title="#{adminUserSettings.usernameInfo}" th:text="#{help}">Help</button>
|
||||
<form id="formsaveuser" th:action="@{'/api/v1/user/admin/saveUser'}" method="post">
|
||||
<div class="mb-3">
|
||||
<label for="username" th:text="#{username}">Username</label>
|
||||
<input type="text" class="form-control" name="username" id="username" th:title="#{adminUserSettings.usernameInfo}" required>
|
||||
<span id="usernameError" style="display: none;" th:text="#{invalidUsernameMessage}">Invalid username!</span>
|
||||
</div>
|
||||
<div class="mb-3" id="passwordContainer">
|
||||
<label for="password" th:text="#{password}">Password</label>
|
||||
<input type="password" class="form-control" name="password" id="password" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="role" th:text="#{adminUserSettings.role}">Role</label>
|
||||
<select name="role" class="form-control" id="role" required>
|
||||
<option value="" disabled selected th:text="#{selectFillter}">-- Select --</option>
|
||||
<option th:each="roleDetail : ${roleDetails}" th:value="${roleDetail.key}" th:text="#{${roleDetail.value}}">Role</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="authType">Authentication Type</label>
|
||||
<select id="authType" name="authType" class="form-control" required>
|
||||
<option value="web" selected>WEB</option>
|
||||
<option value="sso">SSO</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-check mb-3" id="checkboxContainer">
|
||||
<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>
|
||||
<button type="submit" class="btn btn-primary" th:text="#{adminUserSettings.submit}">Save User</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Add User Modal end -->
|
||||
|
||||
<script th:inline="javascript">
|
||||
jQuery.validator.addMethod("usernamePattern", function(value, element) {
|
||||
// Regular expression for user name: Min. 3 characters, max. 50 characters
|
||||
const regexUsername = /^[a-zA-Z0-9](?!.*[-@._+]{2,})([a-zA-Z0-9@._+-]{1,48})[a-zA-Z0-9]$/;
|
||||
|
||||
// Regular expression for email addresses: Max. 320 characters, with RFC-like validation
|
||||
const regexEmail = /^(?=.{1,320}$)(?=.{1,64}@)[A-Za-z0-9](?:[A-Za-z0-9_.+-]*[A-Za-z0-9])?@[^-][A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*(?:\.[A-Za-z]{2,})$/;
|
||||
|
||||
// Check if the field is optional or meets the requirements
|
||||
return this.optional(element) || regexUsername.test(value) || regexEmail.test(value);
|
||||
}, /*[[#{invalidUsernameMessage}]]*/ "Invalid username format");
|
||||
$(document).ready(function() {
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
|
||||
$('#formsaveuser').validate({
|
||||
rules: {
|
||||
username: {
|
||||
required: true,
|
||||
usernamePattern: true
|
||||
},
|
||||
password: {
|
||||
required: true
|
||||
},
|
||||
role: {
|
||||
required: true
|
||||
},
|
||||
authType: {
|
||||
required: true
|
||||
}
|
||||
},
|
||||
messages: {
|
||||
username: {
|
||||
usernamePattern: /*[[#{invalidUsernameMessage}]]*/ "Invalid username format"
|
||||
},
|
||||
},
|
||||
errorPlacement: function(error, element) {
|
||||
if (element.attr("name") === "username") {
|
||||
$("#usernameError").text(error.text()).show();
|
||||
} else if (element.attr("name") !== "role" && element.attr("name") !== "authType") {
|
||||
error.insertAfter(element);
|
||||
}
|
||||
},
|
||||
success: function(label, element) {
|
||||
if ($(element).attr("name") === "username") {
|
||||
$("#usernameError").hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#username').on('input', function() {
|
||||
var usernameInput = $(this);
|
||||
var isValid = usernameInput[0].checkValidity();
|
||||
var errorSpan = $('#usernameError');
|
||||
|
||||
if (isValid) {
|
||||
usernameInput.removeClass('invalid').addClass('valid');
|
||||
errorSpan.hide();
|
||||
} else {
|
||||
usernameInput.removeClass('valid').addClass('invalid');
|
||||
errorSpan.show();
|
||||
}
|
||||
});
|
||||
|
||||
$('#authType').on('change', function() {
|
||||
var authType = $(this).val();
|
||||
var passwordField = $('#password');
|
||||
var passwordFieldContainer = $('#passwordContainer');
|
||||
var checkboxContainer = $('#checkboxContainer');
|
||||
|
||||
if (authType === 'sso') {
|
||||
passwordField.removeAttr('required');
|
||||
passwordField.prop('disabled', true).val('');
|
||||
passwordFieldContainer.slideUp('fast');
|
||||
checkboxContainer.slideUp('fast');
|
||||
} else {
|
||||
passwordField.prop('disabled', false);
|
||||
passwordField.attr('required', 'required');
|
||||
passwordFieldContainer.slideDown('fast');
|
||||
checkboxContainer.slideDown('fast');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}"
|
||||
xmlns:th="https://www.thymeleaf.org">
|
||||
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/common :: head(title=#{EMLToPDF.title}, header=#{EMLToPDF.header})}"></th:block>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="page-container">
|
||||
<div id="content-wrap">
|
||||
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||
<div class="container py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon convertto">email</span>
|
||||
<span class="tool-header-text" th:text="#{EMLToPDF.header}"></span>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data" th:action="@{'/api/v1/convert/eml/pdf'}" class="mt-4">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, accept='.eml,message/rfc822')}">
|
||||
</div>
|
||||
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" name="downloadHtml" id="downloadHtml">
|
||||
<label class="form-check-label" for="downloadHtml" th:text="#{EMLToPDF.downloadHtml}"></label>
|
||||
<div class="form-text" th:text="#{EMLToPDF.downloadHtmlHelp}"></div>
|
||||
</div>
|
||||
|
||||
<div id="pdfOnlyOptions">
|
||||
<div class="form-check mb-3">
|
||||
<input type="checkbox" class="form-check-input" name="includeAttachments" id="includeAttachments" checked>
|
||||
<label class="form-check-label" for="includeAttachments" th:text="#{EMLToPDF.includeAttachments}"></label>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="maxAttachmentSizeMB" class="form-label" th:text="#{EMLToPDF.maxAttachmentSize}"></label>
|
||||
<input type="number" class="form-control" id="maxAttachmentSizeMB" name="maxAttachmentSizeMB" value="10" min="1" max="100">
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<button class="btn btn-outline-primary" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#info" aria-expanded="false" aria-controls="info" th:text="#{info}">
|
||||
</button>
|
||||
<div class="collapse mt-3" id="info">
|
||||
<div class="card card-body">
|
||||
<p class="mb-2" th:text="#{EMLToPDF.help}"></p>
|
||||
<ul class="mb-0">
|
||||
<li th:text="#{EMLToPDF.troubleshootingTip1}"></li>
|
||||
<li th:text="#{EMLToPDF.troubleshootingTip2}"></li>
|
||||
<li th:text="#{EMLToPDF.troubleshootingTip3}"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{EMLToPDF.submit}"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||
</div>
|
||||
|
||||
<script th:inline="javascript">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const downloadHtml = document.getElementById('downloadHtml');
|
||||
const pdfOnlyOptions = document.getElementById('pdfOnlyOptions');
|
||||
const submitBtn = document.getElementById('submitBtn');
|
||||
|
||||
function updateFormState() {
|
||||
if (pdfOnlyOptions && submitBtn) {
|
||||
pdfOnlyOptions.style.display = downloadHtml.checked ? 'none' : 'block';
|
||||
submitBtn.textContent = downloadHtml.checked ? 'Download HTML' : '[[#{EMLToPDF.submit}]]';
|
||||
}
|
||||
}
|
||||
|
||||
if (downloadHtml) {
|
||||
downloadHtml.addEventListener('change', updateFormState);
|
||||
updateFormState();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -29,6 +29,13 @@
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
|
||||
</form>
|
||||
<p th:if="${@endpointConfigurationService.isEndpointEnabled('pdf-to-rtf')}" class="mt-3" th:text="#{PDFToText.credit}"></p>
|
||||
<option th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" value="rtf">RTF</option>
|
||||
<option value="txt">TXT</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{PDFToText.submit}"></button>
|
||||
</form>
|
||||
<p th:if="${@endpointConfiguration.isEndpointEnabled('pdf-to-rtf')}" class="mt-3" th:text="#{PDFToText.credit}"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<div th:fragment="card" class="feature-card hidden" th:id="${id}" th:if="${@endpointConfigurationService.isEndpointEnabled(cardLink)} "
|
||||
<div th:fragment="card" class="feature-card hidden" th:id="${id}" th:if="${@endpointConfiguration.isEndpointEnabled(cardLink)} "
|
||||
th:data-bs-tags="${tags}"
|
||||
th:data-bs-link="@{${endpoint}}">
|
||||
<a th:href="${cardLink}">
|
||||
|
@ -5,6 +5,7 @@
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('zh_CN', '简体中文')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('zh_TW', '繁體中文')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('zh_BO', 'བོད་ཡིག')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('bo_CN', 'བོད་ཡིག')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('az_AZ', 'Azərbaycan Dili')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('da_DK', 'Dansk')}"></div>
|
||||
<div th:replace="~{fragments/languageEntry :: languageEntry ('de_DE', 'Deutsch')}"></div>
|
||||
|
@ -264,6 +264,215 @@
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('show-javascript', 'javascript', 'home.showJS.title', 'home.showJS.desc', 'showJS.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('eml-to-pdf', 'email', 'home.EMLToPDF.title', 'home.EMLToPDF.desc', 'EMLToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupConvertFrom" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-pdfa', 'picture_as_pdf', 'home.pdfToPDFA.title', 'home.pdfToPDFA.desc', 'pdfToPDFA.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-word', 'description', 'home.PDFToWord.title', 'home.PDFToWord.desc', 'PDFToWord.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-presentation', 'slideshow', 'home.PDFToPresentation.title', 'home.PDFToPresentation.desc', 'PDFToPresentation.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-text', 'text_fields', 'home.PDFToText.title', 'home.PDFToText.desc', 'PDFToText.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-html', 'html', 'home.PDFToHTML.title', 'home.PDFToHTML.desc', 'PDFToHTML.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-xml', 'code', 'home.PDFToXML.title', 'home.PDFToXML.desc', 'PDFToXML.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-csv', 'csv', 'home.tableExtraxt.title', 'home.tableExtraxt.desc', 'tableExtraxt.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry ('pdf-to-markdown', 'markdown_copy', 'home.PDFToMarkdown.title', 'home.PDFToMarkdown.desc', 'PDFToMarkdown.tags', 'convert')}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="convertGroup" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertTo})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('img-to-pdf', 'picture_as_pdf', 'home.imageToPdf.title', 'home.imageToPdf.desc', 'imageToPdf.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('file-to-pdf', 'draft', 'home.fileToPDF.title', 'home.fileToPDF.desc', 'fileToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('url-to-pdf', 'link', 'home.URLToPDF.title', 'home.URLToPDF.desc', 'URLToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('html-to-pdf', 'html', 'home.HTMLToPDF.title', 'home.HTMLToPDF.desc', 'HTMLToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('markdown-to-pdf', 'markdown', 'home.MarkdownToPDF.title', 'home.MarkdownToPDF.desc', 'MarkdownToPDF.tags', 'convertto')}">
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.convertFrom})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-img', 'photo_library', 'home.pdfToImage.title', 'home.pdfToImage.desc', 'pdfToImage.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-pdfa', 'picture_as_pdf', 'home.pdfToPDFA.title', 'home.pdfToPDFA.desc', 'pdfToPDFA.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-word', 'description', 'home.PDFToWord.title', 'home.PDFToWord.desc', 'PDFToWord.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-presentation', 'slideshow', 'home.PDFToPresentation.title', 'home.PDFToPresentation.desc', 'PDFToPresentation.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-text', 'text_fields', 'home.PDFToText.title', 'home.PDFToText.desc', 'PDFToText.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-html', 'html', 'home.PDFToHTML.title', 'home.PDFToHTML.desc', 'PDFToHTML.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-xml', 'code', 'home.PDFToXML.title', 'home.PDFToXML.desc', 'PDFToXML.tags', 'convert')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pdf-to-csv', 'csv', 'home.tableExtraxt.title', 'home.tableExtraxt.desc', 'tableExtraxt.tags', 'convert')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupSecurity" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.security})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-password', 'lock', 'home.addPassword.title', 'home.addPassword.desc', 'addPassword.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-password', 'lock_open_right', 'home.removePassword.title', 'home.removePassword.desc', 'removePassword.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('change-permissions', 'encrypted', 'home.permissions.title', 'home.permissions.desc', 'permissions.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('sign', 'signature', 'home.sign.title', 'home.sign.desc', 'sign.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('cert-sign', 'workspace_premium', 'home.certSign.title', 'home.certSign.desc', 'certSign.tags', 'security')}">
|
||||
</div>
|
||||
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('validate-signature', 'verified', 'home.validateSignature.title', 'home.validateSignature.desc', 'validateSignature.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-cert-sign', 'remove_moderator', 'home.removeCertSign.title', 'home.removeCertSign.desc', 'removeCertSign.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('sanitize-pdf', 'sanitizer', 'home.sanitizePdf.title', 'home.sanitizePdf.desc', 'sanitizePdf.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-redact', '/images/redact-auto.svg#icon-redact-auto', 'home.autoRedact.title', 'home.autoRedact.desc', 'autoRedact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('redact', '/images/redact-manual.svg#icon-redact-manual', 'home.redact.title', 'home.redact.desc', 'redact.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('stamp', 'approval', 'home.AddStampRequest.title', 'home.AddStampRequest.desc', 'AddStampRequest.tags', 'security')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-watermark', 'water_drop', 'home.watermark.title', 'home.watermark.desc', 'watermark.tags', 'security')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="groupView" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.edit})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('view-pdf', 'menu_book', 'home.viewPdf.title', 'home.viewPdf.desc', 'viewPdf.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-page-numbers', '123', 'home.add-page-numbers.title', 'home.add-page-numbers.desc', 'add-page-numbers.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('add-image', 'text_fields', 'home.addImage.title', 'home.addImage.desc', 'addImage.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('change-metadata', 'assignment', 'home.changeMetadata.title', 'home.changeMetadata.desc', 'changeMetadata.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('ocr-pdf', 'quick_reference_all', 'home.ocr.title', 'home.ocr.desc', 'ocr.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('extract-images', 'photo_library', 'home.extractImages.title', 'home.extractImages.desc', 'extractImages.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('flatten', 'layers_clear', 'home.flatten.title', 'home.flatten.desc', 'flatten.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-blanks', 'scan_delete', 'home.removeBlanks.title', 'home.removeBlanks.desc', 'removeBlanks.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-annotations', 'thread_unread', 'home.removeAnnotations.title', 'home.removeAnnotations.desc', 'removeAnnotations.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('compare', 'compare', 'home.compare.title', 'home.compare.desc', 'compare.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('get-info-on-pdf', 'info', 'home.getPdfInfo.title', 'home.getPdfInfo.desc', 'getPdfInfo.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('remove-image-pdf', 'remove_selection', 'home.removeImagePdf.title', 'home.removeImagePdf.desc', 'removeImagePdf.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('replace-and-invert-color-pdf', 'format_color_fill', 'home.replaceColorPdf.title', 'home.replaceColorPdf.desc', 'replaceColorPdf.tags', 'other')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('unlock-pdf-forms', 'preview_off', 'home.unlockPDFForms.title', 'home.unlockPDFForms.desc', 'unlockPDFForms.tags', 'other')}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="groupAdvanced" class="feature-group">
|
||||
<div th:replace="~{fragments/featureGroupHeader :: featureGroupHeader(groupTitle=#{navbar.sections.advance})}">
|
||||
</div>
|
||||
<div class="nav-group-container">
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('pipeline', 'family_history', 'home.pipeline.title', 'home.pipeline.desc', 'pipeline.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('adjust-contrast', 'palette', 'home.adjust-contrast.title', 'home.adjust-contrast.desc', 'adjust-contrast.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('compress-pdf', 'zoom_in_map', 'home.compressPdfs.title', 'home.compressPdfs.desc', 'compressPdfs.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('extract-image-scans', 'scanner', 'home.ScannerImageSplit.title', 'home.ScannerImageSplit.desc', 'ScannerImageSplit.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('repair', 'build', 'home.repair.title', 'home.repair.desc', 'repair.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-rename', '/images/rename.svg#icon-rename', 'home.auto-rename.title', 'home.auto-rename.desc', 'auto-rename.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('auto-split-pdf', '/images/split-auto.svg#icon-split-auto', 'home.autoSplitPDF.title', 'home.autoSplitPDF.desc', 'autoSplitPDF.tags', 'advance')}">
|
||||
</div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntry :: navbarEntry('show-javascript', 'javascript', 'home.showJS.title', 'home.showJS.desc', 'showJS.tags', 'advance')}">
|
||||
</div>
|
||||
<div th:replace="~{fragments/navbarEntry :: navbarEntry('fake-scan', 'scanner', 'fakeScan.title', 'fakeScan.description', 'fakeScan.tags', 'advance')}"></div>
|
||||
<div
|
||||
th:replace="~{fragments/navbarEntryCustom :: navbarEntry('split-by-size-or-count', '/images/split-size.svg#icon-split-size', 'home.autoSizeSplitPDF.title', 'home.autoSizeSplitPDF.desc', 'autoSizeSplitPDF.tags', 'advance')}">
|
||||
</div>
|
||||
|
@ -78,6 +78,27 @@
|
||||
</li>
|
||||
|
||||
<li class="nav-item" th:if="${@endpointConfigurationService.isEndpointEnabled('compress-pdf')}">
|
||||
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('multi-tool')}">
|
||||
<a class="nav-link" href="#" th:href="@{'/multi-tool'}"
|
||||
th:classappend="${currentPage}=='multi-tool' ? 'active' : ''" th:title="#{home.multiTool.desc}">
|
||||
<span class="material-symbols-rounded">
|
||||
construction
|
||||
</span>
|
||||
<span class="icon-text" th:data-text="#{navbar.multiTool}" th:text="#{navbar.multiTool}"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}">
|
||||
<a class="nav-link" href="#" th:href="@{'/pipeline'}"
|
||||
th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
|
||||
<span class="material-symbols-rounded">
|
||||
family_history
|
||||
</span>
|
||||
<span class="icon-text" th:data-text="#{home.pipeline.title}" th:text="#{home.pipeline.title}"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" th:if="${@endpointConfiguration.isEndpointEnabled('compress-pdf')}">
|
||||
<a class="nav-link" href="#" title="#{home.compressPdfs.title}" th:href="@{'/compress-pdf'}"
|
||||
th:classappend="${currentPage}=='compress-pdf' ? 'active' : ''" th:title="#{home.compressPdfs.desc}">
|
||||
<span class="material-symbols-rounded">
|
||||
|
@ -15,4 +15,21 @@ th:if="${@endpointConfigurationService.isEndpointEnabled(endpoint)}">
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</th:block>
|
||||
th:if="${@endpointConfiguration.isEndpointEnabled(endpoint)}">
|
||||
<a th:id="@{${endpoint}}" class="dropdown-item" style="position:relative" th:href="@{${endpoint}}"
|
||||
th:data-bs-link="@{${endpoint}}"
|
||||
th:classappend="${endpoint.equals(currentPage)} ? ${toolGroup} + ' active' : '' + ${toolGroup}"
|
||||
th:data-bs-tags="#{${tagKey}}" th:data-bs-title='#{${titleKey}}'>
|
||||
<div style="min-height:2.7rem; align-items: center;display: flex;" th:title="#{${descKey}}" class="icon" alt="icon"
|
||||
th:class="@{${toolGroup}}">
|
||||
<span class="material-symbols-rounded nav-icon" th:text="@{${toolIcon}}" style=" align-items:center; display: flex; justify-content: center; height:2.7rem; width:2.7rem"></span>
|
||||
<span class="icon-text" th:text="#{${titleKey}}"></span>
|
||||
</div>
|
||||
<span class="material-symbols-rounded favorite-icon" style="display: none;" th:data-endpoint="@{${endpoint}}"
|
||||
th:onclick="'addToFavorites(\'' + @{${endpoint}} + '\')'">
|
||||
add
|
||||
</span>
|
||||
</a>
|
||||
|
||||
</th:block>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<th:block th:fragment="navbarEntry(endpoint, toolIcon, titleKey, descKey, tagKey, toolGroup)"
|
||||
th:if="${@endpointConfigurationService.isEndpointEnabled(endpoint)}">
|
||||
th:if="${@endpointConfiguration.isEndpointEnabled(endpoint)}">
|
||||
<a th:id="@{${endpoint}}" class="dropdown-item" style="position:relative" th:href="@{${endpoint}}"
|
||||
th:data-bs-link="@{${endpoint}}"
|
||||
th:classappend="${endpoint.equals(currentPage)} ? ${toolGroup} + ' active' : '' + ${toolGroup}"
|
||||
|
@ -94,6 +94,526 @@
|
||||
} else {
|
||||
h5Elem.textContent = `${key}: ${String(value)}`;
|
||||
}
|
||||
<div class="col-md-7 bg-card">
|
||||
<div class="tool-header">
|
||||
<span class="material-symbols-rounded tool-header-icon other">info</span>
|
||||
<span class="tool-header-text" th:text="#{getPdfInfo.header}"></span>
|
||||
</div>
|
||||
<form id="pdfInfoForm" method="post" enctype="multipart/form-data" th:action="@{'/api/v1/security/get-info-on-pdf'}">
|
||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multipleInputsForSingleRequest=false, remoteCall='false', accept='application/pdf')}"></div>
|
||||
|
||||
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{getPdfInfo.submit}"></button>
|
||||
</form>
|
||||
<div class="container mt-0">
|
||||
<!-- PDF Summary section -->
|
||||
<div id="pdf-summary" class="card mt-3 mb-3" style="display: none;">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0" id="summary-heading">PDF Summary</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Quick overview of key details -->
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h6 id="summary-basic-info-heading">Basic Information</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><strong>Pages:</strong> <span id="summary-pages">-</span></li>
|
||||
<li><strong>File Size:</strong> <span id="summary-size">-</span></li>
|
||||
<li><strong>PDF Version:</strong> <span id="summary-version">-</span></li>
|
||||
<li><strong>Language:</strong> <span id="summary-language">-</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<h6 id="summary-doc-info-heading">Document Information</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><strong>Title:</strong> <span id="summary-title">-</span></li>
|
||||
<li><strong>Author:</strong> <span id="summary-author">-</span></li>
|
||||
<li><strong>Created:</strong> <span id="summary-created">-</span></li>
|
||||
<li><strong>Modified:</strong> <span id="summary-modified">-</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Security section -->
|
||||
<div class="mt-4 mb-3">
|
||||
<h6 id="summary-security-heading">Security Status</h6>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div id="encryption-status" class="card mb-2 h-100">
|
||||
<div class="card-body p-2 d-flex align-items-center">
|
||||
<span id="encryption-icon" class="me-2"><i class="bi bi-lock"></i></span>
|
||||
<span id="encryption-text" class="small">Encryption: Unknown</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div id="permissions-status" class="card mb-2 h-100">
|
||||
<div class="card-body p-2 d-flex align-items-center">
|
||||
<span id="permissions-icon" class="me-2"><i class="bi bi-shield"></i></span>
|
||||
<span id="permissions-text" class="small">Permissions: Unknown</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div id="compliance-status" class="card mb-2 h-100">
|
||||
<div class="card-body p-2 d-flex align-items-center">
|
||||
<span id="compliance-icon" class="me-2"><i class="bi bi-check-circle"></i></span>
|
||||
<span id="compliance-text" class="small">Compliance: Unknown</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Detailed alerts -->
|
||||
<div id="summary-alerts" class="mt-3">
|
||||
<!-- Will be populated with detailed alerts for encryption, permissions, etc. -->
|
||||
</div>
|
||||
|
||||
<!-- Descriptive note about PDF characteristics -->
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h6 class="mb-0">PDF Overview</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p id="summary-text" class="mb-0"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Iterate over each main section in the JSON -->
|
||||
<div id="json-content">
|
||||
<!-- JavaScript will populate this section -->
|
||||
</div>
|
||||
|
||||
<!-- Button to download the JSON -->
|
||||
<a href="#" id="downloadJson" class="btn btn-primary mt-3" style="display: none;" th:text="#{getPdfInfo.downloadJson}">Download JSON</a>
|
||||
</div>
|
||||
<script th:src="@{'/js/fetch-utils.js'}"></script>
|
||||
<script th:inline="javascript">
|
||||
// Pre-load message translations
|
||||
const getPdfInfoSummary = /*[[#{getPdfInfo.summary}]]*/ "PDF Summary";
|
||||
const getPdfInfoSummaryEncrypted = /*[[#{getPdfInfo.summary.encrypted}]]*/ "This PDF is encrypted so may face issues with some applications";
|
||||
const getPdfInfoSummaryPermissions = /*[[#{getPdfInfo.summary.permissions}]]*/ "This PDF has {0} restricted permissions which may limit what you can do with it";
|
||||
const getPdfInfoSummaryCompliance = /*[[#{getPdfInfo.summary.compliance}]]*/ "This PDF complies with the {0} standard, meaning it is suitable for {1}";
|
||||
const getPdfInfoSummaryBasicInfo = /*[[#{getPdfInfo.summary.basicInfo}]]*/ "Basic Information";
|
||||
const getPdfInfoSummaryDocInfo = /*[[#{getPdfInfo.summary.docInfo}]]*/ "Document Information";
|
||||
const getPdfInfoSummarySecuritySection = /*[[#{getPdfInfo.summary.security.section}]]*/ "Security Status";
|
||||
const getPdfInfoSummaryEncryptedAlert = /*[[#{getPdfInfo.summary.encrypted.alert}]]*/ "Encrypted PDF - This document is password protected";
|
||||
const getPdfInfoSummaryNotEncryptedAlert = /*[[#{getPdfInfo.summary.not.encrypted.alert}]]*/ "Unencrypted PDF - No password protection";
|
||||
const getPdfInfoSummaryPermissionsAlert = /*[[#{getPdfInfo.summary.permissions.alert}]]*/ "Restricted Permissions - {0} actions are not allowed";
|
||||
const getPdfInfoSummaryAllPermissionsAlert = /*[[#{getPdfInfo.summary.all.permissions.alert}]]*/ "All Permissions Allowed";
|
||||
const getPdfInfoSummaryComplianceAlert = /*[[#{getPdfInfo.summary.compliance.alert}]]*/ "{0} Compliant";
|
||||
const getPdfInfoSummaryNoComplianceAlert = /*[[#{getPdfInfo.summary.no.compliance.alert}]]*/ "No Compliance Standards";
|
||||
|
||||
// Update the summary headings
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.getElementById('summary-heading').textContent = getPdfInfoSummary;
|
||||
document.getElementById('summary-basic-info-heading').textContent = getPdfInfoSummaryBasicInfo;
|
||||
document.getElementById('summary-doc-info-heading').textContent = getPdfInfoSummaryDocInfo;
|
||||
document.getElementById('summary-security-heading').textContent = getPdfInfoSummarySecuritySection;
|
||||
});
|
||||
|
||||
// Pre-load section descriptions
|
||||
const getPdfInfoSectionBasicInfo = /*[[#{getPdfInfo.section.BasicInfo}]]*/ "Basic Information about the PDF document including file size, page count, and language";
|
||||
const getPdfInfoSectionMetadata = /*[[#{getPdfInfo.section.Metadata}]]*/ "Document metadata including title, author, creation date and other document properties";
|
||||
const getPdfInfoSectionDocumentInfo = /*[[#{getPdfInfo.section.DocumentInfo}]]*/ "Technical details about the PDF document structure and version";
|
||||
const getPdfInfoSectionCompliancy = /*[[#{getPdfInfo.section.Compliancy}]]*/ "PDF standards compliance information (PDF/A, PDF/X, etc.)";
|
||||
const getPdfInfoSectionEncryption = /*[[#{getPdfInfo.section.Encryption}]]*/ "Security and encryption details of the document";
|
||||
const getPdfInfoSectionPermissions = /*[[#{getPdfInfo.section.Permissions}]]*/ "Document permission settings that control what actions can be performed";
|
||||
const getPdfInfoSectionOther = /*[[#{getPdfInfo.section.Other}]]*/ "Additional document components like bookmarks, layers, and embedded files";
|
||||
const getPdfInfoSectionFormFields = /*[[#{getPdfInfo.section.FormFields}]]*/ "Interactive form fields present in the document";
|
||||
const getPdfInfoSectionPerPageInfo = /*[[#{getPdfInfo.section.PerPageInfo}]]*/ "Detailed information about each page in the document";
|
||||
|
||||
document.getElementById("pdfInfoForm").addEventListener("submit", function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Clear previous results when submitting a new form
|
||||
document.getElementById('json-content').innerHTML = '';
|
||||
document.getElementById('pdf-summary').style.display = 'none';
|
||||
document.getElementById('downloadJson').style.display = 'none';
|
||||
|
||||
const formData = new FormData(event.target);
|
||||
|
||||
fetchWithCsrf('api/v1/security/get-info-on-pdf', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
}).then(response => response.json()).then(data => {
|
||||
// Populate and display the enhanced PDF summary
|
||||
populateSummarySection(data);
|
||||
|
||||
displayJsonData(data);
|
||||
setDownloadLink(data);
|
||||
document.getElementById("downloadJson").style.display = "block";
|
||||
}).catch(error => console.error('Error:', error));
|
||||
|
||||
// Function to reset all summary elements to default state
|
||||
function resetSummaryElements() {
|
||||
// Reset basic information fields
|
||||
document.getElementById('summary-pages').textContent = '-';
|
||||
document.getElementById('summary-size').textContent = '-';
|
||||
document.getElementById('summary-version').textContent = '-';
|
||||
document.getElementById('summary-language').textContent = '-';
|
||||
|
||||
// Reset document information fields
|
||||
document.getElementById('summary-title').textContent = '-';
|
||||
document.getElementById('summary-author').textContent = '-';
|
||||
document.getElementById('summary-created').textContent = '-';
|
||||
document.getElementById('summary-modified').textContent = '-';
|
||||
|
||||
// Reset security status cards
|
||||
const cards = ['encryption-status', 'permissions-status', 'compliance-status'];
|
||||
cards.forEach(id => {
|
||||
const card = document.getElementById(id);
|
||||
// Remove all classes except the base ones
|
||||
card.className = 'card mb-2 h-100';
|
||||
});
|
||||
|
||||
// Reset status text and icons
|
||||
document.getElementById('encryption-icon').innerHTML = '<i class="bi bi-lock"></i>';
|
||||
document.getElementById('encryption-text').textContent = 'Encryption: Unknown';
|
||||
|
||||
document.getElementById('permissions-icon').innerHTML = '<i class="bi bi-shield"></i>';
|
||||
document.getElementById('permissions-text').textContent = 'Permissions: Unknown';
|
||||
|
||||
document.getElementById('compliance-icon').innerHTML = '<i class="bi bi-check-circle"></i>';
|
||||
document.getElementById('compliance-text').textContent = 'Compliance: Unknown';
|
||||
|
||||
// Clear alerts container
|
||||
document.getElementById('summary-alerts').innerHTML = '';
|
||||
|
||||
// Reset summary text
|
||||
document.getElementById('summary-text').innerHTML = '';
|
||||
}
|
||||
|
||||
// Function to populate the enhanced summary section
|
||||
function populateSummarySection(data) {
|
||||
// Reset all elements first
|
||||
resetSummaryElements();
|
||||
|
||||
// Get basic information
|
||||
if (data.BasicInfo) {
|
||||
document.getElementById('summary-pages').textContent = data.BasicInfo["Number of pages"] || "-";
|
||||
|
||||
// Format file size nicely
|
||||
let fileSize = data.BasicInfo["FileSizeInBytes"];
|
||||
if (fileSize) {
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
const i = Math.floor(Math.log(fileSize) / Math.log(1024));
|
||||
fileSize = (fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
|
||||
document.getElementById('summary-size').textContent = fileSize;
|
||||
}
|
||||
|
||||
document.getElementById('summary-language').textContent = data.BasicInfo["Language"] || "-";
|
||||
}
|
||||
|
||||
// Get document information
|
||||
if (data.DocumentInfo) {
|
||||
document.getElementById('summary-version').textContent = data.DocumentInfo["PDF version"] || "-";
|
||||
}
|
||||
|
||||
// Get metadata
|
||||
if (data.Metadata) {
|
||||
document.getElementById('summary-title').textContent = data.Metadata["Title"] || "-";
|
||||
document.getElementById('summary-author').textContent = data.Metadata["Author"] || "-";
|
||||
document.getElementById('summary-created').textContent = data.Metadata["CreationDate"] || "-";
|
||||
document.getElementById('summary-modified').textContent = data.Metadata["ModificationDate"] || "-";
|
||||
}
|
||||
|
||||
// Update security status cards
|
||||
|
||||
// Encryption status
|
||||
const encryptionStatusCard = document.getElementById('encryption-status');
|
||||
const encryptionIcon = document.getElementById('encryption-icon');
|
||||
const encryptionText = document.getElementById('encryption-text');
|
||||
|
||||
if (data.Encryption && data.Encryption.IsEncrypted) {
|
||||
encryptionIcon.innerHTML = '<i class="bi bi-lock-fill"></i>';
|
||||
encryptionText.textContent = getPdfInfoSummaryEncryptedAlert;
|
||||
} else {
|
||||
encryptionIcon.innerHTML = '<i class="bi bi-unlock-fill"></i>';
|
||||
encryptionText.textContent = getPdfInfoSummaryNotEncryptedAlert;
|
||||
}
|
||||
|
||||
// Permissions status
|
||||
const permissionsStatusCard = document.getElementById('permissions-status');
|
||||
const permissionsIcon = document.getElementById('permissions-icon');
|
||||
const permissionsText = document.getElementById('permissions-text');
|
||||
|
||||
let restrictedPermissions = [];
|
||||
if (data.Permissions) {
|
||||
for (const [permission, state] of Object.entries(data.Permissions)) {
|
||||
if (state === "Not Allowed") {
|
||||
restrictedPermissions.push(permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictedPermissions.length > 0) {
|
||||
permissionsIcon.innerHTML = '<i class="bi bi-shield-lock-fill"></i>';
|
||||
const formattedAlert = getPdfInfoSummaryPermissionsAlert.replace('{0}', restrictedPermissions.length);
|
||||
permissionsText.textContent = formattedAlert;
|
||||
} else {
|
||||
permissionsIcon.innerHTML = '<i class="bi bi-shield-check"></i>';
|
||||
permissionsText.textContent = getPdfInfoSummaryAllPermissionsAlert;
|
||||
}
|
||||
|
||||
// Compliance status
|
||||
const complianceStatusCard = document.getElementById('compliance-status');
|
||||
const complianceIcon = document.getElementById('compliance-icon');
|
||||
const complianceText = document.getElementById('compliance-text');
|
||||
|
||||
let hasCompliance = false;
|
||||
let compliantStandards = [];
|
||||
|
||||
if (data.Compliancy) {
|
||||
for (const [standard, compliant] of Object.entries(data.Compliancy)) {
|
||||
if (compliant === true) {
|
||||
hasCompliance = true;
|
||||
const standardName = standard.replace("Is", "").replace("Compliant", "");
|
||||
compliantStandards.push(standardName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCompliance) {
|
||||
complianceIcon.innerHTML = '<i class="bi bi-check-circle-fill"></i>';
|
||||
const formattedAlert = getPdfInfoSummaryComplianceAlert.replace('{0}', compliantStandards.join(', '));
|
||||
complianceText.textContent = formattedAlert;
|
||||
} else {
|
||||
complianceIcon.innerHTML = '<i class="bi bi-dash-circle"></i>';
|
||||
complianceText.textContent = getPdfInfoSummaryNoComplianceAlert;
|
||||
}
|
||||
|
||||
// Create detailed characteristic alerts
|
||||
const alertsContainer = document.getElementById('summary-alerts');
|
||||
|
||||
// Clear previous alerts
|
||||
alertsContainer.innerHTML = '';
|
||||
|
||||
// Create a single comprehensive security details section
|
||||
let hasSummaryInfo = false;
|
||||
|
||||
// Create a consolidated security details card if there are security details worth highlighting
|
||||
if ((data.Encryption && data.Encryption.IsEncrypted) ||
|
||||
restrictedPermissions.length > 0 ||
|
||||
hasCompliance) {
|
||||
|
||||
const securityDetailsCard = document.createElement('div');
|
||||
securityDetailsCard.className = 'card mt-3 mb-3';
|
||||
|
||||
const cardHeader = document.createElement('div');
|
||||
cardHeader.className = 'card-header';
|
||||
cardHeader.innerHTML = '<h6 class="mb-0">Detailed Security Information</h6>';
|
||||
securityDetailsCard.appendChild(cardHeader);
|
||||
|
||||
const cardBody = document.createElement('div');
|
||||
cardBody.className = 'card-body';
|
||||
|
||||
// Add detailed encryption info
|
||||
if (data.Encryption && data.Encryption.IsEncrypted) {
|
||||
const encryptionDiv = document.createElement('div');
|
||||
encryptionDiv.className = 'mb-3';
|
||||
encryptionDiv.innerHTML = '<h6>Encryption Details:</h6>';
|
||||
|
||||
const encryptionList = document.createElement('ul');
|
||||
encryptionList.className = 'list-unstyled';
|
||||
|
||||
if (data.Encryption.EncryptionAlgorithm) {
|
||||
encryptionList.innerHTML += `<li><strong>Algorithm:</strong> ${data.Encryption.EncryptionAlgorithm}</li>`;
|
||||
}
|
||||
if (data.Encryption.KeyLength) {
|
||||
encryptionList.innerHTML += `<li><strong>Key Length:</strong> ${data.Encryption.KeyLength} bits</li>`;
|
||||
}
|
||||
|
||||
encryptionDiv.appendChild(encryptionList);
|
||||
cardBody.appendChild(encryptionDiv);
|
||||
hasSummaryInfo = true;
|
||||
}
|
||||
|
||||
// Add detailed permissions info
|
||||
if (restrictedPermissions.length > 0) {
|
||||
const permissionsDiv = document.createElement('div');
|
||||
permissionsDiv.className = 'mb-3';
|
||||
permissionsDiv.innerHTML = '<h6>Restricted Permissions:</h6>';
|
||||
|
||||
const permissionsList = document.createElement('ul');
|
||||
restrictedPermissions.forEach(perm => {
|
||||
permissionsList.innerHTML += `<li>${perm}</li>`;
|
||||
});
|
||||
|
||||
permissionsDiv.appendChild(permissionsList);
|
||||
cardBody.appendChild(permissionsDiv);
|
||||
hasSummaryInfo = true;
|
||||
}
|
||||
|
||||
// Add detailed compliance info
|
||||
if (hasCompliance) {
|
||||
const complianceDiv = document.createElement('div');
|
||||
complianceDiv.className = 'mb-3';
|
||||
complianceDiv.innerHTML = '<h6>Standards Compliance:</h6>';
|
||||
|
||||
const complianceList = document.createElement('ul');
|
||||
complianceList.className = 'list-unstyled';
|
||||
|
||||
compliantStandards.forEach(standard => {
|
||||
let standardDescription = '';
|
||||
|
||||
// Add brief descriptions for standards
|
||||
if (standard === "PDF/A") {
|
||||
standardDescription = 'ISO standard for long-term document archiving';
|
||||
} else if (standard === "PDF/X") {
|
||||
standardDescription = 'ISO standard for printing and graphic arts exchange';
|
||||
} else if (standard === "PDF/UA") {
|
||||
standardDescription = 'ISO standard for universal accessibility';
|
||||
} else if (standard === "PDF/E") {
|
||||
standardDescription = 'ISO standard for engineering documents';
|
||||
} else if (standard === "PDF/VT") {
|
||||
standardDescription = 'ISO standard for variable and transactional printing';
|
||||
}
|
||||
|
||||
complianceList.innerHTML += `<li><strong>${standard}:</strong> ${standardDescription}</li>`;
|
||||
});
|
||||
|
||||
complianceDiv.appendChild(complianceList);
|
||||
cardBody.appendChild(complianceDiv);
|
||||
hasSummaryInfo = true;
|
||||
}
|
||||
|
||||
securityDetailsCard.appendChild(cardBody);
|
||||
|
||||
if (hasSummaryInfo) {
|
||||
alertsContainer.appendChild(securityDetailsCard);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a general document summary
|
||||
const summaryTextElement = document.getElementById('summary-text');
|
||||
|
||||
// Create a general summary for the document
|
||||
let generalSummary = `This is a ${data.BasicInfo["Number of pages"] || "multi"}-page PDF`;
|
||||
|
||||
if (data.Metadata && data.Metadata["Title"]) {
|
||||
generalSummary += ` titled "${data.Metadata["Title"]}"`;
|
||||
}
|
||||
|
||||
if (data.Metadata && data.Metadata["Author"]) {
|
||||
generalSummary += ` created by ${data.Metadata["Author"]}`;
|
||||
}
|
||||
|
||||
if (data.DocumentInfo && data.DocumentInfo["PDF version"]) {
|
||||
generalSummary += ` (PDF version ${data.DocumentInfo["PDF version"]})`;
|
||||
}
|
||||
|
||||
// Add security information to the general summary if relevant
|
||||
if (data.Encryption && data.Encryption.IsEncrypted) {
|
||||
generalSummary += '. The document is password protected';
|
||||
|
||||
if (data.Encryption.EncryptionAlgorithm) {
|
||||
generalSummary += ` using ${data.Encryption.EncryptionAlgorithm}`;
|
||||
|
||||
if (data.Encryption.KeyLength) {
|
||||
generalSummary += ` (${data.Encryption.KeyLength} bit)`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictedPermissions.length > 0) {
|
||||
generalSummary += `. It has ${restrictedPermissions.length} restricted permissions`;
|
||||
}
|
||||
|
||||
// Add compliance standards if available
|
||||
if (hasCompliance && compliantStandards.length > 0) {
|
||||
generalSummary += `. This document complies with the ${compliantStandards.join(', ')} PDF standard${compliantStandards.length > 1 ? 's' : ''}`;
|
||||
}
|
||||
|
||||
generalSummary += '.';
|
||||
|
||||
// Remove SummaryData from JSON to avoid duplication
|
||||
if (data.SummaryData) {
|
||||
delete data.SummaryData;
|
||||
}
|
||||
|
||||
summaryTextElement.innerHTML = generalSummary;
|
||||
|
||||
// Display the summary section
|
||||
document.getElementById('pdf-summary').style.display = 'block';
|
||||
}
|
||||
|
||||
function generateSummaryFromData(summaryData) {
|
||||
let summary = [];
|
||||
|
||||
// Handle encryption information
|
||||
if (summaryData.encrypted) {
|
||||
summary.push(getPdfInfoSummaryEncrypted);
|
||||
}
|
||||
|
||||
// Handle permissions information
|
||||
if (summaryData.restrictedPermissions && summaryData.restrictedPermissions.length > 0) {
|
||||
const formattedPermissionsText = getPdfInfoSummaryPermissions.replace('{0}', summaryData.restrictedPermissionsCount);
|
||||
summary.push(formattedPermissionsText);
|
||||
}
|
||||
|
||||
// Handle standard compliance information
|
||||
if (summaryData.standardCompliance) {
|
||||
const formattedComplianceText = getPdfInfoSummaryCompliance
|
||||
.replace('{0}', summaryData.standardCompliance);
|
||||
summary.push(formattedComplianceText);
|
||||
}
|
||||
|
||||
return summary.join(' ');
|
||||
}
|
||||
});
|
||||
|
||||
function displayJsonData(jsonData) {
|
||||
const jsonContent = document.getElementById('json-content');
|
||||
|
||||
while (jsonContent.firstChild) {
|
||||
jsonContent.removeChild(jsonContent.firstChild);
|
||||
}
|
||||
|
||||
for (const key in jsonData) {
|
||||
const sectionElem = createJsonSection(key, jsonData[key]);
|
||||
jsonContent.appendChild(sectionElem);
|
||||
}
|
||||
}
|
||||
|
||||
function setDownloadLink(jsonData) {
|
||||
const downloadLink = document.getElementById('downloadJson');
|
||||
const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonData, null, 4));
|
||||
downloadLink.setAttribute("href", dataStr);
|
||||
downloadLink.setAttribute("download", "data.json");
|
||||
}
|
||||
|
||||
function createJsonSection(key, value, depth = 0) {
|
||||
let safeKey = (typeof key === "string") ? key.replace(/[^a-zA-Z0-9]/g, '_') : key;
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card mb-3';
|
||||
|
||||
const header = document.createElement('div');
|
||||
header.className = 'card-header';
|
||||
header.id = `${safeKey}-heading-${depth}`;
|
||||
const h5Elem = document.createElement('h5');
|
||||
h5Elem.className = 'mb-0 d-flex align-items-center';
|
||||
|
||||
// Create the main content (button or text)
|
||||
if (key === 'XMPMetadata' && typeof value === "string") {
|
||||
const buttonElem = createButtonElement(key, safeKey, depth);
|
||||
h5Elem.appendChild(buttonElem);
|
||||
} else if (value && typeof value === 'object') {
|
||||
if (Array.isArray(value) && value.length === 0) {
|
||||
h5Elem.textContent = `${key}: Empty array`;
|
||||
} else if (!Array.isArray(value) && Object.keys(value).length === 0) {
|
||||
h5Elem.textContent = `${key}: Empty object`;
|
||||
} else {
|
||||
const buttonElem = createButtonElement(key, safeKey, depth);
|
||||
h5Elem.appendChild(buttonElem);
|
||||
}
|
||||
} else {
|
||||
h5Elem.textContent = `${key}: ${String(value)}`;
|
||||
}
|
||||
|
||||
// Info buttons removed as requested
|
||||
|
||||
header.appendChild(h5Elem);
|
||||
card.appendChild(header);
|
||||
|
Loading…
x
Reference in New Issue
Block a user