API Reference PDF Creation
This document provides step-by-step instructions for creating a combined API reference PDF from individual API summary and module guide files.
---
Coverage Requirements
The API reference PDF should include documentation for:
1. All Dart files: Scan all subfolders of the module directory 2. Public members only: Exclude all private members (starting with
_) 3. Public classes only: Exclude all private classes (starting with _) 4.
All public API: Include classes, functions, constants, and global variables 5. Class hierarchies: Preserve inheritance relationships in documentation
---
Prerequisites
See index.md for required tools:
- Pandoc -
brew install pandoc -
TeX Live -
brew install --cask mactexorbrew install basictex
Before starting, consult .tom_metadata/index.yaml to understand the project structure (parts, modules, naming). See
project_structure.md for metadata format details.
---
Document Structure
The combined API reference document has three parts:
1. Part I: API Summary Index - Navigation tables and module overviews - Global table of contents with links to all modules - Quick Navigation table (module → reference → guide links) - Summary tables for each module listing classes, functions, global variables - Alphabetical indexes (classes, functions, global variables)
2. Part II: Module API References - Detailed API documentation per module - Full API documentation from each
api_summary_{module}.md - Use \newpage before each module for PDF page breaks - Change headline to
{Module} Reference
3. Part III: Module Guides - User guides and tutorials per module - User guides/tutorials from
doc/{module}/{module}.md - Use \newpage before each guide for PDF page breaks - Change headline to
{Module} Guide
4. Remove link columns in all tables in the document
YAML Front Matter
---
title: "{Project} API Reference"
date: "Created on DD.MM.YYYY at HH:MM"
geometry: margin=1in
toc: true
toc-depth: 1
fontsize: 11pt
---
Notes:
-
Use
toc-depth: 1to keep the table of contents shorter by skipping the lowest level of subheadings - Use dynamic date with
$(date '+%d.%m.%Y at %H:%M')in the shell script - Do not use subtitle - it adds unnecessary clutter
---
Step-by-Step Process
Step 1: Create File with YAML Front Matter and Part I
cd {project}/doc/api
# Create the file with YAML front matter (dynamic date, no subtitle)
cat > combined_api_docs.md << EOF
---
title: "{Project} API Reference"
date: "Created on $(date '+%d.%m.%Y at %H:%M')"
geometry: margin=1in
toc: true
toc-depth: 1
fontsize: 11pt
---
# Part I: API Summary Index
EOF
# Append the index content with link cleanup:
# 1. Remove entire Link column (header, separator, data)
# 2. Convert [text](url) links to plain text
# 3. Remove Guide column from Quick Navigation table
sed -E '
s/\| Link \|$//
s/\|------\|$//
s/\| \[→\]\([^)]*\) \|$//
s/\[([^]]+)\]\([^)]*\)/\1/g
' api_summary_index.md >> combined_api_docs.md
Step 2: Add Part II (Module API References)
Each module's API summary is added with a page break and renamed headline. Important: Heading levels must be increased by 1 to nest properly under the Reference section header.
# Add Part II header
printf '\n\\newpage\n\n# Part II: Module API References\n' >> combined_api_docs.md
# Helper function for title case conversion
title_case() {
echo "$1" | sed 's/_/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1'
}
# Add each API summary with renamed headline, must be in alphabetical order
for module in module1 module2 module3; do
printf '\n\\newpage\n\n' >> combined_api_docs.md
title=$(title_case "$module")
echo "## ${title} Reference" >> combined_api_docs.md
echo "" >> combined_api_docs.md
# Skip first line (original headline), remove link columns, convert links to plain text,
# and INCREASE HEADING LEVELS by 1 (## -> ###, ### -> ####, #### -> #####)
tail -n +2 "api_summary_${module}.md" | sed -E '
s/\| Link \|$//
s/\|------\|$//
s/\| \[→\]\([^)]*\) \|$//
s/\[([^]]+)\]\([^)]*\)/\1/g
s/^#### /##### /
s/^### /#### /
s/^## /### /
' >> combined_api_docs.md
done
Step 3: Add Part III (Module Guides)
Each module's guide is added with a page break and renamed headline.
# Add Part III header
printf '\n\\newpage\n\n# Part III: Module Guides\n' >> combined_api_docs.md
# Helper function for title case conversion
title_case() {
echo "$1" | sed 's/_/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1'
}
# Add each guide with renamed headline, must be in alphabetical order
for module in module1 module2 module3; do
guide_file="../{modules_folder}/${module}.md"
if [ -f "$guide_file" ]; then
printf '\n\\newpage\n\n' >> combined_api_docs.md
title=$(title_case "$module")
echo "## ${title} Guide" >> combined_api_docs.md
echo "" >> combined_api_docs.md
# Skip first line (original headline) and append rest
tail -n +2 "$guide_file" >> combined_api_docs.md
fi
done
Step 4: Generate PDF
pandoc combined_api_docs.md --pdf-engine=xelatex -o {project}_api_reference.pdf
---
Technical Notes
Link Removal
The sed script performs these transformations:
1. s/\| Link \|$// - Remove "Link" header from tables 2. s/\|------\|$// - Remove corresponding separator 3.
s/\| \[→\]\([^)]*\) \|$// - Remove link arrow cells 4. s/\[([^]]+)\]\([^)]*\)/\1/g
- Convert [text](url) to plain text
Table Width
Pandoc's default table rendering may not use full page width. For better control:
-
Consider using a LaTeX template with
\usepackage{longtable}and column width specifications - Or use a preprocessing step to convert tables to LaTeX format
- See "MD to LaTeX Conversion" section below for advanced options
Page Numbers in TOC
The PDF's table of contents generated by toc: true in YAML automatically includes page numbers. The markdown TOC in Part I does not have page numbers (it uses hyperlinks which don't work in PDF). Consider removing the markdown TOC section from Part I if page numbers are needed.
Other Notes
- Use
--pdf-engine=xelatexinstead of default pdflatex for better Unicode support - Box-drawing characters (├─└│) in code blocks produce font warnings but don't fail the build
- Undefined hyperlink warnings are normal when internal links reference headings that changed
- Use
\newpage(not---) for page breaks in the PDF -
The
title_casefunction convertshttp_connection→Http Connection - Use
tail -n +2to skip the original headline from source files
---
Example: tom_core API Reference
cd tom_core/doc/api
# Step 1: Create with YAML and Part I (dynamic date, no subtitle)
cat > combined_api_docs.md << EOF
---
title: "Tom API Reference"
date: "Created on $(date '+%d.%m.%Y at %H:%M')"
geometry: margin=1in
toc: true
toc-depth: 1
fontsize: 11pt
---
# Part I: API Summary Index
EOF
# Clean up links in index
sed -E '
s/\| Link \|$//
s/\|------\|$//
s/\| \[→\]\([^)]*\) \|$//
s/\[([^]]+)\]\([^)]*\)/\1/g
' api_summary_index.md >> combined_api_docs.md
# Step 2: Add Part II
printf '\n\\newpage\n\n# Part II: Module API References\n' >> combined_api_docs.md
title_case() {
echo "$1" | sed 's/_/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1'
}
for module in beanlocator context crypto http_connection isolate_pooling json little_things logging observable reflection resources runtime security settings shutdown_cleanup timezoned; do
printf '\n\\newpage\n\n' >> combined_api_docs.md
title=$(title_case "$module")
echo "## ${title} Reference" >> combined_api_docs.md
echo "" >> combined_api_docs.md
# Increase heading levels by 1 to nest under Reference section
tail -n +2 "api_summary_${module}.md" | sed -E '
s/\| Link \|$//
s/\|------\|$//
s/\| \[→\]\([^)]*\) \|$//
s/\[([^]]+)\]\([^)]*\)/\1/g
s/^#### /##### /
s/^### /#### /
s/^## /### /
' >> combined_api_docs.md
done
# Step 3: Add Part III
printf '\n\\newpage\n\n# Part III: Module Guides\n' >> combined_api_docs.md
for module in beanlocator context crypto http_connection isolate_pooling json little_things logging observable reflection resources runtime security settings shutdown_cleanup timezoned; do
guide_file="../tombase/${module}.md"
if [ -f "$guide_file" ]; then
printf '\n\\newpage\n\n' >> combined_api_docs.md
title=$(title_case "$module")
echo "## ${title} Guide" >> combined_api_docs.md
echo "" >> combined_api_docs.md
tail -n +2 "$guide_file" >> combined_api_docs.md
fi
done
# Step 4: Generate PDF
pandoc combined_api_docs.md --pdf-engine=xelatex -o tom_api_reference.pdf
---
Output Files
| File | Description |
|---|---|
combined_api_docs.md |
Assembled Markdown source (~11,500 lines for tom_core) |
{project}_api_reference.pdf |
Final PDF (~540KB, ~220 pages for tom_core) |
---
MD to LaTeX Conversion (Advanced)
For finer control over PDF formatting (table widths, column alignment, fonts), consider a two-step process:
Option 1: Pandoc with Custom LaTeX Template
Create a custom LaTeX template that includes:
% In custom-template.tex
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{array}
\setlength{\LTleft}{0pt}
\setlength{\LTright}{\fill}
Then use: pandoc --template=custom-template.tex ...
Option 2: Direct MD to LaTeX Preprocessing
Write a script that converts markdown tables to LaTeX format before PDF generation:
# Convert markdown tables to LaTeX longtable format
# This allows precise column width control like:
# \begin{longtable}{|p{3cm}|p{8cm}|p{3cm}|}
Recommendation
For most use cases, the current pandoc approach is sufficient. Consider the LaTeX approach only if:
- Tables consistently overflow or have layout issues
- You need precise column width specifications
- You want custom fonts or advanced typography
The trade-off is increased complexity and maintenance burden.