Skip to content

Commit 7f0b62b

Browse files
committed
docfix: adding generate-pdf.sh which uses the OBP brand colours and a
similar font.
1 parent 68a824e commit 7f0b62b

File tree

2 files changed

+313
-0
lines changed

2 files changed

+313
-0
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
OBP Documentation PDF Generation - Font Technical Note
2+
=======================================================
3+
4+
FONT ISSUE: Plus Jakarta Sans Variable Font Incompatibility with XeLaTeX
5+
6+
The Open Bank Project brand guidelines specify Plus Jakarta Sans as the official font.
7+
However, this font cannot be used in the current PDF generation pipeline due to a
8+
technical incompatibility between variable font formats and XeLaTeX/xdvipdfmx.
9+
10+
TECHNICAL ROOT CAUSE:
11+
12+
The Plus Jakarta Sans fonts available from Google Fonts are provided as variable fonts
13+
(.ttf files with weight axis [wght]). When XeLaTeX attempts to resolve font variants
14+
(specifically Bold and BoldItalic), it fails with:
15+
16+
Error: "xdvipdfmx:fatal: Invalid font: -1 (0)"
17+
18+
This occurs because:
19+
1. Variable fonts store multiple weights in a single file using OpenType variation tables
20+
2. XeLaTeX's font resolver (fontspec package) attempts to find discrete font files for
21+
Bold (/B), Italic (/I), and BoldItalic (/BI) variants
22+
3. The variable font doesn't expose these as separate font instances
23+
4. xdvipdfmx (the backend that converts XeTeX's XDV to PDF) cannot map the font ID (-1)
24+
25+
ATTEMPTED SOLUTIONS (All Failed):
26+
27+
1. Using variable fonts with explicit paths and FakeBold features - syntax errors
28+
2. Installing static font variants - these don't exist in Google Fonts repository
29+
3. Font name resolution via fc-list - system finds font but XeLaTeX cannot load variants
30+
4. Explicit fontspec configuration with BoldFont/ItalicFont parameters - path resolution failures
31+
32+
CURRENT SOLUTION:
33+
34+
DejaVu Sans is used as a reliable alternative because:
35+
- It's a standard PostScript/TrueType font with discrete weight files
36+
- Pre-installed on most Linux systems
37+
- Full XeLaTeX compatibility
38+
- All OBP brand colors (#1BA563, #0A281E, #5F8E82) are correctly implemented
39+
40+
FUTURE RESOLUTION OPTIONS:
41+
42+
- Upgrade to TeX Live 2023+ with improved variable font support
43+
- Switch to LuaLaTeX engine (better variable font handling)
44+
- Convert variable fonts to static instances using fonttools
45+
- Use HTML/CSS to PDF tools (wkhtmltopdf, weasyprint) that handle variable fonts natively
46+
47+
For questions, contact: TESOBE GmbH Development Team
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
#!/bin/bash
2+
# generate-pdf.sh - Generate professional PDF from markdown documentation
3+
# Usage:
4+
# ./generate-pdf.sh # Process all .md files in current directory
5+
# ./generate-pdf.sh [input.md] # Process specific file
6+
# ./generate-pdf.sh [input.md] [output.pdf] # Process with custom output name
7+
#
8+
# This script uses Open Bank Project brand guidelines:
9+
# - Font: DejaVu Sans (for compatibility)
10+
# - Colors: OBP Green (#1BA563), Dark Green (#0A281E), Light Green (#5F8E82)
11+
12+
set -e
13+
14+
# Check if pandoc is installed
15+
if ! command -v pandoc &> /dev/null; then
16+
echo "Error: pandoc is not installed"
17+
echo "Install with: sudo apt-get install pandoc texlive-xetex"
18+
exit 1
19+
fi
20+
21+
# Check if xelatex is available
22+
if ! command -v xelatex &> /dev/null; then
23+
echo "Error: xelatex is not installed"
24+
echo "Install with: sudo apt-get install texlive-xetex texlive-fonts-extra"
25+
exit 1
26+
fi
27+
28+
# OBP Brand Colors (defined in LaTeX header)
29+
OBP_GREEN="1BA563" # Primary green: RGB(27, 165, 99)
30+
OBP_DARK_GREEN="0A281E" # Dark green: RGB(10, 40, 30)
31+
OBP_LIGHT_GREEN="5F8E82" # Secondary green: RGB(95, 142, 130)
32+
33+
# Create LaTeX header with OBP branding
34+
LATEX_HEADER=$(cat <<'EOF'
35+
\usepackage{xcolor}
36+
\definecolor{OBPGreen}{HTML}{1BA563}
37+
\definecolor{OBPDarkGreen}{HTML}{0A281E}
38+
\definecolor{OBPLightGreen}{HTML}{5F8E82}
39+
\usepackage{fontspec}
40+
\defaultfontfeatures{Ligatures=TeX}
41+
\setmainfont{DejaVu Sans}
42+
\setsansfont{DejaVu Sans}
43+
\setmonofont{DejaVu Sans Mono}[Scale=0.9]
44+
\usepackage{fancyhdr}
45+
\pagestyle{fancy}
46+
\fancyhf{}
47+
\fancyhead[L]{\textcolor{OBPDarkGreen}{\small\leftmark}}
48+
\fancyhead[R]{\textcolor{OBPDarkGreen}{\small\thepage}}
49+
\fancyfoot[C]{\textcolor{OBPLightGreen}{\footnotesize Copyright © TESOBE GmbH 2025}}
50+
\renewcommand{\headrulewidth}{0.5pt}
51+
\renewcommand{\footrulewidth}{0.5pt}
52+
\renewcommand{\headrule}{\hbox to\headwidth{\color{OBPGreen}\leaders\hrule height \headrulewidth\hfill}}
53+
\renewcommand{\footrule}{\hbox to\headwidth{\color{OBPLightGreen}\leaders\hrule height \footrulewidth\hfill}}
54+
\usepackage{titlesec}
55+
\titleformat{\chapter}[display]
56+
{\normalfont\huge\bfseries\color{OBPGreen}}
57+
{\chaptertitlename\ \thechapter}{20pt}{\Huge}
58+
\titleformat{\section}
59+
{\normalfont\Large\bfseries\color{OBPGreen}}
60+
{\thesection}{1em}{}
61+
\titleformat{\subsection}
62+
{\normalfont\large\bfseries\color{OBPDarkGreen}}
63+
{\thesubsection}{1em}{}
64+
\titleformat{\subsubsection}
65+
{\normalfont\normalsize\bfseries\color{OBPDarkGreen}}
66+
{\thesubsubsection}{1em}{}
67+
\usepackage{listings}
68+
\lstset{
69+
basicstyle=\ttfamily\small,
70+
frame=single,
71+
rulecolor=\color{OBPLightGreen},
72+
backgroundcolor=\color{gray!5},
73+
breaklines=true,
74+
postbreak=\mbox{\textcolor{OBPGreen}{$\hookrightarrow$}\space},
75+
showstringspaces=false,
76+
commentstyle=\color{OBPDarkGreen},
77+
keywordstyle=\color{OBPGreen}\bfseries
78+
}
79+
EOF
80+
)
81+
82+
# Function to generate PDF from a markdown file
83+
generate_pdf() {
84+
local INPUT_FILE="$1"
85+
local OUTPUT_FILE="$2"
86+
local DOC_TITLE="$3"
87+
88+
echo " Processing: $INPUT_FILE"
89+
echo " Output: $OUTPUT_FILE"
90+
91+
pandoc "$INPUT_FILE" \
92+
-o "$OUTPUT_FILE" \
93+
--pdf-engine=xelatex \
94+
--toc \
95+
--toc-depth=3 \
96+
--number-sections \
97+
--highlight-style=tango \
98+
-V geometry:margin=1in \
99+
-V fontsize=11pt \
100+
-V documentclass=report \
101+
-V papersize=a4 \
102+
-V colorlinks=true \
103+
-V linkcolor="[HTML]{$OBP_GREEN}" \
104+
-V urlcolor="[HTML]{$OBP_GREEN}" \
105+
-V toccolor="[HTML]{$OBP_DARK_GREEN}" \
106+
-V header-includes="$LATEX_HEADER" \
107+
--metadata title="$DOC_TITLE" \
108+
--metadata author="Open Bank Project / TESOBE GmbH" \
109+
--metadata date="$(date +%Y-%m-%d)" \
110+
2>&1 | grep -v "^$" || true
111+
112+
if [ -f "$OUTPUT_FILE" ]; then
113+
echo " ✓ Success ($(du -h "$OUTPUT_FILE" | cut -f1))"
114+
return 0
115+
else
116+
echo " ✗ Failed"
117+
return 1
118+
fi
119+
}
120+
121+
# Main script logic
122+
if [ $# -eq 0 ]; then
123+
# No arguments - process all .md files in current directory
124+
echo "=========================================="
125+
echo "OBP Documentation PDF Generator"
126+
echo "=========================================="
127+
echo ""
128+
echo "Processing all markdown files in current directory..."
129+
echo ""
130+
131+
MD_FILES=(*.md)
132+
133+
if [ ${#MD_FILES[@]} -eq 0 ] || [ ! -f "${MD_FILES[0]}" ]; then
134+
echo "No markdown files found in current directory"
135+
exit 1
136+
fi
137+
138+
SUCCESS_COUNT=0
139+
FAIL_COUNT=0
140+
TOTAL_COUNT=${#MD_FILES[@]}
141+
142+
for MD_FILE in "${MD_FILES[@]}"; do
143+
if [ -f "$MD_FILE" ]; then
144+
# Generate output filename
145+
OUTPUT_FILE="${MD_FILE%.md}.pdf"
146+
147+
# Generate document title from filename
148+
DOC_TITLE=$(echo "${MD_FILE%.md}" | sed 's/_/ /g' | sed 's/\b\(.\)/\u\1/g')
149+
150+
echo "[$((SUCCESS_COUNT + FAIL_COUNT + 1))/$TOTAL_COUNT]"
151+
152+
if generate_pdf "$MD_FILE" "$OUTPUT_FILE" "$DOC_TITLE"; then
153+
((SUCCESS_COUNT++))
154+
else
155+
((FAIL_COUNT++))
156+
fi
157+
echo ""
158+
fi
159+
done
160+
161+
echo "=========================================="
162+
echo "Generation Complete"
163+
echo "=========================================="
164+
echo ""
165+
echo "Summary:"
166+
echo " Total files: $TOTAL_COUNT"
167+
echo " Successful: $SUCCESS_COUNT"
168+
echo " Failed: $FAIL_COUNT"
169+
echo ""
170+
171+
if [ $SUCCESS_COUNT -gt 0 ]; then
172+
echo "Generated PDFs:"
173+
ls -lh *.pdf 2>/dev/null | awk '{print " " $9 " (" $5 ")"}'
174+
echo ""
175+
fi
176+
177+
echo "PDF styling:"
178+
echo " - Font: DejaVu Sans (professional, compatible)"
179+
echo " - Colors: OBP brand palette"
180+
echo " * Links: OBP Green (#$OBP_GREEN)"
181+
echo " * Headers: Dark Green (#$OBP_DARK_GREEN)"
182+
echo " * Accents: Light Green (#$OBP_LIGHT_GREEN)"
183+
echo " - Table of contents: 3 levels"
184+
echo " - Section numbering: Enabled"
185+
echo " - Headers/footers: OBP branded"
186+
echo ""
187+
188+
if [ $FAIL_COUNT -gt 0 ]; then
189+
exit 1
190+
fi
191+
192+
elif [ $# -eq 1 ]; then
193+
# One argument - process specific file
194+
INPUT="$1"
195+
OUTPUT="${INPUT%.md}.pdf"
196+
197+
if [ ! -f "$INPUT" ]; then
198+
echo "Error: Input file '$INPUT' not found"
199+
exit 1
200+
fi
201+
202+
DOC_TITLE=$(echo "${INPUT%.md}" | sed 's/_/ /g' | sed 's/\b\(.\)/\u\1/g')
203+
204+
echo "=========================================="
205+
echo "OBP Documentation PDF Generator"
206+
echo "=========================================="
207+
echo ""
208+
209+
if generate_pdf "$INPUT" "$OUTPUT" "$DOC_TITLE"; then
210+
echo ""
211+
echo "=========================================="
212+
echo "[SUCCESS] PDF generated successfully!"
213+
echo "=========================================="
214+
echo ""
215+
ls -lh "$OUTPUT"
216+
echo ""
217+
else
218+
echo ""
219+
echo "=========================================="
220+
echo "[FAIL] Error generating PDF"
221+
echo "=========================================="
222+
echo ""
223+
exit 1
224+
fi
225+
226+
elif [ $# -eq 2 ]; then
227+
# Two arguments - custom input and output
228+
INPUT="$1"
229+
OUTPUT="$2"
230+
231+
if [ ! -f "$INPUT" ]; then
232+
echo "Error: Input file '$INPUT' not found"
233+
exit 1
234+
fi
235+
236+
DOC_TITLE=$(echo "${INPUT%.md}" | sed 's/_/ /g' | sed 's/\b\(.\)/\u\1/g')
237+
238+
echo "=========================================="
239+
echo "OBP Documentation PDF Generator"
240+
echo "=========================================="
241+
echo ""
242+
243+
if generate_pdf "$INPUT" "$OUTPUT" "$DOC_TITLE"; then
244+
echo ""
245+
echo "=========================================="
246+
echo "[SUCCESS] PDF generated successfully!"
247+
echo "=========================================="
248+
echo ""
249+
ls -lh "$OUTPUT"
250+
echo ""
251+
else
252+
echo ""
253+
echo "=========================================="
254+
echo "[FAIL] Error generating PDF"
255+
echo "=========================================="
256+
echo ""
257+
exit 1
258+
fi
259+
260+
else
261+
echo "Usage:"
262+
echo " $0 # Process all .md files in current directory"
263+
echo " $0 [input.md] # Process specific file"
264+
echo " $0 [input.md] [out.pdf] # Process with custom output name"
265+
exit 1
266+
fi

0 commit comments

Comments
 (0)