Skip to content

yuusoft-org/mdtopdf

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mdtopdf

mdtopdf is a small, configurable Markdown-to-PDF CLI built on top of Pandoc. It is intended for repeatable document generation from plain Markdown, with optional fonts, logos, LaTeX header includes, and Pandoc defaults files.

The tool does not hardcode any company branding. Letterheads, logos, fonts, and document styling are supplied through CLI flags or JSON config files.

Requirements

  • Node.js 20 or newer
  • pandoc on PATH
  • A Pandoc PDF engine, usually xelatex

Check your environment:

node src/cli.js --check

Expected output looks like:

ok pandoc: pandoc 3.x
ok xelatex: XeTeX 3.x

Install

From this repository:

npm install
node src/cli.js --help

Use as a local binary from another project:

npm install --save-dev /path/to/mdtopdf
npx mdtopdf docs/contract.md -o out/contract.pdf

Build a standalone binary with Bun:

bun run build
./dist/mdtopdf --help

Quick Start

Convert one Markdown file. If -o is omitted for a single input file, the output path is inferred from the input filename.

node src/cli.js docs/contract.md
# writes docs/contract.pdf

Convert multiple Markdown files into one PDF:

node src/cli.js docs/01-intro.md docs/02-terms.md -o out/document.pdf

Use a logo on every page:

node src/cli.js docs/contract.md \
  -o out/contract.pdf \
  --preset letterhead \
  --logo assets/logo.png \
  --logo-all-pages \
  --logo-height 1.2cm \
  --headheight 44pt \
  --headsep 20pt

Use local font files without installing fonts system-wide:

node src/cli.js docs/contract.md \
  -o out/contract.pdf \
  --font-family DocumentFont \
  --font-dir fonts \
  --font-regular NotoSerif-Regular.ttf \
  --font-bold NotoSerif-Bold.ttf \
  --font-italic NotoSerif-Italic.ttf \
  --font-bold-italic NotoSerif-BoldItalic.ttf

Preview the Pandoc command without generating a PDF:

node src/cli.js docs/contract.md --dry-run

Configuration

Configuration can come from three places. Later sources override earlier ones:

  1. Preset defaults
  2. JSON config file passed with --config
  3. CLI flags

Example:

{
  "preset": "letterhead",
  "out": "out/contract.pdf",
  "logo": "assets/logo.png",
  "logoAllPages": true,
  "logoHeight": "1.2cm",
  "headheight": "44pt",
  "headsep": "20pt",
  "fontFamily": "DocumentFont",
  "fontDir": "fonts",
  "fontRegular": "NotoSerif-Regular.ttf",
  "fontBold": "NotoSerif-Bold.ttf"
}

Run it:

node src/cli.js --config contract.config.json docs/contract.md

Paths inside config files are resolved relative to the config file. For font files, use fontDir plus file names when the files live together.

See:

  • examples/letterhead.config.json
  • examples/font-files.config.json
  • docs/configuration.md

Presets

Presets are intentionally generic:

Preset Purpose
default Generic A4 PDF, 2.5cm margins, page numbers on, no branding
plain Similar to default with slightly looser line height
letterhead Generic letterhead-ready layout; no logo unless --logo is provided
company Backward-compatible alias-style preset for older workflows; still no hardcoded branding

Presets live in src/presets.js and can be edited or extended for a local project. Keep project-specific logos and fonts in config files rather than in the presets.

CLI Options

Core output:

  • -o, --out <file>: output PDF path
  • --config <file>: JSON config file
  • --preset <name>: default, plain, letterhead, or company
  • --dry-run: print the Pandoc command and exit
  • --verbose: print the Pandoc command before running
  • --check: check external dependencies and exit

Pandoc and page layout:

  • --pdf-engine <name>: Pandoc PDF engine, e.g. xelatex
  • --papersize <size>: a4, letter, etc.
  • --margin <value>: shorthand page margin, e.g. 2.5cm
  • --geometry <value>: raw LaTeX geometry string; overrides --margin
  • --fontsize <size>: base font size, e.g. 11pt
  • --lineheight <value>: line spacing multiplier
  • --page-numbers / --no-page-numbers: toggle page numbers
  • --defaults <file>: Pandoc defaults file
  • --metadata <file...>: metadata files passed to Pandoc
  • --include <file...>: LaTeX header includes passed to Pandoc

Installed fonts:

  • --font <name>: installed main font name
  • --mono <name>: installed monospace font name

Font files:

  • --font-family <name>: family label used by fontspec
  • --font-dir <dir>: directory containing font files
  • --font-regular <file>: regular font file
  • --font-bold <file>: bold font file
  • --font-italic <file>: italic font file
  • --font-bold-italic <file>: bold italic font file

Logo header:

  • --logo <path>: logo image path
  • --logo-height <value>: logo height, e.g. 1.2cm
  • --logo-all-pages: apply logo to every page
  • --headheight <value>: LaTeX header height
  • --headsep <value>: space between header and body

CJK helpers:

  • --cjk / --no-cjk: define CJK helper font families in LaTeX
  • --cjk-cn <name>: Chinese CJK font
  • --cjk-jp <name>: Japanese CJK font
  • --cjk-kr <name>: Korean CJK font

Pandoc Defaults Files

You can use normal Pandoc defaults files through --defaults:

node src/cli.js docs/contract.md --defaults templates/default.defaults.yaml

Templates included here:

  • templates/default.defaults.yaml
  • templates/letterhead.defaults.yaml
  • templates/company.defaults.yaml for older workflows

Markdown Notes

Pandoc supports raw LaTeX in Markdown when targeting PDF. This is useful for page breaks:

\newpage

## Schedule A

Avoid standalone lines made entirely of underscores when you want signature fields. Pandoc may interpret them as horizontal rules. Prefer labelled fields:

Signature: _____________________
Date: _________________________

Troubleshooting

pandoc not found on PATH

: Install Pandoc and verify with pandoc --version.

xelatex not found

: Install a TeX distribution such as MacTeX, TeX Live, or MiKTeX. Or choose a different engine with --pdf-engine.

Logo overlaps body text

: Increase --headheight and --headsep.

Font not found

: Use --font only for fonts installed system-wide. For portable output, use --font-dir and font file options.

Title or words hyphenate awkwardly

: Add a small LaTeX include file with project-specific typography rules and pass it with --include. Keep that file in the consuming project rather than baking the rule into this tool.

Development

Run tests:

npm test

Run the CLI locally:

node src/cli.js --help
node src/cli.js --check

Build standalone binary:

bun run build

The implementation is dependency-light by design: Commander for CLI parsing, Node.js built-ins for everything else, and Pandoc for document conversion.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors