Skip to content

Instantly share code, notes, and snippets.

@oscarrenalias
Created April 11, 2025 20:01
Show Gist options
  • Save oscarrenalias/0e4683ed4d77195f5ddc114111d0e029 to your computer and use it in GitHub Desktop.
Save oscarrenalias/0e4683ed4d77195f5ddc114111d0e029 to your computer and use it in GitHub Desktop.
Script that converts a bunch of separate markdown files into a single continuous PDFs that retains assets (images), tables of contents as well as links.

Requires the following brew packages to be installed in MacOS, actual list and names will vary depending on operating system:

pandoc
texlive
#!/bin/bash
# Create a temporary directory for our work
TEMP_DIR=$(mktemp -d)
COMBINED_MD="$TEMP_DIR/combined.md"
OUTPUT_PDF="output.pdf"
echo "Creating combined markdown file..."
# Start with the index file if it exists
if [ -f "index.md" ]; then
cat index.md > "$COMBINED_MD"
echo -e "\n\n" >> "$COMBINED_MD"
fi
# Add a table of contents marker
echo -e "\\\\newpage\n# Table of Contents\n\n" >> "$COMBINED_MD"
echo -e "{:toc}\n\n\\\\newpage\n" >> "$COMBINED_MD"
# Function to process markdown files in a directory
process_directory() {
local dir=$1
local prefix=$2
# Process files in the current directory first
for file in "$dir"/*.md; do
if [ -f "$file" ] && [ "$(basename "$file")" != "index.md" ]; then
echo "Adding $(basename "$file")..."
# Add a section header based on directory structure
if [ -n "$prefix" ]; then
echo -e "\\\\newpage\n# $prefix - $(basename "${file%.md}")\n\n" >> "$COMBINED_MD"
else
echo -e "\\\\newpage\n# $(basename "${file%.md}")\n\n" >> "$COMBINED_MD"
fi
# Add the content with image path correction
# Get the relative directory path for image reference correction
local rel_dir=$(dirname "$file")
if [ "$rel_dir" = "." ]; then
# File is in the root directory, no path adjustment needed
cat "$file" >> "$COMBINED_MD"
else
# Adjust image references to account for the file's original location
sed 's|!\[\(.*\)\](\([^/][^:]*\))|![\1]('"$rel_dir"'/\2)|g' "$file" >> "$COMBINED_MD"
fi
echo -e "\n\n" >> "$COMBINED_MD"
fi
done
# Then process subdirectories
for subdir in "$dir"/*/; do
if [ -d "$subdir" ]; then
local dirname=$(basename "$subdir")
local new_prefix
if [ -n "$prefix" ]; then
new_prefix="$prefix / $dirname"
else
new_prefix="$dirname"
fi
process_directory "$subdir" "$new_prefix"
fi
done
}
# Process the root directory first (excluding index.md which we already added)
for file in *.md; do
if [ -f "$file" ] && [ "$file" != "index.md" ] && [ "$file" != "README.md" ] && [ "$file" != "convert_to_pdf.sh" ]; then
echo "Adding $file..."
echo -e "\\\\newpage\n# $(basename "${file%.md}")\n\n" >> "$COMBINED_MD"
# Add the content with image path correction for root files
rel_dir=$(dirname "$file")
if [ "$rel_dir" = "." ]; then
# File is in the root directory, no path adjustment needed
cat "$file" >> "$COMBINED_MD"
else
# Adjust image references to account for the file's original location
sed 's|!\[\(.*\)\](\([^/][^:]*\))|![\1]('"$rel_dir"'/\2)|g' "$file" >> "$COMBINED_MD"
fi
echo -e "\n\n" >> "$COMBINED_MD"
fi
done
# Process each subdirectory
for dir in */; do
if [ -d "$dir" ]; then
dirname=$(basename "$dir")
process_directory "$dir" "$dirname"
fi
done
echo "Converting to PDF..."
# Use pandoc to convert the combined markdown to PDF
pandoc "$COMBINED_MD" \
--pdf-engine=xelatex \
--toc \
--toc-depth=3 \
--highlight-style=tango \
-V geometry:margin=1in \
-V linkcolor:blue \
-V toccolor:blue \
-V mainfont="Arial Unicode MS" \
-o "$OUTPUT_PDF"
echo "Done! PDF created as $OUTPUT_PDF"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment