#!/usr/bin/env bash set -euo pipefail self=$(readlink -f "${BASH_SOURCE[0]}") assets=${MD_TO_PDF_HOME:-} if [[ -z $assets ]]; then for candidate in \ "${XDG_DATA_HOME:-$HOME/.local/share}/md_to_pdf" \ "$(dirname "$self")/../md_to_pdf" \ "$(dirname "$self")/md_to_pdf" do if [[ -f $candidate/base.css ]]; then assets=$(readlink -f "$candidate") break fi done fi die() { printf 'md_to_pdf: %s\n' "$*" >&2; exit 1; } view() { ((open_after)) && setsid "${MD_TO_PDF_VIEWER:-xdg-open}" "$1" >/dev/null 2>&1 & :; } [[ -n $assets ]] || die "cannot find assets (base.css); set MD_TO_PDF_HOME" themes() { find "$assets/themes" -name '*.css' -printf '%f\n' | sed 's/\.css$//' | sort; } usage() { cat <<'USAGE' md_to_pdf [options] FILE.md [FILE.md ...] Render markdown to a typeset PDF via pandoc and WeasyPrint. Output: -o, --output PATH output file (single input only) -d, --dir DIR output directory (default: /tmp) --html also write the intermediate HTML --html-only write only the HTML, skip the PDF -O, --open open the result when done Style: -t, --theme NAME colour theme (default: paper, or $MD_TO_PDF_THEME) -l, --list-themes list available themes --sans sans-serif body text --ragged ragged-right instead of justified -s, --size PT base font size, e.g. 11pt (default: 10pt) --paper SIZE letter, a4, a5, legal, ... (default: letter) --margin CSS page margin shorthand (default: 0.9in 1in) Document: --toc include a table of contents -n, --number-sections number the headings --engine ENGINE weasyprint (default) or typst, for documents with math Anything after -- is passed straight to pandoc. USAGE } theme=${MD_TO_PDF_THEME:-paper} output="" outdir="" keep_html=0 html_only=0 open_after=0 paper=letter margin="0.9in 1in" fontsize=10pt sans=0 ragged=0 toc=0 numbered=0 engine=weasyprint inputs=() passthrough=() while (($#)); do case $1 in -o|--output) output=$2; shift 2 ;; -d|--dir) outdir=$2; shift 2 ;; --html) keep_html=1; shift ;; --html-only) html_only=1; keep_html=1; shift ;; -O|--open) open_after=1; shift ;; -t|--theme) theme=$2; shift 2 ;; -l|--list-themes) themes | paste -sd' '; exit 0 ;; --sans) sans=1; shift ;; --ragged) ragged=1; shift ;; -s|--size) fontsize=$2; shift 2 ;; --paper) paper=$2; shift 2 ;; --margin) margin=$2; shift 2 ;; --toc) toc=1; shift ;; -n|--number-sections) numbered=1; shift ;; --engine) engine=$2; shift 2 ;; -h|--help) usage; exit 0 ;; --) shift; passthrough+=("$@"); break ;; -*) die "unknown option: $1 (try --help)" ;; *) inputs+=("$1"); shift ;; esac done ((${#inputs[@]})) || { usage >&2; exit 1; } [[ -f $assets/themes/$theme.css ]] || die "no such theme: $theme (have: $(themes | paste -sd' '))" (( ${#inputs[@]} == 1 )) || [[ -z $output ]] || die "--output takes a single input file" pandoc_args=( --from markdown+smart --to html5 --standalone --template "$assets/template.html" --highlight-style kate --css "file://$assets/base.css" --css "file://$assets/themes/$theme.css" -V "papersize=$paper" -V "margin=$margin" -V "fontsize=$fontsize" ) ((sans)) && pandoc_args+=(-V 'bodyfont=var(--font-head)') || : ((ragged)) && pandoc_args+=(-V ragged=1) || : ((toc)) && pandoc_args+=(--toc --toc-depth=3) || : ((numbered)) && pandoc_args+=(--number-sections) || : pandoc_args+=("${passthrough[@]+"${passthrough[@]}"}") tmpdir=$(mktemp -d) trap 'rm -rf "$tmpdir"' EXIT for src in "${inputs[@]}"; do [[ -f $src ]] || die "no such file: $src" src=$(readlink -f "$src") srcdir=$(dirname "$src") stem=$(basename "$src"); stem=${stem%.*} dest_dir=${outdir:-/tmp} mkdir -p "$dest_dir" pdf=${output:-$dest_dir/$stem.pdf} if [[ $engine == typst ]]; then typst_args=() typst_template=${XDG_DATA_HOME:-$HOME/.local/share}/pandoc/templates/default.typst [[ -f $typst_template ]] && typst_args=(--template "$typst_template") || : pandoc "$src" --standalone --pdf-engine typst "${typst_args[@]}" -o "$pdf" printf '%s\n' "$pdf" view "$pdf" continue fi html=$tmpdir/$stem.html ((keep_html)) && html=$dest_dir/$stem.html || : pandoc "${pandoc_args[@]}" -M "pagetitle=$stem" -V "basehref=file://$srcdir/" -o "$html" "$src" if ((html_only)); then printf '%s\n' "$html" continue fi weasyprint -q "$html" "$pdf" printf '%s\n' "$pdf" view "$pdf" done