Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions minipdf-java/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# MiniPdf for Java

MiniPdf for Java is a Java 17 library and command-line tool for converting
DOCX, XLSX, and PPTX files to PDF without Microsoft Office or LibreOffice.

## Install

The library is available from Maven Central:

```xml
<dependency>
<groupId>io.github.shps951023</groupId>
<artifactId>minipdf</artifactId>
<version>0.1.1</version>
</dependency>
```

## Library

```java
import io.github.minisoftware.minipdf.MiniPdf;

import java.nio.file.Path;

MiniPdf.convertToPdf(
Path.of("document.docx"),
Path.of("document.pdf"));
```

Use `MiniPdf.convertBytesToPdf` when the Office document is already in memory.
`ConversionOptions.withPageSize` overrides the output page size.

## CLI

Download the executable JAR with Maven:

```powershell
mvn dependency:copy `
-Dartifact=io.github.shps951023:minipdf-cli:0.1.1 `
-DoutputDirectory=.
```

Convert a document:

```powershell
java -jar minipdf-cli-0.1.1.jar input.pptx -o output.pdf
```

The CLI accepts `.docx`, `.xlsx`, and `.pptx` files. Run it with `--help` for
page-size and font-directory options.

## Current Scope

The Java implementation currently provides text-first Office conversion:

- DOCX paragraphs, tabs, and line breaks
- XLSX shared strings, inline strings, numbers, and booleans
- PPTX slide text, native slide dimensions, and one PDF page per slide
- bounded OOXML ZIP loading and XML external-entity protection

Advanced Office layout, images, charts, and embedded fonts are not yet fully
reproduced by the Java renderer.

## Build and Test

From this directory:

```powershell
mvn -B -ntp verify
```
2 changes: 1 addition & 1 deletion minipdf-java/minipdf-cli/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.shps951023</groupId>
<artifactId>minipdf-java-parent</artifactId>
<version>0.1.0</version>
<version>0.1.1</version>
</parent>

<artifactId>minipdf-cli</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@

@Command(
name = "minipdf",
version = "minipdf-java 0.1.0",
description = "Convert XLSX and DOCX files to PDF with the Java MiniPdf engine.",
version = "minipdf-java 0.1.1",
description = "Convert XLSX, DOCX, and PPTX files to PDF with the Java MiniPdf engine.",
mixinStandardHelpOptions = true,
subcommands = MiniPdfCommand.ConvertCommand.class)
public final class MiniPdfCommand implements Callable<Integer> {
Expand Down Expand Up @@ -131,10 +131,10 @@ private static int convert(Path input, ConversionArguments arguments, CommandLin
String fileName = input.getFileName().toString();
int dot = fileName.lastIndexOf('.');
String extension = dot < 0 ? "" : fileName.substring(dot + 1).toLowerCase(Locale.ROOT);
if (!extension.equals("xlsx") && !extension.equals("docx")) {
if (!extension.equals("xlsx") && !extension.equals("docx") && !extension.equals("pptx")) {
throw new CommandLine.ParameterException(
commandLine,
"unsupported file type '." + extension + "'. Supported: .xlsx, .docx");
"unsupported file type '." + extension + "'. Supported: .xlsx, .docx, .pptx");
}

if (arguments.fonts != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ void convertsDocxWithSubcommandAndCustomSize() throws Exception {
.contains("/MediaBox [0 0 400 500]"));
}

@Test
void convertsPptxWithDirectSyntax() throws Exception {
Path source = REPOSITORY_ROOT.resolve("tests/Issue_Files/pptx/Asian Pacific.pptx");
Path output = temporaryDirectory.resolve("slides.pdf");

CommandResult result = execute(source.toString(), "-o", output.toString());

assertEquals(0, result.exitCode());
assertTrue(Files.readString(output, StandardCharsets.ISO_8859_1).startsWith("%PDF-1.4"));
assertTrue(result.stdout().contains(output.toString()));
}

@Test
void rejectsConflictingPageOptions() {
Path source = REPOSITORY_ROOT.resolve(
Expand Down
2 changes: 1 addition & 1 deletion minipdf-java/minipdf/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<groupId>io.github.shps951023</groupId>
<artifactId>minipdf-java-parent</artifactId>
<version>0.1.0</version>
<version>0.1.1</version>
</parent>

<artifactId>minipdf</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.github.minisoftware.minipdf.internal.OfficePackageDetector;
import io.github.minisoftware.minipdf.internal.docx.DocxConverter;
import io.github.minisoftware.minipdf.internal.pptx.PptxConverter;
import io.github.minisoftware.minipdf.internal.xlsx.XlsxConverter;

import java.io.IOException;
Expand Down Expand Up @@ -59,7 +60,8 @@ public static byte[] convertBytesToPdf(byte[] input, ConversionOptions options)
return switch (format) {
case DOCX -> DocxConverter.convert(input, options);
case XLSX -> XlsxConverter.convert(input, options);
case PPTX, UNKNOWN -> throw new MiniPdfException(
case PPTX -> PptxConverter.convert(input, options);
case UNKNOWN -> throw new MiniPdfException(
MiniPdfException.Kind.UNSUPPORTED_FORMAT,
"unsupported or unknown Office document format");
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,29 @@ private SimplePdfTextRenderer() {
}

public static byte[] render(List<String> sourceLines, ConversionOptions options) {
PageSize size = options.pageSize().orElse(PageSize.A4);
return renderPages(List.of(sourceLines), options, PageSize.A4);
}

public static byte[] renderPages(
List<List<String>> sourcePages,
ConversionOptions options,
PageSize defaultPageSize) {
PageSize size = options.pageSize().orElse(defaultPageSize);
PdfDocument document = new PdfDocument();
PdfPage page = document.addPage(size.width(), size.height());
float y = size.height() - MARGIN;
int maxCharacters = Math.max(1, (int) ((size.width() - MARGIN * 2.0f) / (FONT_SIZE * 0.52f)));

for (String sourceLine : sourceLines) {
for (String line : wrap(sourceLine, maxCharacters)) {
if (y < MARGIN) {
page = document.addPage(size.width(), size.height());
y = size.height() - MARGIN;
for (List<String> sourcePage : sourcePages) {
PdfPage page = document.addPage(size.width(), size.height());
float y = size.height() - MARGIN;
for (String sourceLine : sourcePage) {
for (String line : wrap(sourceLine, maxCharacters)) {
if (y < MARGIN) {
page = document.addPage(size.width(), size.height());
y = size.height() - MARGIN;
}
page.addText(line, MARGIN, y, FONT_SIZE, PdfColor.BLACK, false);
y -= LINE_HEIGHT;
}
page.addText(line, MARGIN, y, FONT_SIZE, PdfColor.BLACK, false);
y -= LINE_HEIGHT;
}
}
return document.toBytes();
Expand Down
Loading
Loading