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 mactex or brew 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: 1 to 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=xelatex instead 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_case function converts http_connection → Http Connection
  • Use tail -n +2 to 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

FileDescription
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.