Skip to content

Alipsa/MarkdownToPdf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MarkdownToPdf — a Markdown to PDF library

Maven Central javadoc

MarkdownToPdf is a Java library that converts Markdown to PDF.

Internally it uses commonmark-java to render Markdown to HTML, jsoup to produce well-formed XHTML, and OpenHTMLtoPDF to produce the PDF. SVG support is provided by Batik.

Requires JDK 21 or later.

Quick start

import se.alipsa.md2pdf.Md2PdfEngine;

byte[] pdf = new Md2PdfEngine()
    .markdown("# Hello\n\nWorld!")
    .toPdf();

// Or write directly to a file:
new Md2PdfEngine()
    .markdown(Path.of("report.md"))
    .toPdf(Path.of("report.pdf"));

Maven dependency

<dependency>
    <groupId>se.alipsa</groupId>
    <artifactId>md2pdf</artifactId>
    <version>0.1.0</version>
</dependency>

Builder configuration

The engine can be configured via a builder before use:

Md2PdfEngine engine = Md2PdfEngine.builder()
    .tables(true)           // enable GFM table support (default: true)
    .softbreak("<br />\n")  // how soft line breaks are rendered (default: <br />\n)
    .build();

Reading Markdown

Markdown can be provided as a String, File, Path, or InputStream:

// From a string
byte[] pdf = engine.markdown("# Report\n\nSome content").toPdf();

// From a file (relative image/CSS paths resolve from the file's directory)
byte[] pdf = engine.markdown(new File("reports/report.md")).toPdf();

// From an input stream
try (InputStream is = MyClass.class.getResourceAsStream("/report.md")) {
    byte[] pdf = engine.markdown(is).toPdf();
}

Output

Terminal methods on the Renderer produce PDF or HTML:

Renderer job = engine.markdown("# Hello");

byte[]      pdf  = job.toPdf();               // byte array
            job.toPdf(Path.of("out.pdf"));     // file
            job.toPdf(outputStream);           // stream

String      html = job.toHtml();              // string
            job.toHtml(Path.of("out.html"));   // file

Styling

Use css(...) to replace the default stylesheet entirely:

byte[] pdf = engine.markdown("# Report")
    .css("body { font-family: serif; font-size: 12pt; }")
    .toPdf();

Use addCss(...) to extend the default stylesheet with overrides:

byte[] pdf = engine.markdown("# Report")
    .addCss("h1 { color: #0057b8; }")
    .toPdf();

Both css(...) and addCss(...) also accept File, Path, URL, and InputStream:

byte[] pdf = engine.markdown("# Report")
    .addCss(Path.of("style/overrides.css"))
    .toPdf();

Images

Relative images

When reading Markdown from a File or Path, relative image references are resolved automatically from the Markdown file's directory:

// logo.png is read from reports/
byte[] pdf = engine.markdown(Path.of("reports/report.md")).toPdf();

When using a Markdown string, set the base path explicitly:

byte[] pdf = engine.markdown("# Report\n\n![Logo](logo.png)")
    .basePath(Path.of("reports"))
    .toPdf();

SVG images

SVG is supported via Batik. You can embed SVG directly as a raw HTML block inside your Markdown file (Markdown passes through raw HTML unchanged):

## My chart

<div style="width:400px;height:300px">
  <svg xmlns="http://www.w3.org/2000/svg">
    <circle cx="150" cy="65" r="60" stroke="black" stroke-width="3" fill="red"/>
  </svg>
</div>

The SVG block must be associated with a block-level element (a <div>) with explicit dimensions so that OpenHTMLtoPDF can allocate space for the Batik-rendered image.

Page structure

A simple page header and footer can be added via the fluent API:

byte[] pdf = engine.markdown("# Alice's Adventures in Wonderland\n\nDown the Rabbit-Hole")
    .pageHeader("Alice's Adventures in Wonderland")
    .pageFooter("Page <span class=\"page-number\"></span> of <span class=\"total-pages\"></span>")
    .pageMargins("0.75in")
    .toPdf();

When a header or footer is present and pageMargins(...) is omitted, md2pdf defaults to 0.75in.

For more control, define running elements in your CSS and reference them from @page:

String css = """
    div.header {
        display: block;
        position: running(header);
        font-size: 9px;
        text-align: right;
    }
    div.footer {
        display: block;
        position: running(footer);
        font-size: 9px;
    }
    @page {
        @top-center   { content: element(header) }
        @bottom-right { content: element(footer) }
    }
    #pagenumber:before { content: counter(page); }
    #pagecount:before  { content: counter(pages); }
    """;

Then include the header and footer divs as raw HTML in your Markdown:

<div class="header">Quarterly Report 2024</div>
<div class="footer">Page <span id="pagenumber"/> of <span id="pagecount"/></div>

# Chapter 1

Content here…

PDF metadata

byte[] pdf = engine.markdown("# Quarterly Report")
    .title("Quarterly Report")
    .author("Alipsa")
    .subject("Sales")
    .producer("Md2Pdf")
    .toPdf();

Custom fonts

Register TTF font files and reference the family from CSS:

byte[] pdf = engine.markdown("# Font Test\n\nCustom font text")
    .css("body { font-family: \"Jersey 25\"; }")
    .font(new File("fonts/Jersey25-Regular.ttf"), "Jersey 25")
    .toPdf();

font(...) also accepts Path, URL, and InputStream.

Google Fonts

Google Fonts typically distribute woff2 files, which OpenHTMLtoPDF does not support. Use the TTF variant instead. You can find TTF URLs via the Google Fonts TTF list.

byte[] pdf = engine.markdown("# Sofia font example\n\nHello world")
    .addCss("""
        @font-face {
            font-family: "Sofia";
            src: url(http://fonts.gstatic.com/s/sofia/v5/Imnvx0Ag9r6iDBFUY5_RaQ.ttf);
        }
        body { font-family: "Sofia"; }
        """)
    .toPdf();

MarkdownToPdf GUI

A desktop application for interactive Markdown editing and PDF generation is available in the gui module.

License

MIT — see LICENSE.

Note that this library depends on OpenHTMLtoPDF (LGPL v2.1+) and Batik (Apache 2.0). See the third-party section below for full details.

Third-party libraries

Library Purpose License
commonmark-java Markdown → HTML BSD 2-Clause
OpenHTMLtoPDF HTML/XHTML → PDF LGPL 2.1+
jsoup HTML → well-formed XHTML MIT
Batik SVG rendering Apache 2.0
SLF4J Logging facade MIT

Test dependencies

Library Purpose License
JUnit Jupiter Test assertions EPL 1.0

About

A gui to convert markdown to pdf with custom styling capabilities

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors