Skip to content

Commit 0950bfd

Browse files
committed
feat: add pdf generation
1 parent 4bd9798 commit 0950bfd

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,12 @@ ci: all
4141
+@make -B exercises # force make (in case exercise files have been edited directly)
4242
if [ -n "$$(git status --porcelain)" ]; then echo 'ERROR: Exercise files are not up-to-date with solutions. `git diff` and `git status` after re-making them:'; git diff; git status; exit 1; fi
4343
.PHONY: ci
44+
45+
pdf: html
46+
@if ! command -v wkhtmltopdf >/dev/null 2>&1; then \
47+
echo "wkhtmltopdf not found. Running inside nix-shell..."; \
48+
nix-shell -p wkhtmltopdf --run "bash ./generate_pdf.sh"; \
49+
else \
50+
bash ./generate_pdf.sh; \
51+
fi
52+
.PHONY: pdf

generate_pdf.sh

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
HTML_DIR="html"
5+
TOC_FILE="${HTML_DIR}/toc.html"
6+
7+
if [ ! -f "$TOC_FILE" ]; then
8+
echo "Error: $TOC_FILE not found! Run 'make html' first."
9+
exit 1
10+
fi
11+
12+
generate_for() {
13+
local PREFIX=$1
14+
local FILTERED_TOC="${HTML_DIR}/toc_${PREFIX}.html"
15+
local OUTPUT_PDF="${PREFIX}.pdf"
16+
17+
# Capitalize the first letter for the title (Bash 4.0+)
18+
local TITLE="Iris Tutorial - ${PREFIX^}"
19+
20+
echo "--- Building ${OUTPUT_PDF} ---"
21+
22+
# 1. Generate the filtered TOC
23+
# This awk script passes through everything outside `<div id="toc">`.
24+
# Inside the TOC, it checks each `<h2>` to see if the link belongs to
25+
# the current prefix (e.g., "solutions"). If so, it keeps printing until
26+
# the next `<h2>` tells it to stop.
27+
awk -v prefix="$PREFIX" '
28+
BEGIN { printing = 1; in_toc = 0; }
29+
/<div id="toc">/ { in_toc = 1; print; next; }
30+
/<\/div>/ && in_toc { in_toc = 0; print; next; }
31+
/<h2/ && in_toc {
32+
if ($0 ~ "href=\"" prefix "\\.") printing = 1;
33+
else printing = 0;
34+
}
35+
{ if (!in_toc || printing) print; }
36+
' "$TOC_FILE" > "$FILTERED_TOC"
37+
38+
# 2. Extract the ordered list of HTML filenames for this prefix.
39+
# By only looking at lines with '<h2', we cleanly grab the top-level files.
40+
local FILES
41+
FILES=$(grep '<h2' "$TOC_FILE" | grep -oE 'href="'"${PREFIX}"'\.[^"]*\.html"' | cut -d'"' -f2 | awk '!x[$0]++')
42+
43+
# 3. Assemble inputs (starting with the filtered TOC)
44+
local INPUTS=("$FILTERED_TOC")
45+
for f in $FILES; do
46+
INPUTS+=("${HTML_DIR}/$f")
47+
done
48+
49+
echo "Combining ${#INPUTS[@]} HTML files into ${OUTPUT_PDF}..."
50+
51+
# 4. Generate the PDF
52+
wkhtmltopdf \
53+
--enable-local-file-access \
54+
--javascript-delay 500 \
55+
--title "$TITLE" \
56+
--footer-center "[page] / [topage]" \
57+
"${INPUTS[@]}" \
58+
"$OUTPUT_PDF"
59+
60+
echo "+++ Successfully generated ${OUTPUT_PDF} +++"
61+
echo ""
62+
}
63+
64+
generate_for "exercises"
65+
generate_for "solutions"

0 commit comments

Comments
 (0)