diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java index fdcd114a..9e1d4fb9 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertHtmlToPDF.java @@ -12,7 +12,7 @@ import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import stirling.software.SPDF.model.api.GeneralFile; +import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest; import stirling.software.SPDF.utils.FileToPdf; import stirling.software.SPDF.utils.WebResponseUtils; @@ -30,7 +30,8 @@ public class ConvertHtmlToPDF { summary = "Convert an HTML or ZIP (containing HTML and CSS) to PDF", description = "This endpoint takes an HTML or ZIP file input and converts it to a PDF format.") - public ResponseEntity HtmlToPdf(@ModelAttribute GeneralFile request) throws Exception { + public ResponseEntity HtmlToPdf(@ModelAttribute HTMLToPdfRequest request) + throws Exception { MultipartFile fileInput = request.getFileInput(); if (fileInput == null) { @@ -45,7 +46,7 @@ public class ConvertHtmlToPDF { } byte[] pdfBytes = FileToPdf.convertHtmlToPdf( - fileInput.getBytes(), originalFilename, htmlFormatsInstalled); + request, fileInput.getBytes(), originalFilename, htmlFormatsInstalled); String outputFilename = originalFilename.replaceFirst("[.][^.]+$", "") diff --git a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java index 1b6efefb..12fc9097 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java +++ b/src/main/java/stirling/software/SPDF/controller/api/converters/ConvertMarkdownToPdf.java @@ -68,7 +68,7 @@ public class ConvertMarkdownToPdf { byte[] pdfBytes = FileToPdf.convertHtmlToPdf( - htmlContent.getBytes(), "converted.html", htmlFormatsInstalled); + null, htmlContent.getBytes(), "converted.html", htmlFormatsInstalled); String outputFilename = originalFilename.replaceFirst("[.][^.]+$", "") diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java index cb8db7d3..99595049 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/FakeScanControllerWIP.java @@ -50,7 +50,7 @@ public class FakeScanControllerWIP { // TODO @Hidden - @PostMapping(consumes = "multipart/form-data", value = "/fakeScan") + //@PostMapping(consumes = "multipart/form-data", value = "/fakeScan") @Operation( summary = "Repair a PDF file", description = diff --git a/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java new file mode 100644 index 00000000..718c0ddd --- /dev/null +++ b/src/main/java/stirling/software/SPDF/controller/api/misc/StampController.java @@ -0,0 +1,295 @@ +package stirling.software.SPDF.controller.api.misc; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +import org.apache.commons.io.IOUtils; +import org.apache.pdfbox.Loader; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.common.PDRectangle; +import org.apache.pdfbox.pdmodel.font.PDFont; +import org.apache.pdfbox.pdmodel.font.PDType0Font; +import org.apache.pdfbox.pdmodel.font.PDType1Font; +import org.apache.pdfbox.pdmodel.font.Standard14Fonts; +import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory; +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; +import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; +import org.apache.pdfbox.util.Matrix; +import org.springframework.core.io.ClassPathResource; +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.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + +import stirling.software.SPDF.model.api.misc.AddStampRequest; +import stirling.software.SPDF.utils.WebResponseUtils; + +@RestController +@RequestMapping("/api/v1/misc") +@Tag(name = "Misc", description = "Miscellaneous APIs") +public class StampController { + + @PostMapping(consumes = "multipart/form-data", value = "/add-stamp") + @Operation( + summary = "Add stamp to a PDF file", + description = + "This endpoint adds a stamp to a given PDF file. Users can specify the watermark type (text or image), rotation, opacity, width spacer, and height spacer. Input:PDF Output:PDF Type:SISO") + public ResponseEntity addStamp(@ModelAttribute AddStampRequest request) + throws IOException, Exception { + MultipartFile pdfFile = request.getFileInput(); + String watermarkType = request.getStampType(); + String watermarkText = request.getStampText(); + MultipartFile watermarkImage = request.getStampImage(); + String alphabet = request.getAlphabet(); + float fontSize = request.getFontSize(); + float rotation = request.getRotation(); + float opacity = request.getOpacity(); + int position = request.getPosition(); // Updated to use 1-9 positioning logic + float overrideX = request.getOverrideX(); // New field for X override + float overrideY = request.getOverrideY(); // New field for Y override + + String customColor = request.getCustomColor(); + float marginFactor; + switch (request.getCustomMargin().toLowerCase()) { + case "small": + marginFactor = 0.02f; + break; + case "medium": + marginFactor = 0.035f; + break; + case "large": + marginFactor = 0.05f; + break; + case "x-large": + marginFactor = 0.075f; + break; + + default: + marginFactor = 0.035f; + break; + } + + // Load the input PDF + PDDocument document = Loader.loadPDF(pdfFile.getBytes()); + + for (PDPage page : document.getPages()) { + PDPageContentStream contentStream = + new PDPageContentStream( + document, page, PDPageContentStream.AppendMode.APPEND, true, true); + + PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState(); + graphicsState.setNonStrokingAlphaConstant(opacity); + contentStream.setGraphicsStateParameters(graphicsState); + + if (watermarkType.equalsIgnoreCase("text")) { + addTextStamp( + contentStream, + watermarkText, + document, + page, + rotation, + position, + fontSize, + alphabet, + overrideX, + overrideY, + marginFactor, + customColor); + } else if (watermarkType.equalsIgnoreCase("image")) { + addImageStamp( + contentStream, + watermarkImage, + document, + page, + rotation, + position, + fontSize, + overrideX, + overrideY, + marginFactor); + } + + contentStream.close(); + } + + return WebResponseUtils.pdfDocToWebResponse( + document, + pdfFile.getOriginalFilename().replaceFirst("[.][^.]+$", "") + "_watermarked.pdf"); + } + + private void addTextStamp( + PDPageContentStream contentStream, + String watermarkText, + PDDocument document, + PDPage page, + float rotation, + int position, // 1-9 positioning logic + float fontSize, + String alphabet, + float overrideX, // X override + float overrideY, + float marginFactor, + String colorString) // Y override + throws IOException { + String resourceDir = ""; + PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA); + switch (alphabet) { + case "arabic": + resourceDir = "static/fonts/NotoSansArabic-Regular.ttf"; + break; + case "japanese": + resourceDir = "static/fonts/Meiryo.ttf"; + break; + case "korean": + resourceDir = "static/fonts/malgun.ttf"; + break; + case "chinese": + resourceDir = "static/fonts/SimSun.ttf"; + break; + case "roman": + default: + resourceDir = "static/fonts/NotoSans-Regular.ttf"; + break; + } + + if (!resourceDir.equals("")) { + ClassPathResource classPathResource = new ClassPathResource(resourceDir); + String fileExtension = resourceDir.substring(resourceDir.lastIndexOf(".")); + File tempFile = File.createTempFile("NotoSansFont", fileExtension); + try (InputStream is = classPathResource.getInputStream(); + FileOutputStream os = new FileOutputStream(tempFile)) { + IOUtils.copy(is, os); + } + + font = PDType0Font.load(document, tempFile); + tempFile.deleteOnExit(); + } + + contentStream.setFont(font, fontSize); + + Color redactColor; + try { + if (!colorString.startsWith("#")) { + colorString = "#" + colorString; + } + redactColor = Color.decode(colorString); + } catch (NumberFormatException e) { + + redactColor = Color.LIGHT_GRAY; + } + + contentStream.setNonStrokingColor(redactColor); + + PDRectangle pageSize = page.getMediaBox(); + float x, y; + + if (overrideX >= 0 && overrideY >= 0) { + // Use override values if provided + x = overrideX; + y = overrideY; + } else { + x = calculatePositionX(pageSize, position, fontSize, font, fontSize, watermarkText, marginFactor); + y = calculatePositionY(pageSize, position, fontSize, marginFactor); + } + + contentStream.beginText(); + contentStream.setTextMatrix(Matrix.getRotateInstance(Math.toRadians(rotation), x, y)); + contentStream.showText(watermarkText); + contentStream.endText(); + } + + private void addImageStamp( + PDPageContentStream contentStream, + MultipartFile watermarkImage, + PDDocument document, + PDPage page, + float rotation, + int position, // 1-9 positioning logic + float fontSize, + float overrideX, + float overrideY, + float marginFactor) + throws IOException { + + // Load the watermark image + BufferedImage image = ImageIO.read(watermarkImage.getInputStream()); + + // Compute width based on original aspect ratio + float aspectRatio = (float) image.getWidth() / (float) image.getHeight(); + + // Desired physical height (in PDF points) + float desiredPhysicalHeight = fontSize; + + // Desired physical width based on the aspect ratio + float desiredPhysicalWidth = desiredPhysicalHeight * aspectRatio; + + // Convert the BufferedImage to PDImageXObject + PDImageXObject xobject = LosslessFactory.createFromImage(document, image); + + PDRectangle pageSize = page.getMediaBox(); + float x, y; + + if (overrideX >= 0 && overrideY >= 0) { + // Use override values if provided + x = overrideX; + y = overrideY; + } else { + x = calculatePositionX(pageSize, position, desiredPhysicalWidth, null, 0, null, marginFactor); + y = calculatePositionY(pageSize, position, fontSize, marginFactor); + } + + contentStream.saveGraphicsState(); + contentStream.transform(Matrix.getTranslateInstance(x, y)); + contentStream.transform(Matrix.getRotateInstance(Math.toRadians(rotation), 0, 0)); + contentStream.drawImage(xobject, 0, 0, desiredPhysicalWidth, desiredPhysicalHeight); + contentStream.restoreGraphicsState(); + } + + private float calculatePositionX( + PDRectangle pageSize, int position, float contentWidth, PDFont font, float fontSize, String text, float marginFactor) throws IOException { + float actualWidth = (text != null) ? calculateTextWidth(text, font, fontSize) : contentWidth; + switch (position % 3) { + case 1: // Left + return pageSize.getLowerLeftX() + marginFactor * pageSize.getWidth(); + case 2: // Center + return (pageSize.getWidth() - actualWidth) / 2; + case 0: // Right + return pageSize.getUpperRightX() - actualWidth - marginFactor * pageSize.getWidth(); + default: + return 0; + } + } + + private float calculateTextWidth(String text, PDFont font, float fontSize) throws IOException { + return font.getStringWidth(text) / 1000 * fontSize; + } + + + + private float calculatePositionY( + PDRectangle pageSize, int position, float height, float marginFactor) { + switch ((position - 1) / 3) { + case 0: // Top + return pageSize.getUpperRightY() - height - marginFactor * pageSize.getHeight(); + case 1: // Middle + return (pageSize.getHeight() - height) / 2; + case 2: // Bottom + return pageSize.getLowerLeftY() + marginFactor * pageSize.getHeight(); + default: + return 0; + } + } +} diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java index b0204779..69609536 100644 --- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java +++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java @@ -38,6 +38,14 @@ public class OtherWebController { model.addAttribute("currentPage", "show-javascript"); return "misc/show-javascript"; } + + @GetMapping("/stamp") + @Hidden + public String stampForm(Model model) { + model.addAttribute("currentPage", "stamp"); + return "misc/stamp"; + } + @GetMapping("/add-page-numbers") @Hidden diff --git a/src/main/java/stirling/software/SPDF/model/api/converters/HTMLToPdfRequest.java b/src/main/java/stirling/software/SPDF/model/api/converters/HTMLToPdfRequest.java new file mode 100644 index 00000000..c778c36f --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/converters/HTMLToPdfRequest.java @@ -0,0 +1,52 @@ +package stirling.software.SPDF.model.api.converters; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +@EqualsAndHashCode(callSuper = true) +public class HTMLToPdfRequest extends PDFFile { + + @Schema( + description = "Zoom level for displaying the website. Default is '1'.", + defaultValue = "1") + private float zoom; + + @Schema(description = "Width of the page in centimeters.") + private Float pageWidth; + + @Schema(description = "Height of the page in centimeters.") + private Float pageHeight; + + @Schema(description = "Top margin of the page in millimeters.") + private Float marginTop; + + @Schema(description = "Bottom margin of the page in millimeters.") + private Float marginBottom; + + @Schema(description = "Left margin of the page in millimeters.") + private Float marginLeft; + + @Schema(description = "Right margin of the page in millimeters.") + private Float marginRight; + + @Schema( + description = "Enable or disable rendering of website background.", + allowableValues = {"Yes", "No"}) + private String printBackground; + + @Schema( + description = + "Enable or disable the default header. The default header includes the name of the page on the left and the page number on the right.", + allowableValues = {"Yes", "No"}) + private String defaultHeader; + + @Schema( + description = "Change the CSS media type of the page. Defaults to 'print'.", + allowableValues = {"none", "print", "screen"}, + defaultValue = "print") + private String cssMediaType; +} diff --git a/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java b/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java new file mode 100644 index 00000000..82296acc --- /dev/null +++ b/src/main/java/stirling/software/SPDF/model/api/misc/AddStampRequest.java @@ -0,0 +1,68 @@ +package stirling.software.SPDF.model.api.misc; + +import org.springframework.web.multipart.MultipartFile; + +import io.swagger.v3.oas.annotations.media.Schema; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import stirling.software.SPDF.model.api.PDFFile; + +@Data +@EqualsAndHashCode(callSuper = true) +public class AddStampRequest extends PDFFile { + + @Schema( + description = "The stamp type (text or image)", + allowableValues = {"text", "image"}, + required = true) + private String stampType; + + @Schema(description = "The stamp text") + private String stampText; + + @Schema(description = "The stamp image") + private MultipartFile stampImage; + + @Schema( + description = "The selected alphabet", + allowableValues = {"roman", "arabic", "japanese", "korean", "chinese"}, + defaultValue = "roman") + private String alphabet = "roman"; + + @Schema(description = "The font size of the stamp text", example = "30") + private float fontSize = 30; + + @Schema(description = "The rotation of the stamp in degrees", example = "0") + private float rotation = 0; + + @Schema(description = "The opacity of the stamp (0.0 - 1.0)", example = "0.5") + private float opacity; + + @Schema( + description = + "Position for stamp placement based on a 1-9 grid (1: bottom-left, 2: bottom-center, ..., 9: top-right)", + example = "1") + private int position; + + @Schema( + description = + "Override X coordinate for stamp placement. If set, it will override the position-based calculation. Negative value means no override.", + example = "-1") + private float overrideX = -1; // Default to -1 indicating no override + + @Schema( + description = + "Override Y coordinate for stamp placement. If set, it will override the position-based calculation. Negative value means no override.", + example = "-1") + private float overrideY = -1; // Default to -1 indicating no override + + @Schema( + description = "Specifies the margin size for the stamp.", + allowableValues = {"small", "medium", "large", "x-large"}, + defaultValue = "medium") + private String customMargin = "medium"; + + @Schema(description = "The color for stamp", defaultValue = "#d3d3d3") + private String customColor = "#d3d3d3"; +} diff --git a/src/main/java/stirling/software/SPDF/utils/FileToPdf.java b/src/main/java/stirling/software/SPDF/utils/FileToPdf.java index a57bfda4..bdf3ec61 100644 --- a/src/main/java/stirling/software/SPDF/utils/FileToPdf.java +++ b/src/main/java/stirling/software/SPDF/utils/FileToPdf.java @@ -2,6 +2,7 @@ package stirling.software.SPDF.utils; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -11,12 +12,16 @@ import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; +import stirling.software.SPDF.model.api.converters.HTMLToPdfRequest; import stirling.software.SPDF.utils.ProcessExecutor.ProcessExecutorResult; public class FileToPdf { public static byte[] convertHtmlToPdf( - byte[] fileBytes, String fileName, boolean htmlFormatsInstalled) + HTMLToPdfRequest request, + byte[] fileBytes, + String fileName, + boolean htmlFormatsInstalled) throws IOException, InterruptedException { Path tempOutputFile = Files.createTempFile("output_", ".pdf"); @@ -40,6 +45,61 @@ public class FileToPdf { command.add("ignore"); command.add("--load-media-error-handling"); command.add("ignore"); + command.add("--zoom"); + command.add(String.valueOf(request.getZoom())); + + // if custom zoom add zoom style direct to html + // https://github.com/wkhtmltopdf/wkhtmltopdf/issues/4900 + if (request.getZoom() != 1.0) { + String htmlContent = new String(Files.readAllBytes(tempInputFile)); + + String zoomStyle = ""; + // Check for tag, add style tag to associated tag + if (htmlContent.contains("")) { + htmlContent = htmlContent.replace("", "" + zoomStyle); + } else if (htmlContent.contains("")) { + // If no tag, but tag exists + htmlContent = htmlContent.replace("", "" + zoomStyle); + } else { + // If neither nor tags exist + htmlContent = zoomStyle + htmlContent; + } + // rewrite new html to file + Files.write(tempInputFile, htmlContent.getBytes(StandardCharsets.UTF_8)); + } + + if (request.getPageWidth() != null) { + command.add("--page-width"); + command.add(request.getPageWidth() + "cm"); + } + + if (request.getPageHeight() != null) { + command.add("--page-height"); + command.add(request.getPageHeight() + "cm"); + } + + if (request.getMarginTop() != null) { + command.add("--margin-top"); + command.add(request.getMarginTop() + "mm"); + } + + // Repeat similar pattern for marginBottom, marginLeft, marginRight + + if ("Yes".equalsIgnoreCase(request.getPrintBackground())) { + command.add("--background"); + } else { + command.add("--no-background"); + } + + if ("Yes".equalsIgnoreCase(request.getDefaultHeader())) { + command.add("--default-header"); + } + + if ("print".equalsIgnoreCase(request.getCssMediaType())) { + command.add("--print-media-type"); + } else if ("screen".equalsIgnoreCase(request.getCssMediaType())) { + command.add("--no-print-media-type"); + } } command.add(tempInputFile.toString()); diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index c6da18c2..aeda5c47 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -44,7 +44,8 @@ blue=Blue custom=Custom... WorkInProgess=Work in progress, May not work or be buggy, Please report any ploblems! poweredBy=Powered by - +yes=Yes +no=No changedCredsMessage=Credentials changed! notAuthenticatedMessage=User not authenticated. userNotFoundMessage=User not found. @@ -385,6 +386,11 @@ 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 + + ########################### # # # WEB PAGES # @@ -460,8 +466,38 @@ 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 diff --git a/src/main/resources/templates/auto-split-pdf.html b/src/main/resources/templates/auto-split-pdf.html index 4fd27772..bb984cc5 100644 --- a/src/main/resources/templates/auto-split-pdf.html +++ b/src/main/resources/templates/auto-split-pdf.html @@ -24,7 +24,7 @@

-
+
diff --git a/src/main/resources/templates/convert/html-to-pdf.html b/src/main/resources/templates/convert/html-to-pdf.html index ab6c5324..cbb22b99 100644 --- a/src/main/resources/templates/convert/html-to-pdf.html +++ b/src/main/resources/templates/convert/html-to-pdf.html @@ -10,10 +10,73 @@

-
+

-
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
diff --git a/src/main/resources/templates/convert/markdown-to-pdf.html b/src/main/resources/templates/convert/markdown-to-pdf.html index c8193112..4606d2b5 100644 --- a/src/main/resources/templates/convert/markdown-to-pdf.html +++ b/src/main/resources/templates/convert/markdown-to-pdf.html @@ -13,7 +13,7 @@

-
+

diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index b090b08c..aec6b826 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -133,6 +133,7 @@
+
diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html index 52f945eb..d42ccb4a 100644 --- a/src/main/resources/templates/home.html +++ b/src/main/resources/templates/home.html @@ -101,8 +101,10 @@
+
+
diff --git a/src/main/resources/templates/misc/show-javascript.html b/src/main/resources/templates/misc/show-javascript.html index 36f1bb80..0614a2c2 100644 --- a/src/main/resources/templates/misc/show-javascript.html +++ b/src/main/resources/templates/misc/show-javascript.html @@ -18,7 +18,7 @@
+ th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, remoteCall='false', accept='application/pdf')}">

diff --git a/src/main/resources/templates/misc/stamp.html b/src/main/resources/templates/misc/stamp.html new file mode 100644 index 00000000..a05e9717 --- /dev/null +++ b/src/main/resources/templates/misc/stamp.html @@ -0,0 +1,216 @@ + + + + + + + + +
+
+
+

+
+
+
+

+ +
+
+
+ + +
+ + + +
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
+
+ + + + + +
+ + +
+ +
+ + +
+ + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ + + + +
+
+
+ +
+
+
+ + diff --git a/src/main/resources/templates/pdf-to-single-page.html b/src/main/resources/templates/pdf-to-single-page.html index c8dedca5..6c26ace5 100644 --- a/src/main/resources/templates/pdf-to-single-page.html +++ b/src/main/resources/templates/pdf-to-single-page.html @@ -14,7 +14,7 @@

-
+
diff --git a/src/main/resources/templates/security/get-info-on-pdf.html b/src/main/resources/templates/security/get-info-on-pdf.html index 41ff4be7..84bf8692 100644 --- a/src/main/resources/templates/security/get-info-on-pdf.html +++ b/src/main/resources/templates/security/get-info-on-pdf.html @@ -16,7 +16,7 @@
+ th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, remoteCall='false', accept='application/pdf')}">