Preview.java

package pro.verron.officestamper;

import picocli.CommandLine;
import pro.verron.asciidoc.compiler.AsciiDocCompiler;
import pro.verron.asciidoc.core.AsciiDocModel;

import java.awt.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static java.nio.file.Files.writeString;
import static pro.verron.asciidoc.compiler.AsciiDocCompiler.saveSvgAsImage;

/// Subcommand that generates a preview image from an AsciiDoc file.
@CommandLine.Command(name = "preview",
                     description = "Generate a preview image from an AsciiDoc"
                                   + " file")
public class Preview
        implements Runnable {

    @CommandLine.Option(names = {"-i", "--input"},
                        required = true,
                        description = "Input AsciiDoc file") private Path input;
    @CommandLine.Option(names = {"-o", "--output"},
                        defaultValue = "preview.png",
                        description = "Output file (PNG or SVG)") private Path output;
    @CommandLine.Option(names = "--theme",
                        defaultValue = "word",
                        description = "Theme: word, gdocs, libre") private String theme;
    @CommandLine.Option(names = "--dpi",
                        defaultValue = "96",
                        description = "DPI for PNG output") private int dpi;
    @CommandLine.Option(names = "--format",
                        description =
                                "Output format: png, svg (auto-detected if "
                                + "omitted)") private String format;

    /// Default constructor.
    public Preview() {}

    @Override
    public void run() {
        try {
            String asciidoc = Files.readString(input);
            var model = AsciiDocCompiler.toModel(asciidoc);

            // Inject theme attribute into model
            var attributes = new java.util.HashMap<>(model.getAttributes());
            attributes.put("theme", theme);
            model = AsciiDocModel.of(attributes, model.getBlocks());

            String formatToUse;
            if (format != null) formatToUse = format;
            else formatToUse = output.endsWith(".svg") ? "svg" : "png";

            var svg = AsciiDocCompiler.toSvg(model);

            switch (formatToUse) {
                case "svg" -> writeString(output, svg);
                case "png" -> saveSvgAsImage(svg, output, dpi, Color.WHITE);
                default -> throw new IllegalArgumentException(
                        "Unsupported format: " + formatToUse);
            }

        } catch (IOException e) {
            throw new RuntimeException("Failed to generate preview", e);
        }
    }
}