
remark plugin to compile markdown to pdf.
- Uses pdfkit for compilation, to avoid issues with puppeteer or headless chromium.
- Works in any environment (e.g. browser, Node.js).
- Generates PDF/A-3A compliant document for accessibility.
- Supports configuration of page layout, fonts and styles.
Supported mdast nodes
Currently, some of the default styles may not be nice. If you have some feature requests or improvements, please create a issue or PR.
Demo
https://inokawa.github.io/remark-pdf/
Install
npm install remark-pdf
Usage
Browser
import { unified } from "unified";
import markdown from "remark-parse";
import pdf from "remark-pdf";
import { saveAs } from "file-saver";
const processor = unified().use(markdown).use(pdf);
const text = "# hello world";
(async () => {
const doc = await processor.process(text);
const arrayBuffer = await doc.result;
saveAs(new Blob([arrayBuffer], { type: "application/pdf" }), "example.pdf");
})();
Node.js
import { unified } from "unified";
import markdown from "remark-parse";
import pdf from "remark-pdf";
import * as fs from "fs";
const processor = unified().use(markdown).use(pdf);
const text = "# hello world";
(async () => {
const doc = await processor.process(text);
const arrayBuffer = await doc.result;
fs.writeFileSync("example.pdf", Buffer.from(arrayBuffer));
})();
Example: Custom fonts
Use custom fonts by providing a fonts option. Use the fonts by name in your styles configurations; the font file will be autoselected based on the chosen bold and italic style specifications.
Note that variable-width fonts are supported, but the path to the same font file must be supplied for all four font variant styles.
import { unified } from "unified";
import markdown from "remark-parse";
import pdf from "remark-pdf";
import * as fs from "fs";
const processor = unified()
.use(markdown)
.use(pdf, {
fonts: [
{
name: "National Park",
normal: fs.readFileSync("/path/to/fonts/nationalpark-variablevf.ttf"),
bold: fs.readFileSync("/path/to/fonts/nationalpark-variablevf.ttf"),
italic: fs.readFileSync("/path/to/fonts/nationalpark-variablevf.ttf"),
bolditalic: fs.readFileSync(
"/path/to/fonts/nationalpark-variablevf.ttf",
),
},
{
name: "Merriweather Sans",
normal: fs.readFileSync("/path/to/fonts/merriweathersans-light.ttf"),
bold: fs.readFileSync("/path/to/fonts/merriweathersans-bold.ttf"),
italic: fs.readFileSync("/path/to/fonts/merriweathersans-italic.ttf"),
bolditalic: fs.readFileSync(
"/path/to/fonts/merriweathersans-bolditalic.ttf",
),
},
],
styles: {
default: { font: "Merriweather Sans", italic: true },
head1: {
bold: true,
font: "National Park",
fontSize: 24,
},
},
});
const text = `
# Header in National Park bold
Body text in Merriweather Sans Italic
`;
(async () => {
const doc = await processor.process(text);
const arrayBuffer = await doc.result;
fs.writeFileSync("example.pdf", Buffer.from(arrayBuffer));
})();
Documentation
Contribute
All contributions are welcome. If you find a problem, feel free to create an issue or a PR.
Making a Pull Request
- Fork this repo.
- Run
npm install. - Commit your fix.
- Add tests to cover the fix.
- Make a PR and confirm all the CI checks passed.