Compare commits
6 Commits
c6cd766e66
...
20c66ac19b
Author | SHA1 | Date |
---|---|---|
dependabot[bot] | 20c66ac19b | |
dependabot[bot] | 86971e7dd5 | |
github-actions[bot] | 4fea8d10f8 | |
Anthony Stirling | 8c9d6f7b66 | |
Anthony Stirling | 30444fc9bb | |
Han | 70349d642b |
|
@ -201,7 +201,7 @@ Stirling PDF allows easy customization of the app.
|
||||||
Includes things like
|
Includes things like
|
||||||
|
|
||||||
- Custom application name
|
- Custom application name
|
||||||
- Custom slogans, icons, images, and even custom HTML (via file overrides)
|
- Custom slogans, icons, HTML, images CSS etc (via file overrides)
|
||||||
|
|
||||||
There are two options for this, either using the generated settings file ``settings.yml``
|
There are two options for this, either using the generated settings file ``settings.yml``
|
||||||
This file is located in the ``/configs`` directory and follows standard YAML formatting
|
This file is located in the ``/configs`` directory and follows standard YAML formatting
|
||||||
|
@ -229,6 +229,7 @@ system:
|
||||||
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files
|
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files
|
||||||
showUpdate: true # see when a new update is available
|
showUpdate: true # see when a new update is available
|
||||||
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
||||||
|
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
|
||||||
|
|
||||||
#ui:
|
#ui:
|
||||||
# appName: exampleAppName # Application's visible name
|
# appName: exampleAppName # Application's visible name
|
||||||
|
|
|
@ -12,7 +12,7 @@ plugins {
|
||||||
import com.github.jk1.license.render.*
|
import com.github.jk1.license.render.*
|
||||||
|
|
||||||
group = 'stirling.software'
|
group = 'stirling.software'
|
||||||
version = '0.23.0'
|
version = '0.23.1'
|
||||||
sourceCompatibility = '17'
|
sourceCompatibility = '17'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -145,7 +145,7 @@ dependencies {
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
exclude group: 'commons-logging', module: 'commons-logging'
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation 'org.bouncycastle:bcprov-jdk18on:1.77'
|
implementation 'org.bouncycastle:bcprov-jdk18on:1.78.1'
|
||||||
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
|
implementation 'org.bouncycastle:bcpkix-jdk18on:1.77'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.4'
|
implementation 'org.springframework.boot:spring-boot-starter-actuator:3.2.4'
|
||||||
implementation 'io.micrometer:micrometer-core:1.12.4'
|
implementation 'io.micrometer:micrometer-core:1.12.4'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
appVersion: 0.23.0
|
appVersion: 0.23.1
|
||||||
description: locally hosted web application that allows you to perform various operations
|
description: locally hosted web application that allows you to perform various operations
|
||||||
on PDF files
|
on PDF files
|
||||||
home: https://github.com/Stirling-Tools/Stirling-PDF
|
home: https://github.com/Stirling-Tools/Stirling-PDF
|
||||||
|
|
|
@ -7,18 +7,34 @@ import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.thymeleaf.spring6.SpringTemplateEngine;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Lazy
|
||||||
public class AppConfig {
|
public class AppConfig {
|
||||||
|
|
||||||
@Autowired ApplicationProperties applicationProperties;
|
@Autowired ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnProperty(
|
||||||
|
name = "system.customHTMLFiles",
|
||||||
|
havingValue = "true",
|
||||||
|
matchIfMissing = false)
|
||||||
|
public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
|
||||||
|
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
|
||||||
|
templateEngine.addTemplateResolver(new FileFallbackTemplateResolver(resourceLoader));
|
||||||
|
return templateEngine;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean(name = "loginEnabled")
|
@Bean(name = "loginEnabled")
|
||||||
public boolean loginEnabled() {
|
public boolean loginEnabled() {
|
||||||
return applicationProperties.getSecurity().getEnableLogin();
|
return applicationProperties.getSecurity().getEnableLogin();
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.thymeleaf.IEngineConfiguration;
|
||||||
|
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
|
||||||
|
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
|
||||||
|
import org.thymeleaf.templateresource.FileTemplateResource;
|
||||||
|
import org.thymeleaf.templateresource.ITemplateResource;
|
||||||
|
|
||||||
|
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
public FileFallbackTemplateResolver(ResourceLoader resourceLoader) {
|
||||||
|
super();
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
setSuffix(".html");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note this does not work in local IDE, Prod jar only.
|
||||||
|
@Override
|
||||||
|
protected ITemplateResource computeTemplateResource(
|
||||||
|
IEngineConfiguration configuration,
|
||||||
|
String ownerTemplate,
|
||||||
|
String template,
|
||||||
|
String resourceName,
|
||||||
|
String characterEncoding,
|
||||||
|
Map<String, Object> templateResolutionAttributes) {
|
||||||
|
Resource resource =
|
||||||
|
resourceLoader.getResource("file:./customFiles/templates/" + resourceName);
|
||||||
|
try {
|
||||||
|
if (resource.exists() && resource.isReadable()) {
|
||||||
|
return new FileTemplateResource(resource.getFile().getPath(), characterEncoding);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ClassLoaderTemplateResource(
|
||||||
|
Thread.currentThread().getContextClassLoader(),
|
||||||
|
"classpath:/templates/" + resourceName,
|
||||||
|
characterEncoding);
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.github.pixee.security.Filenames;
|
import io.github.pixee.security.Filenames;
|
||||||
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
@ -51,7 +52,9 @@ public class FakeScanControllerWIP {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
|
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
|
||||||
|
|
||||||
|
// TODO finish
|
||||||
@PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
|
@PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
|
||||||
|
@Hidden
|
||||||
@Operation(
|
@Operation(
|
||||||
summary = "Repair a PDF file",
|
summary = "Repair a PDF file",
|
||||||
description =
|
description =
|
||||||
|
@ -94,14 +97,13 @@ public class FakeScanControllerWIP {
|
||||||
public BufferedImage processImage(BufferedImage image) {
|
public BufferedImage processImage(BufferedImage image) {
|
||||||
// Rotation
|
// Rotation
|
||||||
|
|
||||||
addDustAndHairs(image, 50);
|
image = softenEdges(image, 50);
|
||||||
// image = rotate(image, 1);
|
image = rotate(image, 1);
|
||||||
|
|
||||||
// image = softenEdges(image, 5);
|
|
||||||
image = applyGaussianBlur(image, 0.5);
|
image = applyGaussianBlur(image, 0.5);
|
||||||
addGaussianNoise(image, 0.8);
|
addGaussianNoise(image, 0.5);
|
||||||
image = linearStretch(image);
|
image = linearStretch(image);
|
||||||
|
addDustAndHairs(image, 3);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,32 +158,51 @@ public class FakeScanControllerWIP {
|
||||||
|
|
||||||
g2.drawImage(image, 0, 0, null);
|
g2.drawImage(image, 0, 0, null);
|
||||||
g2.setComposite(AlphaComposite.DstIn);
|
g2.setComposite(AlphaComposite.DstIn);
|
||||||
g2.setPaint(
|
|
||||||
new GradientPaint(
|
// Top edge
|
||||||
0, 0, new Color(0, 0, 0, 1f), 0, featherRadius, new Color(0, 0, 0, 0f)));
|
|
||||||
g2.fillRect(0, 0, width, featherRadius); // top edge
|
|
||||||
g2.setPaint(
|
g2.setPaint(
|
||||||
new GradientPaint(
|
new GradientPaint(
|
||||||
0,
|
0,
|
||||||
height - featherRadius,
|
0,
|
||||||
|
new Color(0, 0, 0, 1f),
|
||||||
|
0,
|
||||||
|
featherRadius * 2,
|
||||||
|
new Color(0, 0, 0, 0f)));
|
||||||
|
g2.fillRect(0, 0, width, featherRadius);
|
||||||
|
|
||||||
|
// Bottom edge
|
||||||
|
g2.setPaint(
|
||||||
|
new GradientPaint(
|
||||||
|
0,
|
||||||
|
height - featherRadius * 2,
|
||||||
new Color(0, 0, 0, 0f),
|
new Color(0, 0, 0, 0f),
|
||||||
0,
|
0,
|
||||||
height,
|
height,
|
||||||
new Color(0, 0, 0, 1f)));
|
new Color(0, 0, 0, 1f)));
|
||||||
g2.fillRect(0, height - featherRadius, width, featherRadius); // bottom edge
|
g2.fillRect(0, height - featherRadius, width, featherRadius);
|
||||||
|
|
||||||
|
// Left edge
|
||||||
g2.setPaint(
|
g2.setPaint(
|
||||||
new GradientPaint(
|
new GradientPaint(
|
||||||
0, 0, new Color(0, 0, 0, 1f), featherRadius, 0, new Color(0, 0, 0, 0f)));
|
0,
|
||||||
g2.fillRect(0, 0, featherRadius, height); // left edge
|
0,
|
||||||
|
new Color(0, 0, 0, 1f),
|
||||||
|
featherRadius * 2,
|
||||||
|
0,
|
||||||
|
new Color(0, 0, 0, 0f)));
|
||||||
|
g2.fillRect(0, 0, featherRadius, height);
|
||||||
|
|
||||||
|
// Right edge
|
||||||
g2.setPaint(
|
g2.setPaint(
|
||||||
new GradientPaint(
|
new GradientPaint(
|
||||||
width - featherRadius,
|
width - featherRadius * 2,
|
||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 0f),
|
new Color(0, 0, 0, 0f),
|
||||||
width,
|
width,
|
||||||
0,
|
0,
|
||||||
new Color(0, 0, 0, 1f)));
|
new Color(0, 0, 0, 1f)));
|
||||||
g2.fillRect(width - featherRadius, 0, featherRadius, height); // right edge
|
g2.fillRect(width - featherRadius, 0, featherRadius, height);
|
||||||
|
|
||||||
g2.dispose();
|
g2.dispose();
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|
|
@ -20,12 +20,10 @@ import org.apache.pdfbox.printing.PDFPageable;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
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.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
||||||
|
@ -35,12 +33,13 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest;
|
||||||
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
@Tag(name = "Misc", description = "Miscellaneous APIs")
|
||||||
public class PrintFileController {
|
public class PrintFileController {
|
||||||
|
|
||||||
//TODO
|
// TODO
|
||||||
//@PostMapping(value = "/print-file", consumes = "multipart/form-data")
|
// @PostMapping(value = "/print-file", consumes = "multipart/form-data")
|
||||||
//@Operation(
|
// @Operation(
|
||||||
// summary = "Prints PDF/Image file to a set printer",
|
// summary = "Prints PDF/Image file to a set printer",
|
||||||
// description =
|
// description =
|
||||||
// "Input of PDF or Image along with a printer name/URL/IP to match against to send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
|
// "Input of PDF or Image along with a printer name/URL/IP to match against to
|
||||||
|
// send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
|
||||||
public ResponseEntity<String> printFile(@ModelAttribute PrintFileRequest request)
|
public ResponseEntity<String> printFile(@ModelAttribute PrintFileRequest request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
MultipartFile file = request.getFileInput();
|
MultipartFile file = request.getFileInput();
|
||||||
|
|
|
@ -212,6 +212,15 @@ public class ApplicationProperties {
|
||||||
private Integer maxFileSize;
|
private Integer maxFileSize;
|
||||||
private boolean showUpdate;
|
private boolean showUpdate;
|
||||||
private Boolean showUpdateOnlyAdmin;
|
private Boolean showUpdateOnlyAdmin;
|
||||||
|
private boolean customHTMLFiles;
|
||||||
|
|
||||||
|
public boolean isCustomHTMLFiles() {
|
||||||
|
return customHTMLFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCustomHTMLFiles(boolean customHTMLFiles) {
|
||||||
|
this.customHTMLFiles = customHTMLFiles;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getShowUpdateOnlyAdmin() {
|
public boolean getShowUpdateOnlyAdmin() {
|
||||||
return showUpdateOnlyAdmin;
|
return showUpdateOnlyAdmin;
|
||||||
|
|
|
@ -342,8 +342,6 @@ public class PdfUtils {
|
||||||
boolean imageIsLandscape = image.getWidth() > image.getHeight();
|
boolean imageIsLandscape = image.getWidth() > image.getHeight();
|
||||||
PDRectangle pageSize = PDRectangle.A4;
|
PDRectangle pageSize = PDRectangle.A4;
|
||||||
|
|
||||||
System.out.println(fitOption);
|
|
||||||
|
|
||||||
if (autoRotate && imageIsLandscape) {
|
if (autoRotate && imageIsLandscape) {
|
||||||
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
|
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ seeDockerHub=Docker Hub'a bakın
|
||||||
visitGithub=Github Deposunu Ziyaret Edin
|
visitGithub=Github Deposunu Ziyaret Edin
|
||||||
donate=Bağış Yapın
|
donate=Bağış Yapın
|
||||||
color=Renk
|
color=Renk
|
||||||
sponsor=Sponsor
|
sponsor=Bağış
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ navbar.settings=Ayarlar
|
||||||
#############
|
#############
|
||||||
settings.title=Ayarlar
|
settings.title=Ayarlar
|
||||||
settings.update=Güncelleme mevcut
|
settings.update=Güncelleme mevcut
|
||||||
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
settings.updateAvailable={0} mevcut kurulu sürümdür. Yeni bir sürüm ({1}) mevcuttur.
|
||||||
settings.appVersion=Uygulama Sürümü:
|
settings.appVersion=Uygulama Sürümü:
|
||||||
settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
|
settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
|
||||||
settings.downloadOption.1=Aynı pencerede aç
|
settings.downloadOption.1=Aynı pencerede aç
|
||||||
|
@ -666,7 +666,7 @@ BookToPDF.submit=Dönüştür
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF'den Kitaba
|
PDFToBook.title=PDF'den Kitaba
|
||||||
PDFToBook.header=PDF'den Kitaba
|
PDFToBook.header=PDF'den Kitaba
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Format biçimi
|
||||||
PDFToBook.credit=Kalibre Kullanır
|
PDFToBook.credit=Kalibre Kullanır
|
||||||
PDFToBook.submit=Dönüştür
|
PDFToBook.submit=Dönüştür
|
||||||
|
|
||||||
|
@ -941,7 +941,7 @@ pdfToPDFA.header=PDF'den PDF/A'ya
|
||||||
pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
|
pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
|
||||||
pdfToPDFA.submit=Dönüştür
|
pdfToPDFA.submit=Dönüştür
|
||||||
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
|
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Çıkış formatı
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
|
|
|
@ -14,7 +14,8 @@ system:
|
||||||
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
|
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
|
||||||
showUpdate: true # see when a new update is available
|
showUpdate: true # see when a new update is available
|
||||||
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
|
||||||
|
customHTMLFiles: false # Enable to have files placed in /customFiles/templates override the existing template html files
|
||||||
|
|
||||||
#ui:
|
#ui:
|
||||||
# appName: exampleAppName # Application's visible name
|
# appName: exampleAppName # Application's visible name
|
||||||
# homeDescription: I am a description # Short description or tagline shown on homepage.
|
# homeDescription: I am a description # Short description or tagline shown on homepage.
|
||||||
|
|
|
@ -17,20 +17,20 @@
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav me-auto flex-nowrap">
|
<ul class="navbar-nav me-auto flex-nowrap">
|
||||||
<li class="nav-item">
|
<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}">
|
<a class="nav-link" href="#" th:href="@{multi-tool}" th:classappend="${currentPage}=='multi-tool' ? 'active' : ''" th:title="#{home.multiTool.desc}">
|
||||||
<img class="icon" src="images/tools.svg" alt="icon">
|
<img class="icon" src="images/tools.svg" alt="icon">
|
||||||
<span class="icon-text" th:text="#{home.multiTool.title}"></span>
|
<span class="icon-text" th:text="#{home.multiTool.title}"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item nav-item-separator"></li>
|
<li th:if="${@endpointConfiguration.isEndpointEnabled('multi-tool')}" class="nav-item nav-item-separator"></li>
|
||||||
<li class="nav-item">
|
<li th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}" class="nav-item">
|
||||||
<a class="nav-link" href="#" th:href="@{pipeline}" th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
|
<a class="nav-link" href="#" th:href="@{pipeline}" th:classappend="${currentPage}=='pipeline' ? 'active' : ''" th:title="#{home.pipeline.desc}">
|
||||||
<img class="icon" src="images/pipeline.svg" alt="icon">
|
<img class="icon" src="images/pipeline.svg" alt="icon">
|
||||||
<span class="icon-text" th:text="#{home.pipeline.title}"></span>
|
<span class="icon-text" th:text="#{home.pipeline.title}"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item nav-item-separator"></li>
|
<li th:if="${@endpointConfiguration.isEndpointEnabled('pipeline')}" class="nav-item nav-item-separator"></li>
|
||||||
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' ? 'active' : ''">
|
<li class="nav-item dropdown" th:classappend="${currentPage}=='remove-pages' OR ${currentPage}=='merge-pdfs' OR ${currentPage}=='split-pdfs' OR ${currentPage}=='crop' OR ${currentPage}=='adjust-contrast' OR ${currentPage}=='pdf-organizer' OR ${currentPage}=='rotate-pdf' OR ${currentPage}=='multi-page-layout' OR ${currentPage}=='scale-pages' OR ${currentPage}=='auto-split-pdf' OR ${currentPage}=='extract-page' OR ${currentPage}=='pdf-to-single-page' ? 'active' : ''">
|
||||||
<a class="nav-link dropdown-toggle" id="navbarDropdown-1" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
<a class="nav-link dropdown-toggle" id="navbarDropdown-1" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
|
<img class="icon" src="images/file-earmark-pdf.svg" alt="icon">
|
||||||
|
|
Loading…
Reference in New Issue