LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

\n\n - id: check-compile\n name: Check LaTeX Compiles\n entry: pdflatex -interaction=nonstopmode -halt-on-error\n language: system\n files: 'main\\.tex

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

\n pass_filenames: false\n\n - id: trailing-whitespace\n name: Trim Trailing Whitespace\n entry: sed -i 's/[[:space:]]*$//'\n language: system\n files: '\\.tex

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

\n\n # Standard pre-commit hooks\n - repo: https://github.com/pre-commit/pre-commit-hooks\n rev: v4.5.0\n hooks:\n - id: check-yaml\n - id: check-added-large-files\n args: ['--maxkb=1000']\n - id: end-of-file-fixer\n files: '\\.tex

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

\n - id: mixed-line-ending\n args: ['--fix=lf']\n```\n\n### Custom Hook Scripts\n\n**scripts/latex-check.sh**:\n\n```bash\n#!/bin/bash\n# Check LaTeX files before commit\n\nset -e\n\necho \"Running LaTeX checks...\"\n\n# Check for common issues\nfor file in \"$@\"; do\n if [[ \"$file\" == *.tex ]]; then\n # Check for \\label without \\ref\n if grep -q '\\\\label{' \"$file\"; then\n label=$(grep -o '\\\\label{[^}]*}' \"$file\" | sed 's/\\\\label{\\([^}]*\\)}/\\1/')\n if ! grep -q \"\\\\ref{$label}\" *.tex chapters/*.tex 2>/dev/null; then\n echo \"Warning: Unused label in $file: $label\"\n fi\n fi\n\n # Check for TODO comments\n if grep -qi 'TODO\\|FIXME\\|XXX' \"$file\"; then\n echo \"Warning: TODO comments found in $file\"\n grep -n 'TODO\\|FIXME\\|XXX' \"$file\"\n fi\n fi\ndone\n\necho \"LaTeX checks passed!\"\n```\n\nMake executable and add to pre-commit:\n\n```bash\nchmod +x scripts/latex-check.sh\n```\n\n```yaml\n- id: latex-custom-checks\n name: Custom LaTeX Checks\n entry: scripts/latex-check.sh\n language: script\n files: '\\.tex

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

\n```\n\n### Skip Hooks When Needed\n\n```bash\n# Skip all hooks for this commit\ngit commit --no-verify -m \"WIP: draft section\"\n\n# Run hooks manually\npre-commit run --all-files\n```\n\n---\n\n## 8. Troubleshooting CI/CD\n\n### Common CI Failures\n\n**Problem**: Missing LaTeX packages\n\n```\n! LaTeX Error: File `package.sty' not found.\n```\n\n**Solution**: Install package in workflow\n\n```yaml\n- name: Install additional packages\n run: tlmgr install package-name\n```\n\nOr use full TeX Live image: `texlive/texlive:latest`\n\n**Problem**: Bibliography not found\n\n```\nLaTeX Warning: Citation 'key' on page 1 undefined\n```\n\n**Solution**: Ensure bibliography files are committed\n\n```bash\ngit add bibliography.bib\ngit commit -m \"Add bibliography\"\n```\n\n**Problem**: Compilation timeout\n\n**Solution**: Increase timeout and use faster compiler\n\n```yaml\n- name: Compile document\n timeout-minutes: 10\n run: pdflatex -interaction=batchmode main.tex\n```\n\n### Debugging Workflows\n\n**Enable debug logging**:\n\n```yaml\n- name: Debug information\n run: |\n echo \"Working directory:\"\n pwd\n echo \"Files present:\"\n ls -la\n echo \"TeX distribution:\"\n pdflatex --version\n```\n\n**Upload logs on failure**:\n\n```yaml\n- name: Upload logs on failure\n if: failure()\n uses: actions/upload-artifact@v4\n with:\n name: error-logs\n path: |\n *.log\n *.blg\n *.aux\n```\n\n### Performance Optimization\n\n**Cache TeX Live installation**:\n\n```yaml\n- name: Cache TeX Live\n uses: actions/cache@v4\n with:\n path: /usr/local/texlive\n key: texlive-${{ runner.os }}-${{ hashFiles('**/*.tex') }}\n```\n\n**Conditional compilation** (only compile if .tex files changed):\n\n```yaml\non:\n push:\n paths:\n - '**.tex'\n - '**.bib'\n - '.github/workflows/**'\n```\n\n---\n\n## Conclusion\n\nThis guide covers the essential workflows for collaborative LaTeX development with modern CI/CD practices. Key takeaways:\n\n- **Version control**: Use semantic line breaks and modular structure\n- **Automation**: Set up GitHub Actions for every push\n- **Collaboration**: Use branches, PRs, and latexdiff for reviews\n- **Reliability**: Pre-commit hooks catch issues before CI\n\nWith these workflows, your LaTeX projects will be as maintainable as modern software projects.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":23144,"content_sha256":"177846eb612132bdb9d3e21977b838de98f585723272c04530ac2c579a7bab91"},{"filename":"references/debugging-guide.md","content":"# LaTeX Debugging & Error Resolution Guide\n\nA comprehensive guide to understanding, diagnosing, and fixing LaTeX compilation errors.\n\n## Table of Contents\n\n1. [Reading LaTeX Error Messages](#1-reading-latex-error-messages)\n2. [The 20 Most Common Errors](#2-the-20-most-common-errors-with-fixes)\n3. [Reading the .log File](#3-reading-the-log-file)\n4. [Debugging Strategies](#4-debugging-strategies)\n5. [Common Silent Failures](#5-common-silent-failures-no-error-wrong-output)\n6. [Package Conflicts & Resolution](#6-package-conflicts--resolution)\n7. [Quick Reference: Error → Solution Table](#7-quick-reference-error--solution-table)\n8. [Using compile_latex.sh Error Output](#8-using-compile_latexsh-error-output)\n\n---\n\n## 1. Reading LaTeX Error Messages\n\n### Error Message Anatomy\n\nLaTeX error messages follow a consistent structure. Understanding this structure is critical for quick debugging.\n\n```\n! LaTeX Error: Environment theorem undefined.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.42 \\begin{theorem}\n\n?\n```\n\n**The 3 Most Important Lines:**\n\n1. **Line 1** (starts with `!`): The error type and brief description\n - `! LaTeX Error:` = LaTeX-level error\n - `! Undefined control sequence` = TeX-level error\n - `! Package foo Error:` = Package-specific error\n\n2. **Line starting with `l.`**: The line number where LaTeX detected the error\n - `l.42` means line 42 in your source file\n - The actual mistake may be on a previous line (missing `}`, etc.)\n\n3. **The context lines**: Show what LaTeX was processing when it failed\n - Text before the line break is what LaTeX successfully processed\n - Text after shows what's left to process\n\n### Error vs Warning vs Emergency Stop\n\n**Error (`! Error`)**: Compilation stopped, must be fixed\n- LaTeX cannot continue\n- You get the `?` prompt (can type `x` to exit)\n- Produces no PDF, or PDF stops at error location\n\n**Warning (no `!`)**: Compilation continues, should investigate\n```\nLaTeX Warning: Reference `fig:missing' on page 1 undefined.\n```\n- PDF is produced but may have issues\n- Often indicates undefined references, bad citations, or overfull boxes\n\n**Emergency Stop**:\n```\n! ==> Fatal error occurred, no output PDF file produced!\n```\n- Unrecoverable error (often syntax or file system)\n- Usually preceded by other errors showing the root cause\n\n**Compilation Tip**: Always fix errors from **top to bottom**. One early error can cascade into dozens of false errors below it.\n\n---\n\n## 2. The 20 Most Common Errors (with fixes)\n\n### 1. `! Undefined control sequence`\n\n**Error text:**\n```\n! Undefined control sequence.\nl.15 \\theorem\n {Pythagorean Theorem}\n```\n\n**Cause**: Using a command that doesn't exist. Common reasons:\n- Typo in command name\n- Missing `\\usepackage{...}` to define the command\n- Using underscore `_` in text mode (should be `\\_`)\n\n**Fix:**\n```latex\n% Wrong:\n\\theorem{Pythagorean Theorem}\nThe file is named data_file.txt\n\n% Right:\n\\begin{theorem} % Or load a package that defines \\theorem\nPythagorean Theorem\n\\end{theorem}\n\nThe file is named data\\_file.txt % Escape underscores\n```\n\n### 2. `! Missing $ inserted`\n\n**Error text:**\n```\n! Missing $ inserted.\n\u003cinserted text>\n $\nl.23 The complexity is O(n^2\n ) for this algorithm.\n```\n\n**Cause**: Using math-mode commands (`^`, `_`, `\\alpha`, etc.) in text mode without `$... latex-document-skill — Skillopedia .\n\n**Fix:**\n```latex\n% Wrong:\nThe complexity is O(n^2) for this algorithm.\n\n% Right:\nThe complexity is $O(n^2)$ for this algorithm.\n\n% Also wrong:\n\\alpha is the learning rate\n\n% Right:\n$\\alpha$ is the learning rate\n```\n\n### 3. `! Missing \\begin{document}`\n\n**Error text:**\n```\n! LaTeX Error: Missing \\begin{document}.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\nl.6 S\n ome text before document begins\n```\n\n**Cause**: Text or commands that produce output before `\\begin{document}`.\n\n**Fix:**\n```latex\n% Wrong:\n\\documentclass{article}\n\\usepackage{graphicx}\nSome text here % This causes the error\n\n\\begin{document}\n...\n\n% Right:\n\\documentclass{article}\n\\usepackage{graphicx}\n% Only preamble commands allowed here\n\n\\begin{document}\nSome text here % Text goes after \\begin{document}\n```\n\n### 4. `! LaTeX Error: Environment X undefined`\n\n**Error text:**\n```\n! LaTeX Error: Environment algorithm undefined.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.45 \\begin{algorithm}\n```\n\n**Cause**: Using an environment without loading the package that defines it.\n\n**Fix:**\n```latex\n% Wrong:\n\\documentclass{article}\n\\begin{document}\n\\begin{algorithm} % Error: algorithm undefined\n...\n\\end{algorithm}\n\n% Right:\n\\documentclass{article}\n\\usepackage{algorithm} % Load the package\n\\usepackage{algpseudocode}\n\\begin{document}\n\\begin{algorithm}\n...\n\\end{algorithm}\n```\n\n**Common environment → package mappings:**\n- `algorithm` → `\\usepackage{algorithm}`\n- `lstlisting` → `\\usepackage{listings}`\n- `tikzpicture` → `\\usepackage{tikz}`\n- `align` → `\\usepackage{amsmath}`\n- `theorem` → `\\usepackage{amsthm}` (or define manually)\n\n### 5. `! Extra alignment tab character &`\n\n**Error text:**\n```\n! Extra alignment tab character &.\nl.12 a & b & c & d & e\n &\n```\n\n**Cause**: Using more `&` than columns defined in table/matrix preamble.\n\n**Fix:**\n```latex\n% Wrong:\n\\begin{tabular}{ccc} % Only 3 columns defined\na & b & c & d & e % But 5 columns used\n\\end{tabular}\n\n% Right:\n\\begin{tabular}{ccccc} % 5 columns defined\na & b & c & d & e % 5 columns used\n\\end{tabular}\n\n% Or for matrices:\n% Wrong:\n\\begin{bmatrix}\n1 & 2 & 3 & 4 % 4 columns\n\\end{bmatrix}\n\n% Right:\n\\begin{bmatrix}\n1 & 2 & 3 & 4 % Matrices infer column count from first row\n\\end{bmatrix}\n```\n\n### 6. `! Misplaced alignment tab character &`\n\n**Error text:**\n```\n! Misplaced alignment tab character &.\nl.8 In this equation, x &\n = 5\n```\n\n**Cause**: Using `&` outside a table, matrix, or alignment environment.\n\n**Fix:**\n```latex\n% Wrong:\nIn this equation, x & = 5\n\n% Right:\nIn this equation, $x = 5$\n\n% If you need alignment, use an alignment environment:\n\\begin{align}\nx &= 5 \\\\\ny &= 10\n\\end{align}\n```\n\n### 7. `! Missing number, treated as zero`\n\n**Error text:**\n```\n! Missing number, treated as zero.\n\u003cto be read again>\n \\vspace\nl.25 \\includegraphics[width=\\textwidth\n ]{image.pdf}\n```\n\n**Cause**: Incomplete or malformed dimension/number specification, often a typo or missing `=`.\n\n**Fix:**\n```latex\n% Wrong:\n\\includegraphics[width\\textwidth]{image.pdf} % Missing =\n\\vspace{3} % Missing unit\n\n% Right:\n\\includegraphics[width=\\textwidth]{image.pdf}\n\\vspace{3cm} % or 3pt, 3em, etc.\n\n% Wrong:\n\\parbox{5}{text}\n\n% Right:\n\\parbox{5cm}{text}\n```\n\n### 8. `! Illegal unit of measure`\n\n**Error text:**\n```\n! Illegal unit of measure (pt inserted).\n\u003cto be read again>\n }\nl.30 \\rule{3}{\n 0.4pt}\n```\n\n**Cause**: Length command missing a unit (pt, cm, mm, em, ex, etc.).\n\n**Fix:**\n```latex\n% Wrong:\n\\rule{3}{0.4pt} % First dimension missing unit\n\\hspace{10}\n\n% Right:\n\\rule{3cm}{0.4pt}\n\\hspace{10pt}\n\n% Valid units:\n% pt (point), cm, mm, in (inch), em (width of 'M'), ex (height of 'x')\n% Also: \\textwidth, \\linewidth, \\textheight, etc.\n```\n\n### 9. `! Too many }'s` or `! Too many {'s`\n\n**Error text:**\n```\n! Too many }'s.\nl.67 \\textbf{This is bold}}\n\n```\n\n**Cause**: Unbalanced braces – more closing `}` than opening `{`, or vice versa.\n\n**Fix:**\n```latex\n% Wrong:\n\\textbf{This is bold}} % Extra }\n\n% Right:\n\\textbf{This is bold}\n\n% Wrong:\n\\frac{x{y+1} % Missing }\n\n% Right:\n\\frac{x}{y+1}\n\n% Debugging tip: Use an editor with brace matching\n% Count { and } on the problem line and surrounding lines\n```\n\n**Finding unbalanced braces:**\n- Use editor's \"Go to matching bracket\" feature\n- Comment out sections to isolate the problem\n- Count: for every `{` there must be a matching `}`\n\n### 10. `! File X not found`\n\n**Error text:**\n```\n! LaTeX Error: File `image.png' not found.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.45 \\includegraphics{image.png}\n```\n\n**Cause**: Referenced file doesn't exist or path is incorrect.\n\n**Fix:**\n```latex\n% Check:\n% 1. File exists and name is spelled correctly (case-sensitive on Linux)\n% 2. File is in correct directory relative to .tex file\n% 3. File extension is correct\n\n% Wrong (if file is in images/ subdirectory):\n\\includegraphics{logo.pdf}\n\n% Right:\n\\includegraphics{images/logo.pdf}\n\n% Or use relative paths:\n\\graphicspath{{./images/}{./figures/}}\n\\includegraphics{logo.pdf} % Now searches in images/ and figures/\n\n% For \\input or \\include:\n% Wrong:\n\\input{chapter1} % If file is chapter1.tex\n\n% Right:\n\\input{chapter1.tex} % Specify extension for clarity\n```\n\n### 11. `! LaTeX Error: \\begin{X} on input line Y ended by \\end{Z}`\n\n**Error text:**\n```\n! LaTeX Error: \\begin{itemize} on input line 12 ended by \\end{enumerate}.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.15 \\end{enumerate}\n```\n\n**Cause**: Mismatched environment names or improper nesting.\n\n**Fix:**\n```latex\n% Wrong:\n\\begin{itemize}\n\\item First\n\\item Second\n\\end{enumerate} % Should be \\end{itemize}\n\n% Right:\n\\begin{itemize}\n\\item First\n\\item Second\n\\end{itemize}\n\n% Wrong (improper nesting):\n\\begin{equation}\n\\begin{itemize} % Can't put itemize inside equation\n\\item x = 5\n\\end{itemize}\n\\end{equation}\n\n% Right:\n\\begin{itemize}\n\\item $x = 5$\n\\end{itemize}\n```\n\n### 12. `! Package hyperref Error: Wrong DVI mode driver option`\n\n**Error text:**\n```\n! Package hyperref Error: Wrong DVI mode driver option `dvips',\n(hyperref) because pdfTeX is running in PDF mode.\n```\n\n**Cause**: Loading hyperref with driver options that conflict with compilation mode.\n\n**Fix:**\n```latex\n% Wrong (when using pdflatex):\n\\usepackage[dvips]{hyperref}\n\n% Right (let hyperref auto-detect):\n\\usepackage{hyperref}\n\n% If you must specify:\n\\usepackage[pdftex]{hyperref} % For pdflatex\n\\usepackage[xetex]{hyperref} % For xelatex\n\\usepackage[luatex]{hyperref} % For lualatex\n\n% Best practice: Never specify driver unless absolutely necessary\n\\usepackage{hyperref} % Auto-detects correctly\n```\n\n### 13. `! Overfull \\hbox`\n\n**Error text:**\n```\nOverfull \\hbox (15.23pt too wide) in paragraph at lines 34--36\n```\n\n**Cause**: Content exceeds the line width (margin). Not technically an error, but indicates formatting issues. Common with:\n- URLs or long unbreakable strings\n- Wide tables or figures\n- Code listings\n\n**Fix:**\n```latex\n% Wrong:\nThis is a very long URL: https://www.example.com/very/long/path/to/resource/file.pdf\n\n% Right:\n\\usepackage{hyperref}\n\\usepackage{url}\nThis is a very long URL: \\url{https://www.example.com/very/long/path/to/resource/file.pdf}\n\n% For tables:\n% Wrong:\n\\begin{tabular}{llllll}\nVery Long Column Header & Another Long Header & ...\n\\end{tabular}\n\n% Right:\n\\begin{tabular}{p{2cm}p{2cm}p{2cm}} % Fixed-width columns\n\\small % Smaller font\nVery Long Column Header & Another Long Header & ...\n\\end{tabular}\n\n% Or use tabularx:\n\\usepackage{tabularx}\n\\begin{tabularx}{\\textwidth}{XXX} % Auto-width columns\n...\n\\end{tabularx}\n\n% For code:\n\\usepackage{listings}\n\\lstset{breaklines=true} % Auto-wrap long lines\n```\n\n### 14. `! LaTeX Error: Option clash for package X`\n\n**Error text:**\n```\n! LaTeX Error: Option clash for package graphicx.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.5 \\usepackage[draft]{graphicx}\n```\n\n**Cause**: Package loaded twice with different options.\n\n**Fix:**\n```latex\n% Wrong:\n\\usepackage{graphicx}\n\\usepackage[draft]{graphicx} % Loaded again with different options\n\n% Right - Method 1: Use same options everywhere\n\\usepackage[draft]{graphicx}\n\n% Right - Method 2: Use \\PassOptionsToPackage before \\documentclass\n\\PassOptionsToPackage{draft}{graphicx}\n\\documentclass{article}\n\\usepackage{graphicx}\n\n% Right - Method 3: Load once with all options\n\\usepackage[draft,final]{graphicx} % Last option wins\n\n% Common with document classes that auto-load packages:\n% Wrong:\n\\documentclass{article} % Loads graphicx internally\n\\usepackage[draft]{graphicx} % Option clash\n\n% Right:\n\\PassOptionsToPackage{draft}{graphicx}\n\\documentclass{article}\n```\n\n### 15. `! Capacity exceeded, sorry`\n\n**Error text:**\n```\n! TeX capacity exceeded, sorry [input stack size=5000].\n```\n\n**Cause**: Infinite loop, recursive macro, or massive data structure (huge table, deeply nested lists).\n\n**Fix:**\n```latex\n% Common cause: recursive definition\n% Wrong:\n\\newcommand{\\foo}{\\foo bar} % Calls itself infinitely\n\n% Right:\n\\newcommand{\\foo}{bar}\n\n% For huge tables, split into multiple smaller tables or use longtable:\n\\usepackage{longtable}\n\\begin{longtable}{lll}\n% Very long table that spans multiple pages\n...\n\\end{longtable}\n\n% If the problem is legitimate (very complex document):\n% Increase capacity (in latexmk, pdflatex, etc.):\n% pdflatex -extra-mem-top=10000000 document.tex\n\n% Or add to document:\n% !TEX parameter = -extra-mem-top=10000000\n```\n\n### 16. `! Dimension too large`\n\n**Error text:**\n```\n! Dimension too large.\n\u003crecently read> \\pgf@x\n\nl.123 \\end{tikzpicture}\n```\n\n**Cause**: Coordinate or dimension exceeds TeX's maximum (~575cm or ~16383pt). Common in:\n- TikZ with huge coordinates\n- pgfplots with extreme data values\n- Image scaling with huge factors\n\n**Fix:**\n```latex\n% Wrong:\n\\begin{tikzpicture}\n\\draw (0,0) -- (100000,100000); % Coordinates too large\n\\end{tikzpicture}\n\n% Right - scale down:\n\\begin{tikzpicture}[scale=0.001]\n\\draw (0,0) -- (100000,100000);\n\\end{tikzpicture}\n\n% For pgfplots:\n\\begin{tikzpicture}\n\\begin{axis}[\n xmin=0, xmax=1e6,\n ymin=0, ymax=1e6,\n scaled ticks=true, % Use scientific notation\n tick label style={/pgf/number format/sci}\n]\n\\addplot coordinates {(0,0) (1e6,1e6)};\n\\end{axis}\n\\end{tikzpicture}\n\n% For images:\n% Wrong:\n\\includegraphics[width=100\\textwidth]{image.pdf} % 100x too large\n\n% Right:\n\\includegraphics[width=\\textwidth]{image.pdf}\n```\n\n### 17. `Runaway argument?`\n\n**Error text:**\n```\nRunaway argument?\n{This is the start of a caption but there's no closing brace\n! Paragraph ended before \\caption was complete.\n\u003cto be read again>\n \\par\nl.89\n```\n\n**Cause**: Missing closing brace `}` in command argument. LaTeX keeps reading, looking for the `}`, until it hits something incompatible (like `\\par` or end of file).\n\n**Fix:**\n```latex\n% Wrong:\n\\caption{This is a very long caption that explains the figure\nand continues for several lines but forgot the closing brace\n\n% Right:\n\\caption{This is a very long caption that explains the figure\nand continues for several lines with proper closing}\n\n% Wrong:\n\\section{Introduction % Missing }\n\n% Right:\n\\section{Introduction}\n\n% Debugging: Look at the line mentioned in the error and search UPWARD\n% for the command with the unclosed brace\n```\n\n### 18. `! LaTeX Error: Not in outer par mode`\n\n**Error text:**\n```\n! LaTeX Error: Not in outer par mode.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.56 \\begin{figure}\n```\n\n**Cause**: Trying to use a float (`figure`, `table`) inside another float or in a restricted environment (minipage, parbox, etc.).\n\n**Fix:**\n```latex\n% Wrong:\n\\begin{figure}\n \\begin{figure} % Can't nest figures\n \\includegraphics{inner.pdf}\n \\end{figure}\n \\caption{Outer figure}\n\\end{figure}\n\n% Right - use subfigures:\n\\usepackage{subcaption}\n\\begin{figure}\n \\begin{subfigure}{0.45\\textwidth}\n \\includegraphics[width=\\textwidth]{img1.pdf}\n \\caption{First image}\n \\end{subfigure}\n \\hfill\n \\begin{subfigure}{0.45\\textwidth}\n \\includegraphics[width=\\textwidth]{img2.pdf}\n \\caption{Second image}\n \\end{subfigure}\n \\caption{Combined figure}\n\\end{figure}\n\n% Wrong:\n\\parbox{5cm}{\n \\begin{table} % Can't use float in parbox\n ...\n \\end{table}\n}\n\n% Right - don't use float environment:\n\\parbox{5cm}{\n \\captionof{table}{My table} % Requires caption package\n \\begin{tabular}{ll}\n ...\n \\end{tabular}\n}\n```\n\n### 19. `! LaTeX Error: Unknown float option 'H'`\n\n**Error text:**\n```\n! LaTeX Error: Unknown float option `H'.\n\nSee the LaTeX manual or LaTeX Companion for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.23 \\begin{figure}[H]\n```\n\n**Cause**: Using `[H]` placement specifier without loading the `float` package.\n\n**Fix:**\n```latex\n% Wrong:\n\\documentclass{article}\n\\begin{document}\n\\begin{figure}[H] % H undefined\n\\includegraphics{img.pdf}\n\\end{figure}\n\n% Right:\n\\documentclass{article}\n\\usepackage{float} % Provides [H] option\n\\begin{document}\n\\begin{figure}[H] % \"Place HERE, not floating\"\n\\includegraphics{img.pdf}\n\\end{figure}\n\n% Note: Standard options (no package needed):\n% [h] = here if possible\n% [t] = top of page\n% [b] = bottom of page\n% [p] = separate page of floats\n% [!] = ignore internal float parameters\n% [H] = HERE (requires float package, NOT a float anymore)\n```\n\n### 20. `! Package inputenc Error: Unicode character X`\n\n**Error text:**\n```\n! Package inputenc Error: Unicode char \\u8:− not set up for use with LaTeX.\n\nSee the inputenc package documentation for explanation.\nType H \u003creturn> for immediate help.\n ...\n\nl.45 The result is x − y\n```\n\n**Cause**: Non-ASCII Unicode character in source that isn't handled by current encoding setup. Common with:\n- Copy-pasted text from PDFs/websites (em-dash, smart quotes, etc.)\n- Math symbols typed directly (−, ×, ≠, etc.)\n\n**Fix:**\n```latex\n% Method 1: Use XeLaTeX or LuaLaTeX (recommended for Unicode)\n% Compile with: xelatex document.tex\n\\documentclass{article}\n\\usepackage{fontspec} % For XeLaTeX/LuaLaTeX\n\\begin{document}\nThe result is x − y % Unicode minus works\n\\end{document}\n\n% Method 2: Replace Unicode with LaTeX commands (for pdflatex)\n% Wrong:\nThe result is x − y % Unicode minus\n\n% Right:\nThe result is x -- y % En-dash\nThe result is $x - y$ % Math minus\n\n% Common replacements:\n% \"smart quotes\" → ``smart quotes''\n% — (em-dash) → ---\n% – (en-dash) → --\n% … (ellipsis) → \\ldots\n% × → $\\times$\n% ÷ → $\\div$\n% ≠ → $\\neq$\n\n% Method 3: Configure inputenc for specific characters\n\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage{newunicodechar}\n\\newunicodechar{−}{\\text{-}} % Map Unicode minus to hyphen\n\\begin{document}\nThe result is x − y\n\\end{document}\n```\n\n---\n\n## 3. Reading the .log File\n\n### Where to Find It\n\nThe `.log` file is created in the same directory as your `.tex` file:\n- For `document.tex`, look for `document.log`\n- Contains complete compilation output\n- Not deleted on successful compilation (unlike `.aux`, `.out`, etc., in some setups)\n\n### Key Patterns to Search For\n\n**Search for errors:**\n```bash\ngrep \"^!\" document.log\n```\n\n**Lines starting with `!` indicate errors:**\n```\n! Undefined control sequence.\n! LaTeX Error: Environment 'theorem' undefined.\n! Package hyperref Error: Wrong DVI mode driver option\n```\n\n**Search for warnings:**\n```bash\ngrep -i \"warning\" document.log\n```\n\n**Common warnings:**\n```\nLaTeX Warning: Reference `eq:missing' on page 2 undefined.\nLaTeX Warning: There were undefined references.\nLaTeX Warning: Label `fig:duplicate' multiply defined.\nPackage hyperref Warning: Token not allowed in a PDF string\n```\n\n**Search for overfull/underfull boxes:**\n```bash\ngrep -E \"Overfull|Underfull\" document.log\n```\n\n```\nOverfull \\hbox (15.23pt too wide) in paragraph at lines 34--36\nUnderfull \\hbox (badness 10000) in paragraph at lines 67--68\n```\n\n### Understanding Pass-by-Pass Output\n\nLaTeX often compiles in multiple passes. The log shows each pass:\n\n```\n**First pass:**\n...\nLaTeX Warning: Reference `sec:intro' on page 1 undefined on input line 23.\n...\n\n**Second pass:**\n...\nLaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.\n```\n\n**Why multiple passes?**\n- Pass 1: LaTeX doesn't know page numbers yet, so all `\\ref` are `??`\n- Pass 2: Uses `.aux` file from Pass 1 to resolve references\n- Pass 3 (if needed): Resolves any changes from Pass 2\n\n**Automation**: Use `latexmk` to automatically run enough passes:\n```bash\nlatexmk -pdf document.tex\n```\n\n### Using grep for Quick Debugging\n\n```bash\n# Find all errors:\ngrep -n \"^!\" document.log\n\n# Find specific error type:\ngrep -n \"Undefined control sequence\" document.log\n\n# Find all warnings and errors:\ngrep -n -E \"^!|Warning\" document.log\n\n# Find overfull boxes with context:\ngrep -n -A 2 \"Overfull\" document.log\n\n# Find which packages were loaded:\ngrep \"Package:\" document.log | head -20\n\n# Find file list (helpful for debugging missing packages):\ngrep -A 100 \"\\\\*File List\\\\*\" document.log\n```\n\n### Log File Structure\n\nTypical sections in order:\n\n1. **Header**: LaTeX version, format\n2. **File loading**: Document class, packages\n3. **Compilation**: Main document processing\n - Page numbers shown as `[1] [2] [3]`\n - Warnings/errors interspersed\n4. **File list**: `\\listfiles` output (if enabled)\n5. **Summary**: Page count, warnings count\n\n**Example useful section (file list):**\n```\n *File List*\n article.cls 2021/10/04 v1.4n Standard LaTeX document class\n size10.clo 2021/10/04 v1.4n Standard LaTeX file (size option)\ngraphicx.sty 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)\n amsmath.sty 2021/10/15 v2.17l AMS math features\n ***********\n```\n\nUse `\\listfiles` in preamble to ensure this section is generated.\n\n---\n\n## 4. Debugging Strategies\n\n### Binary Search: Comment Out Half\n\nWhen you have a large document with an error but can't locate it:\n\n```latex\n% 1. Start with the full document:\n\\begin{document}\nSection 1 content...\nSection 2 content...\nSection 3 content...\nSection 4 content...\nSection 5 content...\nSection 6 content...\n\\end{document}\n\n% 2. Comment out the second half:\n\\begin{document}\nSection 1 content...\nSection 2 content...\nSection 3 content...\n% Section 4 content...\n% Section 5 content...\n% Section 6 content...\n\\end{document}\n\n% 3. Compile:\n% - If error persists: error is in first half (Sections 1-3)\n% - If error gone: error is in second half (Sections 4-6)\n\n% 4. Repeat: comment out half of the problematic half\n% Continue until you isolate the exact problematic line\n```\n\n**Pro tip**: Use `\\include{chapter1}` for chapters, then comment out entire chapters quickly:\n```latex\n% \\include{chapter1} % Error not here\n% \\include{chapter2} % Error not here\n\\include{chapter3} % Error is here!\n% \\include{chapter4}\n```\n\n### Using `\\listfiles`\n\nAdd to preamble to log all loaded files and versions:\n\n```latex\n\\listfiles\n\\documentclass{article}\n\\usepackage{amsmath}\n...\n```\n\n**Output in .log file:**\n```\n *File List*\n article.cls 2021/10/04 v1.4n Standard LaTeX document class\n amsmath.sty 2021/10/15 v2.17l AMS math features\n```\n\n**Use this to:**\n- Verify correct package versions\n- Check if a package is actually loaded\n- Debug \"works on my machine\" issues (version differences)\n\n### Minimal Working Example (MWE) Technique\n\nReduce your document to the smallest possible example that reproduces the error:\n\n```latex\n% Start with this template:\n\\documentclass{article}\n\\usepackage{amsmath} % Only packages needed for error\n\\begin{document}\n\n% Minimal content that shows the error\n$\nx = \\frac{1}{0} % If this causes error\n$\n\n\\end{document}\n```\n\n**Why create an MWE?**\n- Eliminates irrelevant code that might be confusing\n- Makes it clear which package causes the issue\n- Easier to get help on Stack Exchange (MWEs are required)\n- Forces you to understand the problem\n\n**How to create MWE:**\n1. Copy your document to `mwe.tex`\n2. Delete everything not related to error\n3. Remove unnecessary packages one by one\n4. Compile after each change\n5. Stop when it's as small as possible but still shows error\n\n### Using Tracing Commands\n\nLaTeX provides debugging output commands:\n\n```latex\n% Show every macro expansion (VERY verbose):\n\\tracingmacros=1\n\\badcommand{test}\n\\tracingmacros=0 % Turn off after problematic section\n\n% Show command execution:\n\\tracingcommands=1\n...\n\\tracingcommands=0\n\n% Show online activity (paragraph building, page breaking):\n\\tracingonline=1\n```\n\n**Output appears in .log file**. Warning: Creates massive output. Only use on small sections:\n\n```latex\n\\documentclass{article}\n\\begin{document}\n\nNormal content here...\n\n% Isolate problematic section:\n\\tracingmacros=1\nThis section has an error somewhere...\n\\tracingmacros=0\n\nMore normal content...\n\\end{document}\n```\n\n### Using `draft` Mode for Faster Compilation\n\nSpeed up compilation while debugging:\n\n```latex\n\\documentclass[draft]{article} % Draft mode\n```\n\n**Draft mode effects:**\n- Images shown as boxes (not loaded)\n- Overfull boxes marked with black rectangle\n- Some packages disable features (faster compilation)\n\n**When to use:**\n- Debugging text/structure (don't need images)\n- Working on large documents with many figures\n- Checking overfull/underfull boxes (easier to see)\n\n**Switch to final for submission:**\n```latex\n\\documentclass[final]{article} % Or just omit [draft]\n```\n\n### Interactive Debugging at the `?` Prompt\n\nWhen compilation stops with `?`, you can type commands:\n\n```\n! Undefined control sequence.\nl.42 \\badcommand\n\n?\n```\n\n**Useful responses:**\n- `h` - Help (explains error)\n- `x` - Exit (quit compilation immediately)\n- `q` - Quiet mode (continue but suppress errors)\n- `r` - Run without stopping (continue despite errors)\n- `i` - Insert (type replacement text)\n- `e` - Edit (some systems open editor at error line)\n\n**Example:**\n```\n? i\ninsert> \\newcommand % Type correction\n? x % Then exit to fix in source file\n```\n\n**In practice**: Most users type `x` immediately and fix the source file.\n\n### Using Editor Integration\n\nModern editors show errors inline:\n\n**VS Code** (with LaTeX Workshop):\n- Errors appear as red squiggles\n- Hover for error message\n- Click to jump to line in .log\n\n**Vim** (with vimtex):\n- `:VimtexErrors` to open quickfix window\n- Jump between errors with `:cn` / `:cp`\n\n**Emacs** (with AUCTeX):\n- `C-c `` to jump to next error\n- Error descriptions shown in minibuffer\n\n**Configure your editor** for LaTeX to save significant debugging time.\n\n---\n\n## 5. Common Silent Failures (No Error, Wrong Output)\n\n### Angle Brackets Showing as Inverted Question Marks\n\n**Symptom:**\n```\nYou write: \u003cHTML>\nYou see in PDF: ¡HTML¿\n```\n\n**Cause**: Default font encoding (OT1) doesn't include `\u003c` and `>`.\n\n**Fix:**\n```latex\n% Add to preamble:\n\\usepackage[T1]{fontenc}\n\n% Now \u003c and > work correctly:\n\\begin{document}\nThe HTML tag \u003cdiv> is used for divisions.\n\\end{document}\n```\n\n**Why**: OT1 encoding is optimized for English and lacks many characters. T1 encoding includes full Western character set.\n\n### Missing Bibliography Entries (But No Error)\n\n**Symptom:**\n```latex\n\\cite{Smith2020} % Shows as [?] in PDF, no error\n```\n\n**Cause**: Bibliography entry not in `.bib` file, or BibTeX not run.\n\n**Fix:**\n\n```latex\n% 1. Verify entry exists in references.bib:\n@article{Smith2020,\n author = {Smith, John},\n title = {Great Paper},\n year = {2020}\n}\n\n% 2. Ensure compilation sequence:\npdflatex document.tex % First pass\nbibtex document % Process bibliography\npdflatex document.tex # Resolve citations\npdflatex document.tex # Resolve references\n\n% Or use latexmk:\nlatexmk -pdf document.tex # Does everything automatically\n\n% 3. Check .bib file is referenced:\n\\bibliography{references} % For BibTeX\n% OR\n\\addbibresource{references.bib} % For BibLaTeX\n```\n\n**Check .blg file** for BibTeX warnings:\n```bash\ncat document.blg\n```\n\nLook for:\n```\nWarning--I didn't find a database entry for \"Smith2020\"\n```\n\n### Figures Appearing in Wrong Position\n\n**Symptom**: Figure appears on page 5 when you defined it on page 2.\n\n**Cause**: This is intentional! LaTeX floats figures to optimal positions.\n\n**Fix (if you really want to force position):**\n\n```latex\n% Option 1: Use [h] to prefer \"here\"\n\\begin{figure}[h]\n\\includegraphics{img.pdf}\n\\caption{My image}\n\\end{figure}\n\n% Option 2: Use [H] to force \"HERE\" (requires float package)\n\\usepackage{float}\n\\begin{figure}[H] % \"HERE, not floating\"\n\\includegraphics{img.pdf}\n\\caption{My image}\n\\end{figure}\n\n% Option 3: Increase float placement tolerance\n\\renewcommand{\\topfraction}{0.85} % Allow up to 85% of page for top floats\n\\renewcommand{\\textfraction}{0.1} % Require only 10% text per page\n\n% Option 4: Use \\FloatBarrier to prevent floats crossing points\n\\usepackage{placeins}\n\\section{Introduction}\nContent with figures...\n\\FloatBarrier % Flush all pending floats before next section\n\\section{Methods}\n```\n\n**Best practice**: Let LaTeX position floats, and use `\\ref{fig:label}` to refer to them by number, not position.\n\n### Package Silently Overriding Another Package\n\n**Symptom**: You load two packages that define the same command, and one silently wins.\n\n**Example:**\n```latex\n\\usepackage{algorithm}\n\\usepackage{algorithm2e} % Redefines 'algorithm' environment\n```\n\n**How to detect:**\n\n```bash\n# Check log for \"redefined\" warnings:\ngrep -i \"redefined\" document.log\n```\n\n**Fix**: Only load compatible packages, or load in correct order:\n\n```latex\n% Check documentation for compatibility\n% Usually mentioned in package docs\n\n% If both needed, sometimes renaming works:\n\\usepackage{algorithm2e}\n\\renewcommand{\\algorithm}{algorithmtwo} % Rename to avoid clash\n```\n\n### Font Substitution Warnings\n\n**Symptom**: Log file shows:\n```\nLaTeX Font Warning: Font shape `OT1/cmr/m/n' in size \u003c142.26378> not available\n(Font) size \u003c24.88> substituted on input line 10.\n```\n\n**Cause**: Requesting font size that doesn't exist; LaTeX substitutes closest available size.\n\n**Fix:**\n\n```latex\n% For vector fonts (Type1, TrueType), this is usually fine\n% But for bitmap fonts, can look pixelated\n\n% Option 1: Use scalable fonts\n\\usepackage{lmodern} % Latin Modern (scalable version of Computer Modern)\n\n% Option 2: Use different font package\n\\usepackage{times} % Times Roman\n\\usepackage{helvet} % Helvetica\n\\usepackage{mathptmx} % Times with math support\n\n% Option 3: Ignore if output looks fine\n% Substitution warnings are usually harmless\n```\n\n---\n\n## 6. Package Conflicts & Resolution\n\n### Common Conflicting Pairs\n\n| Package 1 | Package 2 | Issue | Solution |\n|-----------|-----------|-------|----------|\n| `hyperref` | Most packages | `hyperref` redefines many internals | Load `hyperref` **last** |\n| `amsmath` | `empheq` | `empheq` extends `amsmath` | Load `empheq` after `amsmath` |\n| `graphicx` | `color` | Both provide color support | Use only `graphicx` (includes color) |\n| `algorithm` | `algorithm2e` | Both define `algorithm` environment | Use only one |\n| `enumerate` | `enumitem` | Both customize lists | Use only `enumitem` (more powerful) |\n| `caption` | Document classes (KOMA, memoir) | Class has own caption style | Load `caption` with `compatibility` option |\n| `subfigure` | `subfig` | Both provide subfigures | Use only `subfig` or `subcaption` (newer) |\n| `natbib` | `biblatex` | Different bibliography systems | Use only one |\n\n### Load Order Matters\n\n**General rule**: Specific → General → Hyperref\n\n```latex\n% GOOD LOAD ORDER:\n\\documentclass{article}\n\n% 1. Font and encoding\n\\usepackage[T1]{fontenc}\n\\usepackage[utf8]{inputenc}\n\\usepackage{lmodern}\n\n% 2. Math packages (order matters)\n\\usepackage{amsmath} % First\n\\usepackage{amssymb} % After amsmath\n\\usepackage{amsthm} % After amsmath\n\n% 3. Graphics\n\\usepackage{graphicx}\n\\usepackage{tikz}\n\n% 4. Tables\n\\usepackage{booktabs}\n\\usepackage{array}\n\n% 5. Bibliography (if using natbib)\n\\usepackage{natbib}\n\n% 6. Floats and captions\n\\usepackage{float}\n\\usepackage{caption}\n\\usepackage{subcaption}\n\n% 7. Other packages\n\\usepackage{algorithm}\n\\usepackage{listings}\n\n% 8. hyperref (usually LAST)\n\\usepackage{hyperref}\n\n% 9. Packages that must come after hyperref\n\\usepackage{cleveref} % Must be after hyperref\n```\n\n**Why hyperref last?**\n- `hyperref` redefines many commands to add hyperlink support\n- If loaded early, later packages might break hyperlinks\n- Exception: `cleveref` and a few others must come **after** hyperref\n\n### Using `\\PassOptionsToPackage`\n\n**Problem**: Document class loads package, but you need different options.\n\n**Wrong approach:**\n```latex\n\\documentclass{article} % Loads graphicx internally\n\\usepackage[draft]{graphicx} % ERROR: Option clash\n```\n\n**Correct approach:**\n```latex\n\\PassOptionsToPackage{draft}{graphicx}\n\\documentclass{article}\n% Now graphicx is loaded with draft option\n```\n\n**How it works**: `\\PassOptionsToPackage` must come **before** package is loaded (even by document class).\n\n**Multiple options:**\n```latex\n\\PassOptionsToPackage{pdftex,draft}{graphicx}\n\\PassOptionsToPackage{colorlinks,linkcolor=blue}{hyperref}\n\\documentclass{article}\n```\n\n### Checking Which Packages Conflict\n\n**Method 1: Read documentation**\n- Most package docs list incompatibilities\n- Search for \"conflicts\" or \"compatibility\"\n\n**Method 2: Load incrementally**\n```latex\n\\documentclass{article}\n\\usepackage{packageA}\n% \\usepackage{packageB} % Comment out\n% \\usepackage{packageC}\n\\begin{document}\nTest\n\\end{document}\n\n% Compile. If works, uncomment packageB and recompile.\n% Continue until you find the conflicting pair.\n```\n\n**Method 3: Check for redefinition warnings**\n```bash\ngrep -i \"redefin\" document.log\n```\n\n**Output:**\n```\nLaTeX Warning: Command \\algorithm already defined.\n```\n\nThis tells you which packages are fighting over the same command.\n\n### Resolving Option Clashes\n\n**Scenario**: Two packages need same package with different options.\n\n**Example:**\n```latex\n\\usepackage[option1]{foo}\n% ...later in preamble, another package does:\n% \\RequirePackage[option2]{foo} % Would cause option clash\n```\n\n**Solution 1**: Load with both options (if compatible):\n```latex\n\\usepackage[option1,option2]{foo}\n```\n\n**Solution 2**: Check if options are compatible:\n```latex\n% Some options override each other:\n\\usepackage[draft,final]{foo} % final wins (loaded last)\n```\n\n**Solution 3**: Use `\\PassOptionsToPackage`:\n```latex\n\\PassOptionsToPackage{option1,option2}{foo}\n\\documentclass{article} % Or wherever foo gets loaded\n```\n\n**Solution 4**: Don't load package explicitly if class loads it:\n```latex\n% Check if document class already loads the package\n% If so, use \\PassOptionsToPackage BEFORE \\documentclass\n```\n\n---\n\n## 7. Quick Reference: Error → Solution Table\n\n| Error Message | Likely Cause | Quick Fix |\n|---------------|--------------|-----------|\n| `Undefined control sequence` | Typo or missing package | Check spelling; add `\\usepackage{...}` |\n| `Missing $ inserted` | Math command in text mode | Wrap with `$... latex-document-skill — Skillopedia |\n| `Missing \\begin{document}` | Text before `\\begin{document}` | Move content after `\\begin{document}` |\n| `Environment X undefined` | Missing package for environment | Add `\\usepackage{...}` |\n| `Extra alignment tab character &` | Too many `&` in table | Match columns: `{ccc}` for 3 columns |\n| `Misplaced alignment tab character &` | `&` outside table/align | Use `&` only in tabular/align environments |\n| `Missing number, treated as zero` | Incomplete dimension | Add unit: `3cm` not `3` |\n| `Illegal unit of measure` | Missing unit | Use `pt`, `cm`, `em`, etc. |\n| `Too many }'s` | Unbalanced braces | Count braces; match `{` with `}` |\n| `File X not found` | Missing file or wrong path | Check filename, path, extension |\n| `\\begin{X} ended by \\end{Y}` | Mismatched environments | Match begin/end names |\n| `Wrong DVI mode driver option` | Wrong hyperref driver | Remove driver option; let hyperref auto-detect |\n| `Overfull \\hbox` | Text exceeds margin | Use `\\url{...}`; scale tables; use `breaklines` |\n| `Option clash for package X` | Package loaded twice with different options | Use `\\PassOptionsToPackage` |\n| `Capacity exceeded` | Infinite loop or huge structure | Check for recursive macros; split large tables |\n| `Dimension too large` | Coordinate/value exceeds TeX max | Scale down coordinates; use scientific notation |\n| `Runaway argument?` | Missing closing `}` | Find unclosed brace in command |\n| `Not in outer par mode` | Float inside float | Use subfigure; don't nest floats |\n| `Unknown float option 'H'` | Missing float package | Add `\\usepackage{float}` |\n| `Unicode character X` | Non-ASCII character | Use XeLaTeX/LuaLaTeX, or replace with LaTeX command |\n| `Undefined reference` | Missing label or need recompile | Run pdflatex again; check `\\label{...}` |\n| `Citation X undefined` | Missing .bib entry or need bibtex | Run bibtex; check .bib file |\n| `There were multiply-defined labels` | Duplicate `\\label{...}` | Use unique label names |\n| `Command X already defined` | Redefining existing command | Use `\\renewcommand` instead of `\\newcommand` |\n\n---\n\n## 8. Tool-Assisted Debugging\n\n### Using compile_latex.sh Error Output\n\nThe `compile_latex.sh` script parses the `.log` file and presents errors in a more readable format:\n\n**Script behavior:**\n1. Runs `pdflatex` (or `xelatex`, `lualatex`)\n2. Parses `.log` file for lines starting with `!`\n3. Extracts line numbers (lines starting with `l.`)\n4. Groups errors by type\n5. Provides suggestions based on error patterns\n\n**Example output:**\n```bash\n$ ./compile_latex.sh document.tex\n\nCompiling document.tex...\nError on line 42: Undefined control sequence\n \\theorem\nSuggestion: Did you mean \\begin{theorem}? Or missing package?\n\nError on line 67: Missing $ inserted\nSuggestion: Math command used outside math mode. Wrap with $...$\n\nCompilation failed with 2 errors.\n```\n\n### Understanding Its Suggestions\n\nThe script recognizes common error patterns and provides hints:\n\n| Error Pattern | Suggestion |\n|---------------|------------|\n| `Undefined control sequence: \\theorem` | Check if you meant `\\begin{theorem}` or need `\\usepackage{amsthm}` |\n| `Missing $ inserted` | Math command used in text mode; wrap with `$... latex-document-skill — Skillopedia |\n| `Environment X undefined` | Add `\\usepackage{...}` – check documentation for package name |\n| `File X.pdf not found` | Check if file exists and path is correct |\n| `Option clash` | Use `\\PassOptionsToPackage{...}{...}` before `\\documentclass` |\n| `Package hyperref Error` | Move `\\usepackage{hyperref}` to near end of preamble |\n| `Overfull \\hbox` | Consider using `\\usepackage{url}` or scaling content |\n\n**Suggestions are heuristics**, not guaranteed fixes. Always verify the suggestion makes sense for your specific case.\n\n### When to Use `--auto-fix`\n\nSome scripts provide an `--auto-fix` flag that attempts automatic corrections:\n\n```bash\n./compile_latex.sh --auto-fix document.tex\n```\n\n**What auto-fix might do:**\n- Add missing packages to preamble\n- Escape underscores `_` to `\\_`\n- Add missing ` latex-document-skill — Skillopedia around detected math commands\n- Fix common brace imbalances\n\n**When to use it:**\n- For known simple errors (missing packages, unescaped underscores)\n- When working with auto-generated LaTeX (from scripts/tools)\n- For quick prototyping (then review changes)\n\n**When NOT to use it:**\n- On important documents (always review changes)\n- For complex structural errors (nested environments, etc.)\n- When you don't understand the error (auto-fix might mask the real issue)\n\n**Best practice:**\n```bash\n# Make backup first\ncp document.tex document.tex.backup\n\n# Run auto-fix\n./compile_latex.sh --auto-fix document.tex\n\n# Review changes\ndiff document.tex.backup document.tex\n\n# Compile and test\npdflatex document.tex\n```\n\n### Interpreting Error Location\n\nThe script shows line numbers, but remember:\n\n**Line number is where LaTeX detected the error, not necessarily where you made the mistake.**\n\n```latex\n% Line 10: Missing {\n\\textbf Text that should be bold}\n\n% Line 30: LaTeX reports error here\n\\section{Next Section}\n! Too many }'s.\nl.30 \\section{Next Section}\n```\n\n**The actual error is on line 10**, but LaTeX doesn't detect it until line 30.\n\n**Debugging tip**: When script reports error on line N, check:\n1. Line N itself\n2. Lines N-1, N-2, ... (look backwards)\n3. For brace/environment errors, search upward for unclosed `{` or `\\begin{...}`\n\n### Using lacheck - Syntax Checker\n\n**lacheck** is a simple syntax checker that catches common LaTeX errors before compilation.\n\n**Installation:**\n```bash\n# Usually included with TeX distributions\n# Standalone installation:\napt-get install lacheck # Debian/Ubuntu\nbrew install lacheck # macOS\n```\n\n**Basic usage:**\n```bash\nlacheck document.tex\n```\n\n**Example output:**\n```\n\"document.tex\", line 15: possible unwanted space at \"{\"\n\"document.tex\", line 23: double space at \" ~\"\n\"document.tex\", line 42: missing `\\begin{document}'\n\"document.tex\", line 67: `{' expected, found `}'\n```\n\n**What lacheck detects:**\n- Unmatched braces `{}`\n- Misplaced spaces around punctuation\n- Common command typos\n- Missing `\\begin{document}`\n- Doubled spaces before tie `~`\n- Unescaped special characters\n\n**Limitations:**\n- Only checks syntax, not semantics\n- Many false positives (especially with complex macros)\n- Doesn't understand custom commands\n- Can't check package-specific syntax\n\n**Best practices:**\n```bash\n# Run lacheck before compiling\nlacheck document.tex && pdflatex document.tex\n\n# Ignore false positives by piping through grep\nlacheck document.tex | grep -v \"unwanted space\"\n\n# Check all .tex files in project\nfind . -name \"*.tex\" -exec lacheck {} \\;\n```\n\n**Common false positives:**\n```latex\n% lacheck warns: \"possible unwanted space at '{'\"\n\\textbf {text} % lacheck flags this, but it's harmless\n\n% lacheck warns: \"double space at ' ~'\"\nWord ~\\cite{ref} % This is correct, ignore warning\n```\n\n### Using ChkTeX - Comprehensive Linter\n\n**ChkTeX** is a more sophisticated LaTeX linter that provides style and semantic checking.\n\n**Installation:**\n```bash\napt-get install chktex # Debian/Ubuntu\nbrew install chktex # macOS\n# Or included in TeX Live full installation\n```\n\n**Basic usage:**\n```bash\nchktex document.tex\n```\n\n**Example output:**\n```\nWarning 1 in document.tex line 15: Command terminated with space.\n \\LaTeX is great\n ^\n\nWarning 8 in document.tex line 23: Wrong length of dash may have been used.\n pages 1-10\n ^\n\nWarning 13 in document.tex line 34: Interword spacing should perhaps be used.\n e.g.this\n ^\n\nWarning 24 in document.tex line 45: Delete this space to maintain correct pagereferences.\n Figure ~\\ref{fig:example}\n ^\n```\n\n**ChkTeX warning categories:**\n\n| Warning | Description | Example |\n|---------|-------------|---------|\n| 1 | Command terminated with space | `\\LaTeX is` → `\\LaTeX{} is` |\n| 2 | Non-breaking space before citation/ref | `ref~\\cite{x}` |\n| 8 | Wrong dash length | `1-10` → `1--10` (en-dash) |\n| 11 | Comment text with actual percent | `% 50%` → `% 50\\%` |\n| 13 | Interword spacing issue | `e.g.this` → `e.g.\\ this` |\n| 17 | Number followed by word | `3times` → `3 times` |\n| 24 | Space before tilde | `fig ~\\ref` → `fig~\\ref` |\n| 26 | Space before punctuation | `text .` → `text.` |\n| 36 | Space before superscript/subscript | `x ^2` → `x^2` |\n\n**Configuration with .chktexrc:**\n\nCreate `~/.chktexrc` to customize behavior:\n\n```bash\n# Suppress specific warnings globally\nCmdLine\n{\n -n 1 # Ignore \"command terminated with space\"\n -n 8 # Ignore \"wrong dash length\"\n}\n\n# Set quiet mode\nQuietMode { True }\n\n# Add custom abbreviations (to avoid Warning 13)\nAbbrev\n{\n etc. fig. vs. e.g. i.e. cf. et al.\n}\n\n# User-defined patterns to ignore\nUserWarn\n{\n # Custom rules can be added here\n}\n\n# Verbosity level (0-4)\nVerbosityLevel { 2 }\n```\n\n**Suppress warnings inline:**\n\n```latex\n% chktex-file 1 8\n% ^ Suppress warnings 1 and 8 for entire file\n\n\\LaTeX is great % chktex 1\n% ^ Suppress warning 1 for this line only\n\n% chktex-begin\n\\LaTeX is great\nMany lines here\n% chktex-end\n% ^ Suppress all warnings for this block\n```\n\n**Advanced usage:**\n\n```bash\n# Suppress specific warnings from command line\nchktex -n 1 -n 2 document.tex\n\n# Machine-readable output (for IDE integration)\nchktex -v0 -q document.tex\n\n# Output format: filename:line:column:error\nchktex -v0 -q -f \"%f:%l:%c:%n:%k:%m\\n\" document.tex\n\n# Check all .tex files recursively\nfind . -name \"*.tex\" -print0 | xargs -0 chktex\n\n# Show only errors (level 3), suppress warnings\nchktex -l3 document.tex\n\n# Detailed statistics\nchktex -s document.tex\n```\n\n**Integration with editors:**\n\n**VS Code (LaTeX Workshop):**\n```json\n{\n \"latex-workshop.linting.chktex.enabled\": true,\n \"latex-workshop.linting.chktex.exec.args\": [\n \"-n\", \"1\", \"-n\", \"8\", // Suppress warnings 1 and 8\n \"-wall\",\n \"-I0\",\n \"-f%f:%l:%c:%d:%k:%m\\n\"\n ]\n}\n```\n\n**Vim (with syntastic or ALE):**\n```vim\n\" In ~/.vimrc\nlet g:syntastic_tex_checkers = ['chktex']\nlet g:syntastic_tex_chktex_args = '-n 1 -n 8'\n```\n\n**Emacs (with AUCTeX):**\n```elisp\n;; In ~/.emacs\n(setq LaTeX-command-style '((\"\" \"%(PDF)%(latex) -file-line-error %S%(PDFout)\")))\n(add-hook 'LaTeX-mode-hook 'flycheck-mode)\n```\n\n### Combining Tools for Maximum Coverage\n\n**Recommended debugging workflow:**\n\n```bash\n#!/bin/bash\n# check_latex.sh - Comprehensive LaTeX checking script\n\nTEX_FILE=\"$1\"\n\necho \"=== Step 1: Syntax check with lacheck ===\"\nlacheck \"$TEX_FILE\" 2>&1 | grep -v \"unwanted space\" || true\n\necho -e \"\\n=== Step 2: Style check with ChkTeX ===\"\nchktex -n 1 -n 24 \"$TEX_FILE\" 2>&1 || true\n\necho -e \"\\n=== Step 3: Compilation test ===\"\npdflatex -interaction=nonstopmode \"$TEX_FILE\" > /dev/null\n\necho -e \"\\n=== Step 4: Check compilation errors ===\"\ngrep \"^!\" \"${TEX_FILE%.tex}.log\" || echo \"No errors found\"\n\necho -e \"\\n=== Step 5: Check warnings ===\"\ngrep -i \"warning\" \"${TEX_FILE%.tex}.log\" | head -10 || echo \"No warnings found\"\n\necho -e \"\\n=== Step 6: Check overfull boxes ===\"\ngrep \"Overfull\" \"${TEX_FILE%.tex}.log\" || echo \"No overfull boxes\"\n\necho -e \"\\n=== Step 7: Summary ===\"\nERROR_COUNT=$(grep -c \"^!\" \"${TEX_FILE%.tex}.log\" 2>/dev/null || echo \"0\")\nWARN_COUNT=$(grep -c -i \"warning\" \"${TEX_FILE%.tex}.log\" 2>/dev/null || echo \"0\")\necho \"Errors: $ERROR_COUNT | Warnings: $WARN_COUNT\"\n\nif [ \"$ERROR_COUNT\" -eq 0 ]; then\n echo \"✓ Document compiled successfully!\"\n exit 0\nelse\n echo \"✗ Document has compilation errors\"\n exit 1\nfi\n```\n\n**Make it executable and use:**\n```bash\nchmod +x check_latex.sh\n./check_latex.sh document.tex\n```\n\n### IDE Integration for Real-Time Debugging\n\n**VS Code with LaTeX Workshop:**\n\nProvides real-time error detection and inline annotations.\n\n**Features:**\n- Error highlighting in editor\n- Clickable error messages\n- Jump-to-error from Problems panel\n- Integrated PDF viewer with SyncTeX\n\n**Setup:**\n```json\n{\n \"latex-workshop.latex.autoBuild.run\": \"onSave\",\n \"latex-workshop.view.pdf.viewer\": \"tab\",\n \"latex-workshop.latex.clean.enabled\": true,\n \"latex-workshop.linting.chktex.enabled\": true\n}\n```\n\n**Overleaf:**\n\nCloud-based LaTeX editor with built-in error detection.\n\n**Features:**\n- Real-time compilation\n- Error panel with file/line context\n- Click error to jump to source\n- Collaborative debugging\n- Version history for reverting mistakes\n\n**TeXstudio:**\n\nDesktop LaTeX IDE with advanced debugging features.\n\n**Features:**\n- Integrated error panel\n- Syntax highlighting with error detection\n- Structure validation\n- Brace matching\n- Auto-completion reduces errors\n\n**Configure TeXstudio:**\n1. Options → Configure TeXstudio\n2. Build → Default Compiler → PdfLaTeX\n3. Advanced Editor → Enable \"Check Spelling\" and \"Syntax Check\"\n\n### Getting More Details\n\nIf script's summary isn't enough:\n\n```bash\n# View full log file\nless document.log\n\n# Search for errors\ngrep \"^!\" document.log\n\n# Get error with context\ngrep -A 5 \"^!\" document.log\n\n# Check warnings too\ngrep -i \"warning\" document.log\n```\n\nMost scripts also support verbose mode:\n```bash\n./compile_latex.sh --verbose document.tex\n# Shows full pdflatex output, not just summary\n```\n\n---\n\n## Final Tips\n\n1. **Fix errors from top to bottom** – Early errors cascade into fake errors later\n2. **Read the first line of the error message** – It usually tells you exactly what's wrong\n3. **Check line numbers, but look upward too** – Missing braces detected late\n4. **Use an editor with LaTeX support** – Syntax highlighting catches many errors before compilation\n5. **Compile frequently** – Easier to find error when you've only changed a few lines\n6. **Keep a minimal preamble** – Fewer packages = fewer conflicts\n7. **Use latexmk** – Automatically runs multiple passes and bibtex\n8. **Search for exact error text** – Stack Exchange has answers for almost every LaTeX error\n9. **Create MWEs** – Smallest example that reproduces error helps debugging\n10. **Read package documentation** – Most errors come from misusing packages\n\n---\n\n## Resources\n\n- **TeX Stack Exchange**: https://tex.stackexchange.com/\n - Search your exact error message; likely already answered\n- **CTAN (Package Documentation)**: https://ctan.org/\n - Official package documentation and examples\n- **LaTeX Wikibook**: https://en.wikibooks.org/wiki/LaTeX\n - Comprehensive tutorial and reference\n- **The Not So Short Introduction to LaTeX**: Classic beginner guide\n - Search for \"lshort.pdf\"\n\n**When asking for help**, always provide:\n1. Minimal Working Example (MWE)\n2. Full error message from .log file\n3. LaTeX distribution and version (`pdflatex --version`)\n4. Compilation command used\n\n---\n\n## 9. Document-Specific Pitfalls\n\n### Exam Class Pitfalls\n\n- Do NOT use `\\usepackage{fancyhdr}` with exam class -- it conflicts with exam's own `headandfoot` pagestyle, causing `\\f@nch@orf` errors. The exam class provides `\\firstpageheader`, `\\runningheader`, `\\footer` instead.\n- Do NOT use bare `\\section*{}` inside `\\begin{questions}` -- it causes \"Something's wrong--perhaps a missing \\item\" errors. Use `\\fullwidth{\\section*{Part A: ...}}` instead.\n- Use `\\fullwidth{...}` for ANY non-question content inside the `questions` environment (headings, instructions, notes).\n\n### Book/Thesis Pitfalls\n\n- When using `fancyhdr` with custom headers, set `headheight=14pt` (or larger) in geometry options: `\\usepackage[margin=1in, headheight=14pt]{geometry}`. Without this, you get \"headheight is too small\" warnings that can cause layout issues.\n- First-pass compilation of books/theses will always show \"undefined references\" and \"Label(s) may have changed\" warnings -- this is normal. The compile script runs multiple passes to resolve these.\n\n---\n\n**Document Version**: 1.0\n**Last Updated**: 2026-02-17\n**Word Count**: ~14,500 words (~14.5KB)","content_type":"text/markdown; charset=utf-8","language":"markdown","size":50420,"content_sha256":"951c89677c542f3660f8a4a96a304ecc9da6100c37d2b8b394bfa7a0dd257945"},{"filename":"references/font-guide.md","content":"# Font Selection & Typography Guide\n\nA comprehensive guide to choosing and configuring fonts in LaTeX documents, covering everything from basic font selection to advanced typography techniques.\n\n## Table of Contents\n\n1. [Font Basics in LaTeX](#1-font-basics-in-latex)\n2. [Engine-Specific Font Handling](#2-engine-specific-font-handling)\n3. [Font Pairing Recommendations](#3-font-pairing-recommendations)\n4. [Mathematical Fonts](#4-mathematical-fonts)\n5. [Icons with fontawesome5](#5-icons-with-fontawesome5)\n6. [Microtype (Typography Fine-Tuning)](#6-microtype-typography-fine-tuning)\n7. [Font Size & Spacing](#7-font-size--spacing)\n8. [CJK Font Setup](#8-cjk-font-setup)\n9. [Common Font Problems & Solutions](#9-common-font-problems--solutions)\n10. [Quick Reference: Font → Package Mapping](#10-quick-reference-font--package-mapping)\n\n---\n\n## 1. Font Basics in LaTeX\n\nLaTeX fonts are controlled through three independent axes that can be combined to create different typographic effects:\n\n### The Three Font Axes\n\n1. **Family** - The overall design style\n - `\\rmfamily` or `\\textrm{...}` - Serif (roman) fonts with decorative strokes\n - `\\sffamily` or `\\textsf{...}` - Sans-serif fonts without strokes\n - `\\ttfamily` or `\\texttt{...}` - Monospace (typewriter) fonts with fixed width\n\n2. **Series** - The weight or width\n - `\\mdseries` or `\\textmd{...}` - Medium weight (default)\n - `\\bfseries` or `\\textbf{...}` - Bold weight\n - Some fonts support `\\lfseries` (light) through special packages\n\n3. **Shape** - The posture or variation\n - `\\upshape` or `\\textup{...}` - Upright (default)\n - `\\itshape` or `\\textit{...}` - Italic (cursive, redesigned letters)\n - `\\slshape` or `\\textsl{...}` - Slanted (mechanically sloped)\n - `\\scshape` or `\\textsc{...}` - Small Caps\n\n### Default LaTeX Fonts: Computer Modern\n\nLaTeX's default font is Computer Modern (CM), designed by Donald Knuth specifically for TeX. This is why LaTeX documents have a distinctive \"LaTeX-y\" look:\n\n- **Characteristics**: High stroke contrast, narrow letter spacing, geometric design\n- **Advantages**: Excellent mathematical typography, crisp at all sizes, free\n- **Disadvantages**: Looks dated to modern readers, limited character sets in original CM\n- **Modern Alternative**: Latin Modern (extended CM with better encoding)\n\n### Why Documents Look \"LaTeX-y\" and How to Change\n\nThe LaTeX aesthetic comes from:\n1. Computer Modern font family\n2. Tight letter spacing and specific kerning\n3. Mathematical typesetting conventions\n4. Default page margins (quite wide)\n\nTo modernize your documents:\n```latex\n% Switch to modern fonts\n\\usepackage[T1]{fontenc} % Better font encoding\n\\usepackage{lmodern} % Latin Modern (improved CM)\n% OR choose a completely different font\n\\usepackage{mathpazo} % Palatino\n\\usepackage{newtxtext,newtxmath} % Times\n```\n\n---\n\n## 2. Engine-Specific Font Handling\n\nLaTeX has three main compilation engines, each with different font capabilities:\n\n### pdfLaTeX Fonts (Package-Based)\n\npdfLaTeX uses traditional TeX fonts installed through packages. This is the most compatible but least flexible approach.\n\n#### Serif (Text) Fonts\n\n```latex\n% Palatino - Elegant, highly readable, excellent for books\n\\usepackage{mathpazo}\n% OR modern version with better math support:\n\\usepackage{newpxtext,newpxmath}\n\n% Times - Compact, traditional, good for space-constrained docs\n\\usepackage{newtxtext,newtxmath}\n\n% Latin Modern - Clean, modern version of Computer Modern\n\\usepackage{lmodern}\n\n% Libertinus - Modern, open source, excellent math support\n\\usepackage{libertinus}\n\n% Cochineal - Warm, readable, based on Crimson\n\\usepackage{cochineal}\n\\usepackage[cochineal]{newtxmath}\n\n% Baskerville - Classic, elegant, good for literature\n\\usepackage{librebaskerville}\n\n% Garamond - Traditional, refined, excellent for books\n\\usepackage{ebgaramond}\n\\usepackage[cmintegrals,cmbraces]{newtxmath}\n\\usepackage[italic]{mathastext}\n\n% Charter - Clean, readable, designed for low-res output\n\\usepackage[bitstream-charter]{mathdesign}\n\n% Utopia - Generous x-height, modern serif\n\\usepackage{fourier}\n```\n\n#### Sans-Serif Fonts\n\n```latex\n% Roboto - Google's geometric humanist font\n\\usepackage[sfdefault]{roboto}\n\n% Fira Sans - Mozilla's humanist sans, great for tech docs\n\\usepackage[sfdefault]{FiraSans}\n\n% Noto Sans - Google's font covering 800+ languages\n\\usepackage[sfdefault]{noto-sans}\n\n% Source Sans Pro - Adobe's readable humanist sans\n\\usepackage[default]{sourcesanspro}\n\n% Helvetica (clone) - Classic neutral sans-serif\n\\usepackage[scaled]{helvet}\n\\renewcommand\\familydefault{\\sfdefault}\n\n% Avant Garde (clone) - Geometric, rounded\n\\usepackage{avant}\n\\renewcommand\\familydefault{\\sfdefault}\n\n% Cabin - Humanist sans inspired by Gill Sans\n\\usepackage[sfdefault]{cabin}\n```\n\n#### Monospace Fonts\n\n```latex\n% Inconsolata - Most popular LaTeX monospace, great for code\n\\usepackage[scaled=0.95]{inconsolata}\n\n% Fira Mono - Matches Fira Sans, excellent readability\n\\usepackage[scale=0.9]{FiraMono}\n\n% Source Code Pro - Adobe's monospace, generous spacing\n\\usepackage[scale=0.9]{sourcecodepro}\n\n% Anonymous Pro - Fixed-width with distinct characters\n\\usepackage[ttdefault]{anonymous-pro}\n\n% Courier - Classic typewriter font\n\\usepackage{courier}\n```\n\n#### Complete Font Setup Example (pdfLaTeX)\n\n```latex\n\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\n% Text font: Palatino\n\\usepackage{newpxtext}\n% Math font: Matching Palatino math\n\\usepackage{newpxmath}\n% Monospace: Inconsolata for code\n\\usepackage[scaled=0.95]{inconsolata}\n\n\\begin{document}\nRegular text in Palatino. \\texttt{Code in Inconsolata}. $E = mc^2$ in Palatino math.\n\\end{document}\n```\n\n### XeLaTeX/LuaLaTeX Fonts (System Fonts with fontspec)\n\nXeLaTeX and LuaLaTeX can use any font installed on your system through the `fontspec` package. This is more flexible but requires fonts to be installed system-wide.\n\n```latex\n\\documentclass{article}\n\\usepackage{fontspec}\n\n% Main text font (serif)\n\\setmainfont{TeX Gyre Pagella}[\n Ligatures=TeX, % Enable LaTeX ligatures (-- → en-dash)\n Numbers=OldStyle, % Use old-style figures (optional)\n BoldFont=TeX Gyre Pagella Bold,\n ItalicFont=TeX Gyre Pagella Italic\n]\n\n% Sans-serif font\n\\setsansfont{TeX Gyre Heros}[\n Scale=MatchLowercase, % Match x-height of main font\n Ligatures=TeX\n]\n\n% Monospace font\n\\setmonofont{Fira Code}[\n Scale=0.9,\n Contextuals=Alternate % Enable ligatures in code (optional)\n]\n\n\\begin{document}\nMain text. \\textsf{Sans-serif text}. \\texttt{Monospace code}.\n\\end{document}\n```\n\n#### Using System Fonts\n\n```latex\n% macOS examples\n\\setmainfont{Hoefler Text}\n\\setsansfont{Helvetica Neue}\n\n% Windows examples\n\\setmainfont{Georgia}\n\\setsansfont{Segoe UI}\n\n% Linux examples (requires fonts installed)\n\\setmainfont{Linux Libertine O}\n\\setsansfont{Linux Biolinum O}\n\n% Adobe fonts (if installed)\n\\setmainfont{Minion Pro}\n\\setsansfont{Myriad Pro}\n```\n\n### Engine-Agnostic Setup (Modern Best Practice with iftex)\n\nFor maximum portability, write code that works with both pdfLaTeX and XeLaTeX/LuaLaTeX:\n\n```latex\n\\documentclass{article}\n\\usepackage{iftex}\n\n\\ifPDFTeX\n % pdfLaTeX setup\n \\usepackage[utf8]{inputenc}\n \\usepackage[T1]{fontenc}\n \\usepackage{newtxtext,newtxmath}\n \\usepackage[scaled=0.95]{inconsolata}\n\\else\n % XeLaTeX/LuaLaTeX setup\n \\usepackage{fontspec}\n \\setmainfont{TeX Gyre Termes}\n \\setmonofont{Inconsolata}[Scale=0.95]\n \\usepackage{unicode-math}\n \\setmathfont{TeX Gyre Termes Math}\n\\fi\n\n\\begin{document}\nThis document works with all engines!\n\\end{document}\n```\n\n#### Complete Engine-Agnostic Template\n\n```latex\n\\documentclass[11pt]{article}\n\\usepackage{iftex}\n\n\\ifPDFTeX\n \\usepackage[utf8]{inputenc}\n \\usepackage[T1]{fontenc}\n \\usepackage{newpxtext} % Palatino text\n \\usepackage{newpxmath} % Palatino math\n \\usepackage[scaled=0.95]{inconsolata}\n\\else\n \\usepackage{fontspec}\n \\setmainfont{TeX Gyre Pagella}[Ligatures=TeX]\n \\setmonofont{Inconsolata}[Scale=0.95]\n \\usepackage{unicode-math}\n \\setmathfont{TeX Gyre Pagella Math}\n\\fi\n\n\\usepackage{microtype} % Works with all engines\n\n\\begin{document}\nWorks everywhere: plain text, \\textbf{bold}, \\textit{italic},\n\\texttt{code}, and math: $\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}$\n\\end{document}\n```\n\n---\n\n## 3. Font Pairing Recommendations\n\nGood typography requires harmonious font combinations. Here are tested pairings for different document types.\n\n### Academic/Formal Documents\n\n| Text Font | Math Font | Package | Best For | Notes |\n|-----------|-----------|---------|----------|-------|\n| Palatino | Matching | `newpxtext` + `newpxmath` | Theses, books, elegant docs | Hermann Zapf's masterpiece, highly readable |\n| Times | Matching | `newtxtext` + `newtxmath` | Papers, journals, compact docs | Industry standard, space-efficient |\n| Libertinus | Matching | `libertinus` | Modern academic, open source | Based on Linux Libertine, excellent math |\n| Latin Modern | Default CM | `lmodern` | Pure LaTeX aesthetic | For when you want the classic TeX look |\n| Garamond | adapted | `ebgaramond` + `newtxmath` | Literary works, humanities | Classic elegance, best for long texts |\n| Baskerville | adapted | `librebaskerville` + math | Historical documents, formal | Traditional British typography |\n| Charter | Matching | `mathdesign` (charter) | Technical reports, preprints | Designed for low-resolution printing |\n| Concrete | Matching | `ccfonts` + `eulervm` | Knuth's books, expository math | Used in \"Concrete Mathematics\" |\n\n#### Example: Thesis Setup\n\n```latex\n\\documentclass[12pt,twoside]{report}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\n% Palatino for elegant, readable body text\n\\usepackage{newpxtext}\n\\usepackage{newpxmath}\n\n% Monospace for code listings\n\\usepackage[scaled=0.95]{inconsolata}\n\n% Fine typography adjustments\n\\usepackage[final]{microtype}\n\n\\begin{document}\n% Beautiful thesis content\n\\end{document}\n```\n\n### Modern/Technical Documents\n\n| Text Font | Sans Font | Mono Font | Best For | Character |\n|-----------|-----------|-----------|----------|-----------|\n| Source Serif | Source Sans | Source Code | Adobe suite, tech docs | Cohesive Adobe family |\n| Fira Sans | - | Fira Mono | Mozilla, data science | Modern, technical, great on-screen |\n| Roboto | Roboto Condensed | Roboto Mono | Google-style, presentations | Geometric, friendly, versatile |\n| Noto Serif | Noto Sans | Noto Mono | Multilingual, CJK support | Universal language coverage |\n| Carlito + Caladea | Carlito | Courier | LibreOffice compatibility | MS Office metric-compatible |\n\n#### Example: Technical Report\n\n```latex\n\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\n% Modern sans-serif throughout\n\\usepackage[sfdefault]{FiraSans}\n\\usepackage[scale=0.9]{FiraMono}\n\n% No math font needed for technical docs without equations\n\\usepackage{microtype}\n\n\\begin{document}\nClean, modern technical documentation.\n\\end{document}\n```\n\n### Resume/Business Documents\n\n| Font | Style | Best For | Impression |\n|------|-------|----------|------------|\n| Fira Sans | Modern, clean | Tech resumes, startups | Professional, contemporary |\n| Roboto | Friendly, readable | Creative, marketing | Approachable, modern |\n| EB Garamond | Classic, elegant | Finance, law, consulting | Traditional, prestigious |\n| Libertinus | Scholarly, open | Research positions | Academic, sophisticated |\n| Source Sans | Technical, clear | Engineering, data | Clean, technical |\n| Charter | Readable, neutral | General business | Professional, safe choice |\n\n#### Example: Modern Resume\n\n```latex\n\\documentclass[10pt]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\n% Clean sans-serif\n\\usepackage[sfdefault,light]{roboto}\n\n% Icons for contact info\n\\usepackage{fontawesome5}\n\n% Tight margins for resume\n\\usepackage[margin=0.5in]{geometry}\n\n\\begin{document}\n\\section*{Contact}\n\\faEnvelope\\ [email protected] \\quad\n\\faPhone*\\ (555) 123-4567 \\quad\n\\faGithub\\ github.com/username\n\\end{document}\n```\n\n### Presentation/Slide Pairings\n\n| Heading Font | Body Font | Best For |\n|--------------|-----------|----------|\n| Fira Sans Bold | Fira Sans | Technical talks |\n| Roboto Condensed | Roboto | Business presentations |\n| Montserrat | Source Sans | Modern, creative |\n| Raleway | Lato | Minimalist, clean |\n\n---\n\n## 4. Mathematical Fonts\n\nMathematics requires special font handling because of the vast number of symbols and strict spacing requirements.\n\n### Key Math Font Packages (pdfLaTeX)\n\n```latex\n% Times-compatible math\n\\usepackage{newtxtext,newtxmath}\n% Produces: text in Times, math in Times-styled symbols\n\n% Palatino-compatible math\n\\usepackage{newpxtext,newpxmath}\n% Produces: text in Palatino, math in Palatino-styled symbols\n\n% Classic Palatino math (older package)\n\\usepackage{mathpazo}\n% Still works but newpxmath is more complete\n\n% Libertinus (text + math in one package)\n\\usepackage{libertinus}\n% Modern, excellent coverage, open source\n\n% Euler math (upright, calligraphic style)\n\\usepackage{eulervm}\n% Used with Concrete fonts in Knuth's books\n\n% Fourier (with Utopia text)\n\\usepackage{fourier}\n% Generous x-height, modern appearance\n\n% KP Serif math (with Kepler fonts)\n\\usepackage{kpfonts}\n% Complete package with many options\n\n% Antykwa Toruńska\n\\usepackage{anttor}\n% Polish design, distinctive appearance\n```\n\n### Unicode Math (XeLaTeX/LuaLaTeX)\n\nWith modern engines, use the `unicode-math` package for OpenType math fonts:\n\n```latex\n\\usepackage{unicode-math}\n\n% Available OpenType math fonts:\n\\setmathfont{Latin Modern Math} % Extended Computer Modern\n\\setmathfont{TeX Gyre Pagella Math} % Palatino-style\n\\setmathfont{TeX Gyre Termes Math} % Times-style\n\\setmathfont{TeX Gyre DejaVu Math} % DejaVu-style\n\\setmathfont{STIX Two Math} % Scientific/technical\n\\setmathfont{XITS Math} % Extended STIX\n\\setmathfont{Libertinus Math} % Modern, complete\n\\setmathfont{Fira Math} % Sans-serif math (experimental)\n\\setmathfont{Asana Math} % Extensive symbol coverage\n```\n\n### Font Metrics: Matching X-Height\n\nThe x-height (height of lowercase 'x') must match between text and math for visual consistency:\n\n```latex\n% Bad: text and math x-heights don't match\n\\usepackage{charter} % Charter text\n\\usepackage{newtxmath} % Times math - MISMATCH!\n\n% Good: matched pair\n\\usepackage[charter]{mathdesign} % Charter text + matching math\n% OR\n\\usepackage{newtxtext,newtxmath} % Both Times-based\n```\n\n### Math Font Comparison\n\n```latex\n\\documentclass{article}\n\n% Test different math fonts:\n\\usepackage{newpxtext,newpxmath} % Choice 1: Palatino\n\n\\begin{document}\nInline math: $E = mc^2$, $\\alpha + \\beta = \\gamma$\n\nDisplay math:\n\\[\n\\int_0^\\infty \\frac{x^3}{e^x-1}\\,dx = \\frac{\\pi^4}{15}\n\\]\n\nMatrix:\n\\[\n\\begin{pmatrix}\na & b \\\\\nc & d\n\\end{pmatrix}\n\\]\n\\end{document}\n```\n\n### Advanced Math Font Configuration\n\n```latex\n% Mix and match for specific needs\n\\usepackage{newpxtext} % Palatino text\n\\usepackage[vvarbb]{newpxmath} % Palatino math with special options\n% Options:\n% vvarbb - variant blackboard bold\n% bigdelims - larger delimiters\n% noamssymbols - don't load AMS symbols\n\n% Or use different fonts for different math alphabets\n\\usepackage{newpxtext,newpxmath}\n\\usepackage{bm} % Bold math\n% Now \\mathbb, \\mathcal, \\mathfrak are available\n```\n\n---\n\n## 5. Icons with fontawesome5\n\nThe `fontawesome5` package provides access to 1,500+ vector icons, essential for modern resumes and documents.\n\n### Basic Setup\n\n```latex\n\\usepackage{fontawesome5}\n\n% Use icons inline:\n\\faEnvelope\\ [email protected]\n```\n\n### Common Icons Reference\n\n#### Contact Information\n```latex\n\\faEnvelope % email (outline)\n\\faEnvelope* % email (solid)\n\\faPhone % phone (outline)\n\\faPhone* % phone (solid)\n\\faMobile % mobile phone\n\\faMobile* % mobile phone (solid)\n\\faMapMarker % location (outline)\n\\faMapMarker* % location (solid)\n\\faHome % home address\n\\faGlobe % website\n```\n\n#### Social Media\n```latex\n\\faLinkedin % LinkedIn logo\n\\faGithub % GitHub logo\n\\faGitlab % GitLab logo\n\\faTwitter % Twitter/X logo\n\\faFacebook % Facebook logo\n\\faInstagram % Instagram logo\n\\faStackOverflow % Stack Overflow logo\n\\faYoutube % YouTube logo\n\\faMedium % Medium logo\n```\n\n#### Professional/Resume\n```latex\n\\faBriefcase % work experience\n\\faGraduationCap % education\n\\faCertificate % certification\n\\faAward % awards/honors\n\\faCode % programming/code\n\\faLaptopCode % software development\n\\faTools % skills/tools\n\\faProjectDiagram % projects\n\\faUsers % teamwork\n\\faLightbulb % ideas/innovation\n\\faChartLine % growth/metrics\n```\n\n#### Document Elements\n```latex\n\\faFile % generic file\n\\faFilePdf % PDF file\n\\faFileCode % code file\n\\faFileAlt % document\n\\faLink % hyperlink\n\\faExternalLinkAlt % external link\n\\faDownload % download\n\\faInfoCircle % information\n\\faExclamationTriangle % warning\n\\faCheckCircle % success/checkmark\n\\faTimesCircle % error/close\n```\n\n### Icon Styles\n\nFont Awesome has three styles: solid (default), regular (outline), and brands.\n\n```latex\n% Solid style (filled) - use * or -s suffix\n\\faHeart* % filled heart\n\\faStar* % filled star\n\n% Regular style (outline) - use -r suffix or no suffix\n\\faHeart[-regular] % outline heart\n\\faStar[-regular] % outline star\n\n% Brands style (logos) - automatic\n\\faGithub % brand logos\n```\n\n### Sizing Icons\n\n```latex\n% Match text size\n\\faIcon{envelope}\n\n% Custom size\n\\faIcon[regular]{star} \\quad\n{\\Large \\faIcon{star}} \\quad\n{\\Huge \\faIcon{star}}\n```\n\n### Resume Example with Icons\n\n```latex\n\\documentclass{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage[sfdefault]{roboto}\n\\usepackage{fontawesome5}\n\\usepackage[margin=0.5in]{geometry}\n\n\\begin{document}\n\n\\section*{\\faUser\\ John Doe}\n\n\\faEnvelope\\ [email protected] \\quad\n\\faPhone*\\ (555) 123-4567 \\quad\n\\faMapMarker*\\ San Francisco, CA\n\n\\faLinkedin\\ linkedin.com/in/johndoe \\quad\n\\faGithub\\ github.com/johndoe \\quad\n\\faGlobe\\ johndoe.com\n\n\\section*{\\faBriefcase\\ Experience}\n\\textbf{Senior Software Engineer} \\quad \\faCalendar\\ 2020--Present\n\n\\section*{\\faGraduationCap\\ Education}\n\\textbf{B.S. Computer Science} \\quad \\faUniversity\\ MIT \\quad 2016\n\n\\section*{\\faCode\\ Skills}\nPython \\quad JavaScript \\quad \\faDatabase\\ SQL \\quad \\faDocker\\ Docker\n\n\\end{document}\n```\n\n---\n\n## 6. Microtype (Typography Fine-Tuning)\n\nThe `microtype` package provides micro-typographic improvements that make text more readable and professional-looking.\n\n### Basic Usage\n\n```latex\n% Minimal setup (recommended for all documents)\n\\usepackage{microtype}\n\n% Full setup with all features\n\\usepackage[\n final, % Enable in final mode (default)\n protrusion=true, % Character protrusion\n expansion=true, % Font expansion\n tracking=true, % Letter spacing adjustments\n kerning=true % Additional kerning\n]{microtype}\n```\n\n### Character Protrusion (Margin Kerning)\n\nProtrusion lets certain characters (hyphens, periods, commas) extend slightly into the margin for better optical alignment:\n\n```latex\n\\usepackage[protrusion=true]{microtype}\n\n% Customization (advanced)\n\\SetProtrusion{\n encoding = *,\n family = *\n}{\n A = {50,50}, % Protrude both sides of 'A'\n . = {,700}, % Protrude period to the right\n - = {,500} % Protrude hyphen to the right\n}\n```\n\n**Effect**: Makes justified text appear more even, especially at line beginnings/ends.\n\n### Font Expansion\n\nAllows tiny stretching or shrinking of characters (typically ±2%) to improve line breaking:\n\n```latex\n\\usepackage[expansion=true]{microtype}\n\n% Customization\n\\SetExpansion[\n stretch = 20, % Maximum stretch (1/1000 em)\n shrink = 20, % Maximum shrink\n step = 5 % Granularity\n]{\n encoding = *\n}{\n A = 500, % 'A' can expand more\n Q = 700 % 'Q' can expand even more\n}\n```\n\n**Effect**: Reduces hyphenation and improves word spacing in justified text. **Note**: Only works with pdfLaTeX, not XeLaTeX/LuaLaTeX.\n\n### Tracking (Letter Spacing)\n\nAdjusts spacing between letters, particularly useful for small caps and all-caps text:\n\n```latex\n\\usepackage[tracking=true]{microtype}\n\n% Automatic tracking for small caps\n\\textsc{Small Caps Look Better}\n\n% Manual tracking adjustment\n{\\textls[100]{WIDELY SPACED TEXT}}\n{\\textls[-50]{Tightly Spaced}}\n```\n\n### Draft vs Final Mode\n\n```latex\n% Disable microtype during drafting for faster compilation\n\\usepackage[draft]{microtype}\n\n% Enable for final version\n\\usepackage[final]{microtype}\n\n% OR respect document class option\n\\usepackage{microtype} % Uses class's draft/final setting\n```\n\n### Complete Example\n\n```latex\n\\documentclass[11pt]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage{newpxtext,newpxmath}\n\n% Full microtype configuration\n\\usepackage[\n final,\n protrusion=true,\n expansion=true,\n tracking=true,\n kerning=true,\n spacing=true\n]{microtype}\n\n\\begin{document}\n\\section{Beautiful Typography}\n\nThis document uses microtype for professional-quality typesetting.\nNotice how the line breaking is improved, margins are optically aligned,\nand \\textsc{Small Caps} are properly spaced. The difference is subtle\nbut significant in long documents.\n\nCompare: \\textsc{without tracking} vs \\textls[75]{\\textsc{with tracking}}\n\n\\end{document}\n```\n\n### When to Use Each Feature\n\n| Feature | Use Case | Engine Support |\n|---------|----------|----------------|\n| Protrusion | Always (minimal cost, big benefit) | pdfLaTeX, XeLaTeX, LuaLaTeX |\n| Expansion | Justified text, formal documents | pdfLaTeX only |\n| Tracking | Small caps, headers, titles | All engines |\n| Kerning | Fine-tuning specific fonts | All engines |\n\n---\n\n## 7. Font Size & Spacing\n\n### Document Class Sizes\n\nStandard LaTeX classes offer three sizes:\n\n```latex\n\\documentclass[10pt]{article} % Small (default)\n\\documentclass[11pt]{article} % Medium (recommended for most)\n\\documentclass[12pt]{article} % Large (formal documents, theses)\n```\n\n### Extended Sizes with extarticle\n\nFor non-standard sizes, use the `extarticle` or `extreport` classes:\n\n```latex\n\\documentclass[8pt]{extarticle} % Very small\n\\documentclass[9pt]{extarticle} % Small\n\\documentclass[14pt]{extarticle} % Large\n\\documentclass[17pt]{extarticle} % Very large\n\\documentclass[20pt]{extarticle} % Huge (posters, presentations)\n```\n\n### Custom Font Sizes\n\nFor precise size control, use `\\fontsize{size}{baselineskip}\\selectfont`:\n\n```latex\n% Syntax: \\fontsize{size in pt}{baseline skip in pt}\\selectfont\n\n{\\fontsize{14}{18}\\selectfont Large text with 18pt baseline}\n\n{\\fontsize{8}{10}\\selectfont Small text with 10pt baseline}\n\n% Rule of thumb: baseline skip = 1.2 × font size\n```\n\n### Relative Size Commands\n\nLaTeX provides relative size commands:\n\n```latex\n\\tiny % ~5pt in 10pt document\n\\scriptsize % ~7pt\n\\footnotesize % ~8pt\n\\small % ~9pt\n\\normalsize % document default (10/11/12pt)\n\\large % ~12pt\n\\Large % ~14pt\n\\LARGE % ~17pt\n\\huge % ~20pt\n\\Huge % ~25pt\n```\n\n**Usage:**\n```latex\n{\\Large This text is larger} % Note the braces for grouping\n```\n\n### Line Spacing\n\nControl vertical spacing between lines:\n\n```latex\n% Using setspace package (recommended)\n\\usepackage{setspace}\n\n\\singlespacing % 1.0 spacing\n\\onehalfspacing % 1.5 spacing (common for theses)\n\\doublespacing % 2.0 spacing (manuscripts)\n\n% Custom spacing\n\\setstretch{1.25} % 1.25 spacing\n\n% Local changes\n\\begin{spacing}{1.5}\nThis paragraph has 1.5 line spacing.\n\\end{spacing}\n```\n\n```latex\n% Using linespread (primitive method)\n\\linespread{1.3} % 1.3 × default spacing\n\\selectfont % Activate the change\n\n% Note: linespread uses different scale than setspace\n% linespread{1.3} ≈ onehalfspacing\n% linespread{1.6} ≈ doublespacing\n```\n\n### Paragraph Spacing\n\n```latex\n% Increase space between paragraphs\n\\setlength{\\parskip}{0.5\\baselineskip}\n\\setlength{\\parindent}{0pt} % Remove indentation when using parskip\n\n% Or use parskip package\n\\usepackage{parskip} % Adds space, removes indentation automatically\n```\n\n### Complete Example\n\n```latex\n\\documentclass[11pt]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage{newpxtext}\n\\usepackage{setspace}\n\n% Document-wide 1.15 spacing\n\\setstretch{1.15}\n\n\\begin{document}\n\n% Normal size section\n\\section{Standard Size}\nThis is 11pt text with 1.15 line spacing.\n\n% Increase spacing locally\n\\begin{spacing}{1.5}\n\\section{Increased Spacing}\nThis section has 1.5 line spacing, often required for thesis submissions.\n\\end{spacing}\n\n% Custom size for a block\n{\\fontsize{14}{18}\\selectfont\n\\section*{Large Section}\nThis section uses 14pt font with 18pt baseline.\n}\n\n% Small print\n{\\small\n\\section*{Fine Print}\nThis section uses the small size relative to the document class.\n}\n\n\\end{document}\n```\n\n---\n\n## 8. CJK Font Setup\n\nChinese, Japanese, and Korean (CJK) languages require special font packages.\n\n### XeLaTeX/LuaLaTeX (Recommended)\n\nModern engines handle CJK naturally with system fonts:\n\n```latex\n\\documentclass{article}\n\\usepackage{xeCJK}\n\n% Chinese (Simplified)\n\\setCJKmainfont{Noto Serif CJK SC}\n\\setCJKsansfont{Noto Sans CJK SC}\n\\setCJKmonofont{Noto Sans Mono CJK SC}\n\n\\begin{document}\n中文测试 Chinese test 中英混排\n\\end{document}\n```\n\n#### Chinese Variants\n\n```latex\n% Simplified Chinese (mainland China)\n\\setCJKmainfont{Noto Serif CJK SC}\n\n% Traditional Chinese (Taiwan)\n\\setCJKmainfont{Noto Serif CJK TC}\n\n% Traditional Chinese (Hong Kong)\n\\setCJKmainfont{Noto Serif CJK HK}\n\n% Alternative fonts\n\\setCJKmainfont{Source Han Serif SC} % Adobe's font\n\\setCJKmainfont{FandolSong} % Free font in TeX Live\n```\n\n#### Japanese\n\n```latex\n\\usepackage{xeCJK}\n\\setCJKmainfont{Noto Serif CJK JP}\n\\setCJKsansfont{Noto Sans CJK JP}\n\n% Alternative fonts\n\\setCJKmainfont{Source Han Serif JP} % Adobe\n\\setCJKmainfont{IPAMincho} % Free Japanese font\n```\n\n#### Korean\n\n```latex\n\\usepackage{xeCJK}\n\\setCJKmainfont{Noto Serif CJK KR}\n\\setCJKsansfont{Noto Sans CJK KR}\n\n% Alternative fonts\n\\setCJKmainfont{Source Han Serif KR}\n\\setCJKmainfont{Baekmuk Batang} % Free Korean font\n```\n\n### Mixed CJK Languages\n\n```latex\n\\documentclass{article}\n\\usepackage{xeCJK}\n\n% Default CJK font\n\\setCJKmainfont{Noto Serif CJK SC}\n\n% Specific language fonts\n\\newCJKfontfamily\\chinesefont{Noto Serif CJK SC}\n\\newCJKfontfamily\\japanesefont{Noto Serif CJK JP}\n\\newCJKfontfamily\\koreanfont{Noto Serif CJK KR}\n\n\\begin{document}\nEnglish text.\n\n{\\chinesefont 中文文本}\n\n{\\japanesefont 日本語テキスト}\n\n{\\koreanfont 한국어 텍스트}\n\\end{document}\n```\n\n### pdfLaTeX CJK (Legacy)\n\nFor pdfLaTeX (not recommended, limited font support):\n\n```latex\n\\documentclass{article}\n\\usepackage{CJKutf8}\n\n\\begin{document}\n\\begin{CJK}{UTF8}{gbsn} % Simplified Chinese\n中文测试\n\\end{CJK}\n\n\\begin{CJK}{UTF8}{bsmi} % Traditional Chinese\n中文測試\n\\end{CJK}\n\n\\begin{CJK}{UTF8}{min} % Japanese\n日本語テキスト\n\\end{CJK}\n\\end{document}\n```\n\n### Complete CJK Example\n\n```latex\n\\documentclass[12pt]{article}\n\\usepackage{xeCJK}\n\\usepackage{fontspec}\n\n% English fonts\n\\setmainfont{TeX Gyre Pagella}\n\n% CJK fonts\n\\setCJKmainfont{Noto Serif CJK SC}[\n BoldFont=Noto Serif CJK SC Bold,\n ItalicFont=AR PL KaitiM GB % Kaiti style for emphasis\n]\n\\setCJKsansfont{Noto Sans CJK SC}\n\\setCJKmonofont{Noto Sans Mono CJK SC}\n\n\\begin{document}\n\n\\section{Introduction 介绍}\n\nThis document demonstrates CJK and English mixing.\n本文档展示中英文混合排版。\n\n\\textbf{Bold text 粗体文本}\n\n\\textsf{Sans-serif 无衬线字体}\n\n\\texttt{Monospace 等宽字体}\n\n\\end{document}\n```\n\n---\n\n## 9. Common Font Problems & Solutions\n\n### Problem: \"Font X not found\"\n\n**Symptoms:**\n```\n! Font \\TU/FiraCode/m/n/10=FiraCode at 10pt not loadable\n```\n\n**Cause:** Font not installed on the system (XeLaTeX/LuaLaTeX) or package not installed (pdfLaTeX).\n\n**Solutions:**\n\nFor XeLaTeX/LuaLaTeX:\n```bash\n# List available fonts\nfc-list | grep \"Fira\"\n\n# Install fonts (Ubuntu/Debian)\nsudo apt install fonts-firacode\n\n# Install fonts (macOS)\nbrew install --cask font-fira-code\n\n# Or download and install manually to:\n# - Linux: ~/.fonts/ or /usr/share/fonts/\n# - macOS: ~/Library/Fonts/ or /Library/Fonts/\n# - Windows: C:\\Windows\\Fonts\\\n```\n\nFor pdfLaTeX:\n```bash\n# Install package via TeX Live manager\ntlmgr install firacode\n\n# Or via Linux package manager\nsudo apt install texlive-fonts-extra\n```\n\n### Problem: \"Missing character\" warnings\n\n**Symptoms:**\n```\nMissing character: There is no é in font cmr10!\n```\n\n**Cause:** Font doesn't contain the character, or wrong encoding.\n\n**Solutions:**\n\n```latex\n% pdfLaTeX: Use T1 encoding and inputenc\n\\usepackage[T1]{fontenc}\n\\usepackage[utf8]{inputenc}\n\n% XeLaTeX/LuaLaTeX: Already supports Unicode\n\\usepackage{fontspec}\n\n% If character still missing, use a font with better coverage\n\\usepackage{lmodern} % Latin Modern has extended characters\n% OR\n\\setmainfont{DejaVu Serif} % Extensive Unicode coverage\n```\n\n### Problem: Font Substitution\n\n**Symptoms:**\n```\nLaTeX Font Warning: Font shape `T1/cmr/bx/sc' undefined\n(Font) using `T1/cmr/bx/n' instead\n```\n\n**Cause:** Requested font variation (e.g., bold small caps) doesn't exist.\n\n**Solutions:**\n\n```latex\n% 1. Choose a font family with more variations\n\\usepackage{newpxtext} % Palatino has bold small caps\n\n% 2. Or accept the substitution\n% LaTeX will use available variant automatically\n\n% 3. Or fake it (not recommended)\n\\usepackage{fontspec}\n\\setmainfont{Some Font}[\n SmallCapsFont = Some Font,\n SmallCapsFeatures = {Letters=SmallCaps}\n]\n```\n\n### Problem: Bold Not Available (Faux Bold)\n\n**Symptoms:**\n```\nLaTeX Font Warning: Font shape `TU/SomeFont/b/n' undefined\n(Font) using `TU/SomeFont/m/n' instead\n```\n\n**Cause:** Font family doesn't include a bold variant.\n\n**Solutions:**\n\n```latex\n% 1. Manually specify bold font\n\\setmainfont{Some Font}[\n BoldFont = Some Bold Font, % Use different font for bold\n]\n\n% 2. Allow synthetic (fake) bold (not recommended for print)\n\\setmainfont{Some Font}[\n BoldFont = Some Font,\n BoldFeatures = {FakeBold=1.5}\n]\n\n% 3. Use a complete font family\n\\setmainfont{TeX Gyre Pagella} % Has all variants\n```\n\n### Problem: Math Symbols Missing\n\n**Symptoms:** Math symbols appear blank or wrong.\n\n**Cause:** Text font changed but math font not updated.\n\n**Solutions:**\n\n```latex\n% pdfLaTeX: Use matching math package\n\\usepackage{newpxtext}\n\\usepackage{newpxmath} % Must match!\n\n% XeLaTeX/LuaLaTeX: Use unicode-math\n\\usepackage{unicode-math}\n\\setmainfont{TeX Gyre Pagella}\n\\setmathfont{TeX Gyre Pagella Math}\n```\n\n### Problem: Encoding Issues with Special Characters\n\n**Symptoms:** Special characters (é, ñ, ü) appear wrong or cause errors.\n\n**Cause:** File encoding doesn't match LaTeX encoding.\n\n**Solutions:**\n\n```latex\n% pdfLaTeX: Ensure UTF-8 encoding\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\n% Save your .tex file as UTF-8 (no BOM) in your editor\n\n% XeLaTeX/LuaLaTeX: UTF-8 by default, no inputenc needed\n\\usepackage{fontspec}\n```\n\n### Problem: Ligatures Not Working\n\n**Symptoms:** \"fi\" and \"fl\" combinations don't form ligatures.\n\n**Cause:** Ligatures disabled or wrong font encoding.\n\n**Solutions:**\n\n```latex\n% pdfLaTeX: Use T1 encoding\n\\usepackage[T1]{fontenc}\n\n% XeLaTeX/LuaLaTeX: Enable ligatures\n\\setmainfont{TeX Gyre Pagella}[\n Ligatures=TeX % Enable TeX ligatures (-- --- `` '')\n]\n\n% Disable for monospace fonts\n\\setmonofont{Fira Code}[\n Ligatures=NoCommon % Disable in code\n]\n```\n\n### Problem: Poor Quality PDF Fonts\n\n**Symptoms:** Fonts look blurry or pixelated in PDF.\n\n**Cause:** Using bitmap fonts instead of vector fonts.\n\n**Solutions:**\n\n```latex\n% Use vector fonts (Type 1 or OpenType)\n\\usepackage{lmodern} % Latin Modern (vector)\n% NOT the default Computer Modern (bitmap)\n\n% Check in PDF viewer: zoom to 400%\n% Vector fonts stay sharp, bitmap fonts pixelate\n\n% For pdfLaTeX, ensure:\n\\usepackage[T1]{fontenc} % T1 encoding uses vector fonts\n```\n\n---\n\n## 10. Quick Reference: Font → Package Mapping\n\nFast lookup table for common fonts and their LaTeX packages.\n\n### Serif Fonts (pdfLaTeX)\n\n| Font Name | Package | Math Support | Notes |\n|-----------|---------|--------------|-------|\n| Palatino | `newpxtext,newpxmath` | Yes | Modern, complete, recommended |\n| Palatino | `mathpazo` | Yes | Classic, older version |\n| Times | `newtxtext,newtxmath` | Yes | Modern Times implementation |\n| Times | `mathptmx` | Yes | Legacy, use newtxtext instead |\n| Latin Modern | `lmodern` | Yes (default) | Extended Computer Modern |\n| Garamond | `ebgaramond` | Partial | Use with adapted math font |\n| Baskerville | `librebaskerville` | No | Pair with adapted math |\n| Charter | `[charter]{mathdesign}` | Yes | Good for tech documents |\n| Utopia | `fourier` | Yes | Generous x-height |\n| Libertinus | `libertinus` | Yes | Modern, open source, excellent |\n| Cochineal | `cochineal` + newtxmath | Yes | Crimson-like, warm |\n| Bookman | `bookman` | No | Wide, readable |\n| Century | `century` | No | Traditional |\n| Concrete | `ccfonts` + `eulervm` | Yes | Knuth's design |\n\n### Sans-Serif Fonts (pdfLaTeX)\n\n| Font Name | Package | Notes |\n|-----------|---------|-------|\n| Roboto | `[sfdefault]{roboto}` | Google's geometric humanist |\n| Fira Sans | `[sfdefault]{FiraSans}` | Mozilla, modern |\n| Noto Sans | `[sfdefault]{noto-sans}` | Google, multilingual |\n| Source Sans | `[default]{sourcesanspro}` | Adobe's humanist sans |\n| Cabin | `[sfdefault]{cabin}` | Gill Sans inspired |\n| Montserrat | `[defaultfam]{montserrat}` | Geometric sans |\n| Raleway | `[default]{raleway}` | Elegant, thin available |\n| Lato | `[default]{lato}` | Humanist, corporate-friendly |\n| Helvetica | `helvet` | Classic neutral sans |\n| Avant Garde | `avant` | Geometric, rounded |\n\n### Monospace Fonts (pdfLaTeX)\n\n| Font Name | Package | Notes |\n|-----------|---------|-------|\n| Inconsolata | `[scaled=0.95]{inconsolata}` | Most popular for code |\n| Fira Mono | `[scale=0.9]{FiraMono}` | Pairs with Fira Sans |\n| Source Code Pro | `[scale=0.9]{sourcecodepro}` | Adobe, generous spacing |\n| Anonymous Pro | `[ttdefault]{anonymous-pro}` | Distinct characters |\n| DejaVu Sans Mono | `{DejaVuSansMono}` | Wide Unicode support |\n| Courier | `courier` | Classic typewriter |\n\n### XeLaTeX/LuaLaTeX System Fonts\n\n| Font Family | Main Font | Sans Font | Mono Font |\n|-------------|-----------|-----------|-----------|\n| TeX Gyre (Free) | TeX Gyre Pagella | TeX Gyre Heros | TeX Gyre Cursor |\n| TeX Gyre (Free) | TeX Gyre Termes | TeX Gyre Heros | TeX Gyre Cursor |\n| Libertinus (Free) | Libertinus Serif | Libertinus Sans | Libertinus Mono |\n| Source (Adobe) | Source Serif Pro | Source Sans Pro | Source Code Pro |\n| Noto (Google) | Noto Serif | Noto Sans | Noto Sans Mono |\n| Fira (Mozilla) | Fira Serif | Fira Sans | Fira Mono |\n\n### Math Fonts\n\n| Math Style | Package (pdfLaTeX) | OpenType Font (XeLaTeX/LuaLaTeX) |\n|------------|-------------------|----------------------------------|\n| Computer Modern | Default or `lmodern` | Latin Modern Math |\n| Palatino | `newpxmath` | TeX Gyre Pagella Math |\n| Times | `newtxmath` | TeX Gyre Termes Math |\n| Libertinus | `libertinus` | Libertinus Math |\n| Euler (upright) | `eulervm` | - |\n| STIX | `stix2` | STIX Two Math |\n\n### Font Package Installation Commands\n\n```bash\n# TeX Live (Linux/macOS)\ntlmgr install \u003cpackage-name>\ntlmgr install collection-fontsrecommended\ntlmgr install collection-fontsextra\n\n# Ubuntu/Debian\nsudo apt install texlive-fonts-recommended\nsudo apt install texlive-fonts-extra\n\n# System fonts for XeLaTeX/LuaLaTeX\n# Ubuntu/Debian\nsudo apt install fonts-noto fonts-firacode fonts-roboto\n\n# macOS (Homebrew)\nbrew install --cask font-fira-code\nbrew install --cask font-source-sans-pro\n```\n\n---\n\n## Summary\n\nThis guide covers the essential aspects of font selection in LaTeX:\n\n1. **Understand font basics**: Family, series, and shape axes\n2. **Choose the right engine**: pdfLaTeX (packages) vs XeLaTeX/LuaLaTeX (system fonts)\n3. **Pair fonts harmoniously**: Match text and math fonts by style and metrics\n4. **Use microtype**: Professional typography with minimal effort\n5. **Configure properly**: Set sizes, spacing, and encodings correctly\n6. **Solve problems**: Know how to diagnose and fix common font issues\n\nFor most users:\n- **Academic documents**: `newpxtext` + `newpxmath` (Palatino)\n- **Technical documents**: `[sfdefault]{FiraSans}` (modern sans)\n- **Modern workflow**: XeLaTeX + `fontspec` + system fonts\n- **Always add**: `\\usepackage{microtype}`\n\nRemember: Good typography is invisible. The best font choice is one that serves the content without drawing attention to itself.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":37035,"content_sha256":"b4f778c76a159f030e0a96f7ea3ecbf0fecd97129b2fcb6e347c0985547c5b31"},{"filename":"references/format-conversion.md","content":"# Document Format Conversion Reference\n\n## Overview\n\n**Pandoc** is a universal document converter that can transform documents between many different formats. It's particularly powerful for converting between Markdown, LaTeX, DOCX, HTML, and PDF formats.\n\n### When to Use Pandoc\n\n- **Markdown → LaTeX**: When you want to write in simple Markdown but need LaTeX output for academic papers or publications\n- **LaTeX → Markdown**: When collaborating with non-LaTeX users or editing in a simpler format\n- **DOCX → LaTeX**: When receiving Word documents that need to be converted to LaTeX\n- **LaTeX → DOCX**: For journal submissions requiring Word format or collaboration with Word users\n- **LaTeX → HTML**: For publishing documents on the web with proper math rendering\n- **LaTeX → PDF**: Alternative to pdflatex/xelatex for simpler documents\n\n### Key Features\n\n- Preserves document structure (headings, lists, tables)\n- Handles mathematical equations (LaTeX math syntax)\n- Converts citations and bibliographies\n- Supports images and figures\n- Customizable via templates\n- Extensible with filters\n\n---\n\n## Markdown to LaTeX\n\nConverting Markdown to LaTeX is useful when you want to write content quickly in Markdown but need the typesetting power and requirements of LaTeX.\n\n### Basic Conversion\n\n```bash\npandoc input.md -o output.tex --standalone\n```\n\nThe `--standalone` flag creates a complete LaTeX document with preamble and document environment.\n\n### Example: Markdown Input\n\n```markdown\n# Introduction\n\nThis is a **simple** document with *emphasis*.\n\n## Mathematical Equations\n\nThe quadratic formula is:\n\n$x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}$\n\nInline math: $E = mc^2$\n\n## Lists\n\n1. First item\n2. Second item\n - Nested bullet\n - Another bullet\n3. Third item\n\n## Code\n\nHere's some Python code:\n\n\\`\\`\\`python\ndef hello():\n print(\"Hello, world!\")\n\\`\\`\\`\n\n## Table\n\n| Name | Age | City |\n|---------|-----|----------|\n| Alice | 30 | New York |\n| Bob | 25 | Boston |\n| Charlie | 35 | Chicago |\n\n## Images\n\n![A beautiful landscape](landscape.jpg)\n```\n\n### LaTeX Output Structure\n\n```latex\n\\documentclass{article}\n\\usepackage{graphicx}\n\\usepackage{amsmath}\n\n\\begin{document}\n\n\\section{Introduction}\nThis is a \\textbf{simple} document with \\emph{emphasis}.\n\n\\subsection{Mathematical Equations}\nThe quadratic formula is:\n\\[x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a}\\]\n\nInline math: $E = mc^2$\n\n\\subsection{Lists}\n\\begin{enumerate}\n\\item First item\n\\item Second item\n \\begin{itemize}\n \\item Nested bullet\n \\item Another bullet\n \\end{itemize}\n\\item Third item\n\\end{enumerate}\n\n% ... etc\n\\end{document}\n```\n\n### Handling Math\n\nPandoc automatically converts:\n- `$... latex-document-skill — Skillopedia → inline math\n- `$...$` → display math equations\n- `\\begin{equation}...\\end{equation}` → numbered equations\n\n### Handling Images\n\nMarkdown images are converted to `\\includegraphics`:\n\n```markdown\n![Caption text](image.png)\n```\n\nBecomes:\n\n```latex\n\\begin{figure}\n\\centering\n\\includegraphics{image.png}\n\\caption{Caption text}\n\\end{figure}\n```\n\n### Handling Tables\n\nPandoc converts Markdown tables to LaTeX `tabular` environment:\n\n```latex\n\\begin{table}\n\\centering\n\\begin{tabular}{lll}\n\\toprule\nName & Age & City \\\\\n\\midrule\nAlice & 30 & New York \\\\\nBob & 25 & Boston \\\\\nCharlie & 35 & Chicago \\\\\n\\bottomrule\n\\end{tabular}\n\\end{table}\n```\n\n### Advanced: Custom LaTeX Template\n\nCreate a custom template for specific formatting:\n\n```bash\npandoc input.md -o output.tex \\\n --template=custom.latex \\\n --variable documentclass=report \\\n --variable fontsize=12pt \\\n --variable geometry:margin=1in\n```\n\n---\n\n## LaTeX to Markdown\n\nConverting LaTeX to Markdown is useful for collaborative editing, web publishing, or creating simpler versions of documents.\n\n### Basic Conversion\n\n```bash\npandoc input.tex -o output.md --from=latex --to=markdown\n```\n\n### What Gets Preserved\n\n- Section headings → Markdown headings\n- `\\textbf{}` → `**bold**`\n- `\\emph{}` → `*italic*`\n- Math equations (preserved as `$... latex-document-skill — Skillopedia and `$...$`)\n- Lists and tables\n- Images (converted to Markdown image syntax)\n\n### What May Be Lost\n\n- Complex LaTeX packages and custom commands\n- Precise formatting (margins, fonts, spacing)\n- TikZ diagrams (converted to raw LaTeX blocks)\n- Custom environments (may need manual cleanup)\n\n### Example\n\n**LaTeX Input:**\n```latex\n\\section{Results}\n\nOur experiment showed that \\textbf{accuracy improved} by 15\\%.\n\n\\begin{equation}\n\\text{Accuracy} = \\frac{TP + TN}{TP + TN + FP + FN}\n\\end{equation}\n```\n\n**Markdown Output:**\n```markdown\n# Results\n\nOur experiment showed that **accuracy improved** by 15%.\n\n$\\text{Accuracy} = \\frac{TP + TN}{TP + TN + FP + FN}$\n```\n\n---\n\n## DOCX to LaTeX\n\nConverting Word documents to LaTeX is common when collaborating with non-LaTeX users or when receiving submissions in Word format.\n\n### Basic Conversion\n\n```bash\npandoc manuscript.docx -o manuscript.tex --standalone\n```\n\n### Preserving Formatting\n\nPandoc converts:\n- **Bold** → `\\textbf{}`\n- *Italic* → `\\emph{}`\n- Headings → `\\section{}`, `\\subsection{}`\n- Lists → `enumerate`, `itemize`\n- Tables → `tabular`\n- Images → `\\includegraphics{}`\n\n### Handling Images\n\nImages embedded in DOCX are extracted to a media folder:\n\n```bash\npandoc manuscript.docx -o manuscript.tex --extract-media=./media\n```\n\nThis creates `./media/` containing extracted images, and the LaTeX file will reference them:\n\n```latex\n\\includegraphics{./media/image1.png}\n```\n\n### Handling Equations\n\n- Word equations (MathType/Office Math) are converted to LaTeX math\n- Quality varies depending on how equations were created in Word\n\n### Common Issues\n\n1. **Complex formatting may not convert perfectly** - manual cleanup often needed\n2. **Track changes are lost** - accept all changes before conversion\n3. **Page numbers/headers/footers** - not preserved, need manual addition\n4. **Custom fonts** - may need manual specification in LaTeX\n\n### Example Workflow\n\n```bash\n# 1. Convert DOCX to LaTeX\npandoc paper.docx -o paper.tex --standalone --extract-media=./figures\n\n# 2. Review and clean up paper.tex\n# 3. Adjust preamble, add packages as needed\n# 4. Compile with pdflatex or lualatex\n```\n\n---\n\n## LaTeX to DOCX\n\nConverting LaTeX to Word is often required for journal submissions that only accept DOCX format or for collaboration with non-LaTeX users.\n\n### Basic Conversion\n\n```bash\npandoc paper.tex -o paper.docx --standalone\n```\n\n### With Bibliography\n\n```bash\npandoc paper.tex -o paper.docx \\\n --bibliography=references.bib \\\n --csl=apa.csl\n```\n\nDownload CSL styles from: https://github.com/citation-style-language/styles\n\n### Preserving Formatting\n\nPandoc converts:\n- `\\section{}` → Heading 1\n- `\\subsection{}` → Heading 2\n- `\\textbf{}` → Bold\n- `\\emph{}` → Italic\n- Math equations → Office Math format\n- Tables → Word tables\n- Figures → Embedded images\n\n### What May Be Lost\n\n- Custom LaTeX commands\n- TikZ diagrams (need to convert to images first)\n- Precise spacing and layout\n- Custom page headers/footers\n- Some advanced math constructs\n\n### Best Practices\n\n1. **Use standard LaTeX commands** - avoid custom macros\n2. **Convert TikZ to images** before running Pandoc\n3. **Test early** - don't wait until submission deadline\n4. **Keep LaTeX as source of truth** - DOCX is for distribution only\n\n### Example: Journal Submission\n\n```bash\n# Convert to DOCX with bibliography\npandoc manuscript.tex -o submission.docx \\\n --bibliography=refs.bib \\\n --csl=ieee.csl \\\n --toc\n\n# Open in Word to:\n# - Verify formatting\n# - Add page numbers\n# - Check that equations rendered correctly\n# - Adjust figure placements\n```\n\n---\n\n## LaTeX to HTML\n\nConverting LaTeX to HTML is useful for web publishing, online documentation, or creating accessible versions of documents.\n\n### Basic Conversion\n\n```bash\npandoc paper.tex -o paper.html --standalone --mathjax\n```\n\nThe `--mathjax` flag enables proper math rendering in browsers.\n\n### With Table of Contents\n\n```bash\npandoc document.tex -o document.html \\\n --standalone \\\n --mathjax \\\n --toc \\\n --toc-depth=3\n```\n\n### MathJax Integration\n\nPandoc automatically includes MathJax for rendering LaTeX math in HTML:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js\">\u003c/script>\n```\n\nMath is preserved in LaTeX syntax and rendered by MathJax:\n\n```html\n\u003cp>The equation is \\(E = mc^2\\).\u003c/p>\n\n\u003cp>\\[\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}\\]\u003c/p>\n```\n\n### Custom CSS Styling\n\n```bash\npandoc paper.tex -o paper.html \\\n --standalone \\\n --mathjax \\\n --css=style.css\n```\n\nExample `style.css`:\n\n```css\nbody {\n font-family: 'Latin Modern Roman', serif;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n line-height: 1.6;\n}\n\nh1, h2, h3 {\n color: #2c3e50;\n}\n\npre {\n background-color: #f4f4f4;\n padding: 10px;\n border-radius: 5px;\n}\n```\n\n### Handling Images\n\nLaTeX `\\includegraphics{}` is converted to HTML `\u003cimg>` tags:\n\n```latex\n\\includegraphics[width=0.5\\textwidth]{figure.png}\n```\n\nBecomes:\n\n```html\n\u003cimg src=\"figure.png\" style=\"width:50%;\" />\n```\n\n### Self-Contained HTML\n\nCreate a single HTML file with embedded images:\n\n```bash\npandoc paper.tex -o paper.html --standalone --mathjax --self-contained\n```\n\nThis embeds images as base64 data URIs.\n\n---\n\n## HTML to LaTeX\n\nConverting HTML to LaTeX is useful when you have web content that needs to be typeset in LaTeX format.\n\n### Basic Conversion\n\n```bash\npandoc webpage.html -o document.tex --standalone\n```\n\n### What Gets Converted\n\n- `\u003ch1>` → `\\section{}`\n- `\u003ch2>` → `\\subsection{}`\n- `\u003cstrong>` → `\\textbf{}`\n- `\u003cem>` → `\\emph{}`\n- `\u003cul>`, `\u003col>` → `itemize`, `enumerate`\n- `\u003ctable>` → `tabular`\n- `\u003cimg>` → `\\includegraphics{}`\n- Math (if using MathJax) → LaTeX math\n\n### Limitations\n\n- CSS styling is not converted\n- JavaScript content is ignored\n- Complex HTML layouts may not translate well\n- Web fonts are not preserved\n\n### Best Practices\n\n1. Clean HTML (remove navigation, ads, etc.) before conversion\n2. Ensure images are accessible via relative paths\n3. Test and manually adjust formatting\n4. May need to restructure for LaTeX document flow\n\n---\n\n## Using convert_document.sh\n\nThe `convert_document.sh` script provides a convenient wrapper around Pandoc with automatic format detection.\n\n### Basic Usage\n\n```bash\n# Markdown to LaTeX\nconvert_document.sh report.md report.tex\n\n# LaTeX to PDF\nconvert_document.sh paper.tex paper.pdf\n\n# DOCX to LaTeX\nconvert_document.sh manuscript.docx manuscript.tex\n```\n\n### With Options\n\n```bash\n# With table of contents\nconvert_document.sh document.md document.tex --toc\n\n# With bibliography\nconvert_document.sh paper.tex paper.pdf \\\n --bibliography=refs.bib \\\n --csl=ieee.csl\n\n# With custom template\nconvert_document.sh report.md report.tex \\\n --template=custom_template.latex \\\n --standalone\n\n# Multiple options\nconvert_document.sh thesis.md thesis.pdf \\\n --toc \\\n --bibliography=references.bib \\\n --csl=chicago.csl \\\n --standalone\n```\n\n### Auto-Detection Examples\n\nThe script automatically detects conversion direction:\n\n```bash\n# .md → .tex (auto-detected)\nconvert_document.sh input.md output.tex\n\n# .tex → .html (auto-detected with MathJax)\nconvert_document.sh input.tex output.html\n\n# .docx → .tex (auto-detected with media extraction)\nconvert_document.sh input.docx output.tex\n```\n\n### Script Features\n\n- **Auto-installs Pandoc** if missing (checks first)\n- **Colored output** for better readability\n- **Error handling** with helpful messages\n- **File size reporting** after conversion\n- **Absolute path output** for easy reference\n\n---\n\n## Common Pitfalls\n\n### 1. Character Encoding Issues\n\n**Problem:** Special characters (é, ñ, 中文) don't display correctly.\n\n**Solution:**\n```bash\n# Ensure UTF-8 encoding\npandoc input.md -o output.tex --standalone\n# Then use lualatex or xelatex instead of pdflatex\nlualatex output.tex\n```\n\nOr specify in LaTeX:\n```latex\n\\usepackage[utf8]{inputenc}\n```\n\n### 2. Image Path Problems\n\n**Problem:** Images don't appear in converted document.\n\n**Solution:**\n- Use relative paths from the document location\n- Extract embedded images: `--extract-media=./media`\n- Verify image files exist at specified paths\n- Copy images to appropriate directory after conversion\n\n### 3. Math Rendering Issues\n\n**Problem:** Math equations don't render or appear as raw LaTeX.\n\n**Solution:**\n- For HTML: Use `--mathjax` flag\n- For DOCX: Ensure Office Math support\n- For LaTeX → MD: Math is preserved as `$... latex-document-skill — Skillopedia \n- Complex math may need manual adjustment\n\n### 4. Bibliography Not Appearing\n\n**Problem:** Citations show as `[@ref]` instead of formatted references.\n\n**Solution:**\n```bash\n# Include bibliography file\npandoc input.md -o output.pdf \\\n --bibliography=refs.bib \\\n --csl=style.csl\n\n# Or use LaTeX's biblatex:\npandoc input.md -o output.tex --biblatex\n# Then compile with biber\n```\n\n### 5. Tables Break Across Pages\n\n**Problem:** Long tables split awkwardly in PDF output.\n\n**Solution:**\n- Use `longtable` package in LaTeX\n- Add to Pandoc template or manually edit\n- Consider rotating wide tables with `rotating` package\n\n### 6. Custom LaTeX Commands Not Recognized\n\n**Problem:** `\\newcommand` definitions cause errors in conversion.\n\n**Solution:**\n- Define commands in Pandoc template\n- Use `--include-in-header=defs.tex`\n- Convert custom commands to standard LaTeX before conversion\n- Use Pandoc filters for complex transformations\n\n---\n\n## Advanced Topics\n\n### Custom Pandoc Templates\n\nCreate a custom LaTeX template for consistent formatting:\n\n```bash\n# Get default template\npandoc -D latex > my_template.latex\n\n# Edit my_template.latex to customize\n# - Add packages\n# - Modify page layout\n# - Change fonts\n# - Add custom commands\n\n# Use template\npandoc input.md -o output.tex --template=my_template.latex\n```\n\n### Pandoc Filters\n\nFilters allow custom transformations during conversion:\n\n**Example:** Convert all `\u003cspan class=\"todo\">` to LaTeX `\\todo{}` commands\n\n```python\n#!/usr/bin/env python3\n# todo_filter.py\nfrom pandocfilters import toJSONFilter, RawInline\n\ndef todo(key, value, format, meta):\n if key == 'Span':\n [[ident, classes, kvs], content] = value\n if 'todo' in classes:\n if format == 'latex':\n return RawInline('latex', '\\\\todo{' +\n str(content) + '}')\n\nif __name__ == \"__main__\":\n toJSONFilter(todo)\n```\n\nUsage:\n```bash\npandoc input.md -o output.tex --filter=./todo_filter.py\n```\n\n### Metadata Blocks\n\nAdd document metadata in Markdown:\n\n```markdown\n---\ntitle: \"My Document Title\"\nauthor: \"John Doe\"\ndate: \"2026-02-15\"\nabstract: \"This is the abstract.\"\nkeywords: [pandoc, conversion, latex]\n---\n\n# Introduction\n\nDocument content here...\n```\n\nPandoc uses this metadata in the generated document.\n\n### Variables for Templates\n\nPass variables to customize output:\n\n```bash\npandoc input.md -o output.pdf \\\n --variable documentclass=report \\\n --variable fontsize=12pt \\\n --variable geometry:margin=1in \\\n --variable colorlinks=true \\\n --variable linkcolor=blue\n```\n\n### Batch Conversion\n\nConvert multiple files:\n\n```bash\n# Convert all .md files to .tex\nfor file in *.md; do\n pandoc \"$file\" -o \"${file%.md}.tex\" --standalone\ndone\n\n# Convert all .tex files to .pdf with bibliography\nfor file in *.tex; do\n pandoc \"$file\" -o \"${file%.tex}.pdf\" \\\n --bibliography=refs.bib \\\n --csl=ieee.csl\ndone\n```\n\n### Combining Documents\n\nConcatenate multiple Markdown files:\n\n```bash\npandoc chapter1.md chapter2.md chapter3.md \\\n -o book.pdf \\\n --toc \\\n --number-sections \\\n --bibliography=refs.bib\n```\n\n---\n\n## Quick Reference\n\n### Common Conversions\n\n| From | To | Command |\n|--------|--------|---------|\n| MD | TEX | `pandoc input.md -o output.tex --standalone` |\n| TEX | MD | `pandoc input.tex -o output.md` |\n| MD | PDF | `pandoc input.md -o output.pdf` |\n| TEX | PDF | `pandoc input.tex -o output.pdf` |\n| DOCX | TEX | `pandoc input.docx -o output.tex --standalone --extract-media=./media` |\n| TEX | DOCX | `pandoc input.tex -o output.docx --bibliography=refs.bib` |\n| TEX | HTML | `pandoc input.tex -o output.html --mathjax --standalone` |\n| HTML | TEX | `pandoc input.html -o output.tex --standalone` |\n\n### Useful Flags\n\n- `--standalone` - Complete document with preamble\n- `--toc` - Include table of contents\n- `--mathjax` - Enable math rendering in HTML\n- `--bibliography=FILE` - Include bibliography\n- `--csl=FILE` - Citation style\n- `--template=FILE` - Custom template\n- `--extract-media=DIR` - Extract embedded images\n- `--self-contained` - Embed images in HTML\n- `--number-sections` - Number sections automatically\n\n### Resources\n\n- **Pandoc Manual**: https://pandoc.org/MANUAL.html\n- **CSL Styles**: https://github.com/citation-style-language/styles\n- **Pandoc Templates**: https://github.com/jgm/pandoc/wiki/User-contributed-templates\n- **Pandoc Filters**: https://pandoc.org/filters.html\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":16901,"content_sha256":"43c9cc6cdaf88a01b10079a81e46ec7cf136a3b8c2aa67e4c21823e2da838f7f"},{"filename":"references/graphviz-plantuml.md","content":"# Graphviz and PlantUML in LaTeX\n\n## Overview\n\n**Graphviz** and **PlantUML** are external diagramming tools that generate high-quality diagrams from text descriptions. Unlike TikZ or pgfplots (which are native LaTeX), these tools process text files externally to create PDF or PNG images that are then included in LaTeX documents via `\\includegraphics`.\n\n### Why Use External Diagram Tools?\n\n**Advantages:**\n- **Automatic layout** - no manual positioning of nodes\n- **Text-based** - version control friendly, easy to diff\n- **Fast prototyping** - quick to write and iterate\n- **Specialized strengths** - each tool excels at specific diagram types\n- **No LaTeX expertise required** - accessible to non-LaTeX users\n\n**Disadvantages:**\n- **Extra build step** - requires preprocessing before LaTeX compilation\n- **External dependency** - need separate tools installed\n- **Less LaTeX integration** - included as images, not native graphics\n- **Limited typography** - can't use LaTeX math directly in diagrams (unless using dot2tex)\n\n### Typical Workflow\n\n```\n1. Write diagram in .dot or .puml file\n ↓\n2. Convert to PDF/PNG using command-line tool\n ↓\n3. Include in LaTeX with \\includegraphics\n ↓\n4. Compile LaTeX document\n```\n\n---\n\n## Graphviz\n\n### What is Graphviz?\n\n**Graphviz** is a graph visualization toolkit that automatically lays out nodes and edges. It excels at:\n- **Directed/undirected graphs** - network topologies, dependencies\n- **State machines** - FSMs, statecharts\n- **Flowcharts** - process flows, decision trees\n- **Data structures** - trees, linked lists\n- **Software architecture** - module dependencies, call graphs\n\n### Layout Engines\n\nGraphviz provides multiple layout engines for different graph types:\n\n| Engine | Best For | Layout Style |\n|--------|----------|-------------|\n| **dot** | Directed graphs, hierarchies | Top-to-bottom or left-to-right |\n| **neato** | Undirected graphs | Spring model (force-directed) |\n| **circo** | Circular layouts | Nodes in circles |\n| **fdp** | Undirected graphs | Force-directed placement |\n| **twopi** | Radial layouts | Nodes radiate from center |\n| **sfdp** | Large graphs (1000+ nodes) | Multiscale force-directed |\n\n### Installation\n\n```bash\n# Debian/Ubuntu\nsudo apt-get install graphviz\n\n# macOS\nbrew install graphviz\n\n# Fedora/RHEL\nsudo dnf install graphviz\n\n# Alpine\nsudo apk add graphviz\n\n# Arch\nsudo pacman -S graphviz\n```\n\nOr use the helper script (auto-installs):\n```bash\ngraphviz_to_pdf.sh diagram.dot\n```\n\n### LaTeX Packages\n\n```latex\n\\usepackage{graphicx} % For \\includegraphics\n\\usepackage{float} % For H placement specifier\n```\n\n---\n\n## Graphviz Examples\n\n### Directed Graph (dot)\n\n**File: `dependency_graph.dot`**\n```dot\ndigraph Dependencies {\n rankdir=LR;\n node [shape=box, style=\"rounded,filled\", fillcolor=lightblue];\n\n main -> parser;\n main -> executor;\n parser -> lexer;\n parser -> ast;\n executor -> ast;\n executor -> runtime;\n runtime -> memory;\n runtime -> gc;\n\n main [fillcolor=lightgreen];\n memory [shape=cylinder, fillcolor=lightyellow];\n gc [shape=cylinder, fillcolor=lightyellow];\n}\n```\n\n**Convert to PDF:**\n```bash\ndot -Tpdf dependency_graph.dot -o dependency_graph.pdf\n# Or use helper script\ngraphviz_to_pdf.sh dependency_graph.dot\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{dependency_graph.pdf}\n \\caption{Module dependency graph showing compilation pipeline}\n \\label{fig:dependencies}\n\\end{figure}\n```\n\n### Undirected Graph (neato)\n\n**File: `network_topology.dot`**\n```dot\ngraph Network {\n layout=neato;\n node [shape=circle, style=filled, fillcolor=lightblue];\n edge [color=gray];\n\n Router [fillcolor=orange, shape=box];\n\n Router -- Switch1;\n Router -- Switch2;\n Switch1 -- PC1;\n Switch1 -- PC2;\n Switch1 -- PC3;\n Switch2 -- PC4;\n Switch2 -- PC5;\n Switch2 -- Printer;\n\n Printer [shape=box, fillcolor=lightgreen];\n}\n```\n\n**Convert:**\n```bash\nneato -Tpdf network_topology.dot -o network_topology.pdf\n# Or\ngraphviz_to_pdf.sh network_topology.dot --engine neato\n```\n\n### State Machine\n\n**File: `order_states.dot`**\n```dot\ndigraph OrderStateMachine {\n rankdir=LR;\n node [shape=circle, style=filled, fillcolor=lightblue];\n\n start [shape=point, width=0.3];\n Pending [fillcolor=lightyellow];\n Processing [fillcolor=lightcyan];\n Shipped [fillcolor=lightgreen];\n Delivered [fillcolor=green, fontcolor=white];\n Cancelled [fillcolor=red, fontcolor=white];\n\n start -> Pending;\n Pending -> Processing [label=\"payment\"];\n Pending -> Cancelled [label=\"cancel\"];\n Processing -> Shipped [label=\"dispatch\"];\n Processing -> Cancelled [label=\"error\"];\n Shipped -> Delivered [label=\"signed\"];\n Delivered -> end;\n Cancelled -> end;\n\n end [shape=doublecircle, width=0.3, fillcolor=gray];\n}\n```\n\n**LaTeX:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=\\textwidth]{order_states.pdf}\n \\caption{Order lifecycle state machine}\n \\label{fig:order-fsm}\n\\end{figure}\n```\n\n### Record Nodes (Data Structures)\n\n**File: `linked_list.dot`**\n```dot\ndigraph LinkedList {\n rankdir=LR;\n node [shape=record, style=filled, fillcolor=lightblue];\n\n node1 [label=\"\u003cdata> 42 | \u003cnext>\"];\n node2 [label=\"\u003cdata> 17 | \u003cnext>\"];\n node3 [label=\"\u003cdata> 89 | \u003cnext>\"];\n null [shape=plaintext, label=\"NULL\"];\n\n node1:next -> node2:data;\n node2:next -> node3:data;\n node3:next -> null;\n\n head [shape=plaintext];\n head -> node1:data [label=\"head pointer\"];\n}\n```\n\n### Cluster (Subgraphs)\n\n**File: `architecture.dot`**\n```dot\ndigraph Architecture {\n rankdir=TB;\n node [shape=box, style=\"rounded,filled\", fillcolor=lightblue];\n\n subgraph cluster_frontend {\n label=\"Frontend Layer\";\n style=filled;\n color=lightgray;\n\n UI [label=\"User Interface\"];\n Router [label=\"Router\"];\n Components [label=\"Components\"];\n }\n\n subgraph cluster_backend {\n label=\"Backend Layer\";\n style=filled;\n color=lightgray;\n\n API [label=\"REST API\"];\n Auth [label=\"Authentication\"];\n Business [label=\"Business Logic\"];\n }\n\n subgraph cluster_data {\n label=\"Data Layer\";\n style=filled;\n color=lightgray;\n\n DB [label=\"Database\", shape=cylinder, fillcolor=lightyellow];\n Cache [label=\"Cache\", shape=cylinder, fillcolor=lightyellow];\n }\n\n UI -> Router -> Components;\n Components -> API;\n API -> Auth;\n API -> Business;\n Business -> DB;\n Business -> Cache;\n}\n```\n\n---\n\n## Graphviz Attributes\n\n### Common Node Shapes\n\n```dot\nnode [shape=box]; // Rectangle\nnode [shape=circle]; // Circle\nnode [shape=ellipse]; // Ellipse (default)\nnode [shape=diamond]; // Diamond (decisions)\nnode [shape=parallelogram]; // Input/Output\nnode [shape=cylinder]; // Database\nnode [shape=folder]; // Directory\nnode [shape=note]; // Document\nnode [shape=component]; // Component box\n```\n\n### Colors and Styles\n\n```dot\nnode [style=filled, fillcolor=lightblue];\nnode [style=\"rounded,filled\", fillcolor=lightgreen];\nnode [color=red, penwidth=2.0];\nedge [color=blue, style=dashed];\nedge [label=\"label text\", fontcolor=red];\n```\n\n### Direction\n\n```dot\nrankdir=TB; // Top to Bottom (default)\nrankdir=LR; // Left to Right\nrankdir=BT; // Bottom to Top\nrankdir=RL; // Right to Left\n```\n\n---\n\n## Converting Graphviz to PDF/PNG\n\n### Command-Line Usage\n\n```bash\n# Basic conversion to PDF\ndot -Tpdf input.dot -o output.pdf\n\n# Convert to PNG\ndot -Tpng input.dot -o output.png\n\n# High-resolution PNG\ndot -Tpng -Gdpi=300 input.dot -o output.png\n\n# Use specific layout engine\nneato -Tpdf graph.dot -o graph.pdf\ncirco -Tpdf graph.dot -o graph.pdf\n```\n\n### Using the Helper Script\n\n```bash\n# Basic usage (defaults: pdf format, dot engine)\ngraphviz_to_pdf.sh diagram.dot\n\n# Specify output file\ngraphviz_to_pdf.sh diagram.dot --output result.pdf\n\n# PNG format\ngraphviz_to_pdf.sh diagram.dot --format png\n\n# Different layout engine\ngraphviz_to_pdf.sh diagram.dot --engine neato\n\n# Batch mode: convert all .dot files in directory\ngraphviz_to_pdf.sh diagrams/ --format pdf\n```\n\n---\n\n## Advanced: dot2tex (Native TikZ Output)\n\n**dot2tex** converts Graphviz to native TikZ code, enabling LaTeX math in nodes.\n\n### Installation\n\n```bash\npip install dot2tex\n```\n\n### Usage\n\n```bash\n# Convert .dot to .tex\ndot2tex -ftikz diagram.dot > diagram.tex\n\n# Include in LaTeX\n\\input{diagram.tex}\n```\n\n### Requires in LaTeX\n\n```latex\n\\usepackage{tikz}\n\\usetikzlibrary{arrows,shapes}\n```\n\n**Note:** Requires `-shell-escape` for LaTeX compilation:\n```bash\npdflatex -shell-escape document.tex\n```\n\n### Inline with dot2texi Package\n\n```latex\n\\usepackage{dot2texi}\n\\usepackage{tikz}\n\\usetikzlibrary{shapes,arrows}\n\n\\begin{dot2tex}[neato]\ngraph G {\n a -- b;\n b -- c;\n c -- a;\n}\n\\end{dot2tex}\n```\n\nThis allows embedding Graphviz directly in LaTeX, but still requires `-shell-escape`.\n\n---\n\n## PlantUML\n\n### What is PlantUML?\n\n**PlantUML** is a text-based UML diagramming tool that generates professional UML diagrams. It excels at:\n- **Sequence diagrams** - API interactions, message flows\n- **Class diagrams** - OOP structure\n- **Use case diagrams** - system requirements\n- **Activity diagrams** - workflows, algorithms\n- **Component diagrams** - system architecture\n- **State diagrams** - state machines\n- **Entity-relationship diagrams** - database schemas\n\n### Installation\n\n```bash\n# Debian/Ubuntu\nsudo apt-get install plantuml\n\n# macOS\nbrew install plantuml\n\n# Fedora/RHEL\nsudo dnf install plantuml\n\n# Manual (requires Java)\nwget https://github.com/plantuml/plantuml/releases/download/v1.2024.8/plantuml-1.2024.8.jar\nalias plantuml='java -jar plantuml.jar'\n```\n\nOr use the helper script (auto-installs):\n```bash\nplantuml_to_pdf.sh diagram.puml\n```\n\n---\n\n## PlantUML Examples\n\n### Sequence Diagram\n\n**File: `api_sequence.puml`**\n```plantuml\n@startuml\nactor User\nparticipant \"Web App\" as Web\nparticipant \"API Server\" as API\ndatabase \"Database\" as DB\n\nUser -> Web: Click \"Login\"\nWeb -> API: POST /auth/login\nactivate API\nAPI -> DB: Query user\nactivate DB\nDB --> API: User record\ndeactivate DB\nAPI -> API: Verify password\nalt Authentication success\n API --> Web: JWT token\n Web --> User: Redirect to dashboard\nelse Authentication failed\n API --> Web: 401 Unauthorized\n Web --> User: Show error\nend\ndeactivate API\n@enduml\n```\n\n**Convert:**\n```bash\nplantuml -tpdf api_sequence.puml\n# Or\nplantuml_to_pdf.sh api_sequence.puml\n```\n\n**LaTeX:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.9\\textwidth]{api_sequence.pdf}\n \\caption{API authentication sequence diagram}\n \\label{fig:api-seq}\n\\end{figure}\n```\n\n### Class Diagram\n\n**File: `class_diagram.puml`**\n```plantuml\n@startuml\nclass User {\n -userId: int\n -email: string\n -passwordHash: string\n +login(): boolean\n +logout(): void\n +updateProfile(): void\n}\n\nclass Order {\n -orderId: int\n -orderDate: DateTime\n -totalAmount: decimal\n -status: OrderStatus\n +calculateTotal(): decimal\n +processPayment(): boolean\n}\n\nclass Product {\n -productId: int\n -name: string\n -price: decimal\n -stockQuantity: int\n +updateStock(qty: int): void\n +getDetails(): ProductInfo\n}\n\nclass OrderItem {\n -quantity: int\n -priceAtPurchase: decimal\n +calculateSubtotal(): decimal\n}\n\nUser \"1\" -- \"0..*\" Order : places\nOrder \"1\" *-- \"1..*\" OrderItem : contains\nProduct \"1\" -- \"0..*\" OrderItem : ordered in\n@enduml\n```\n\n### Activity Diagram\n\n**File: `workflow.puml`**\n```plantuml\n@startuml\nstart\n:Receive request;\nif (Valid input?) then (yes)\n :Process data;\n :Query database;\n if (Record found?) then (yes)\n :Update record;\n else (no)\n :Create new record;\n endif\n :Send success response;\nelse (no)\n :Log error;\n :Send error response;\nendif\nstop\n@enduml\n```\n\n### Component Diagram\n\n**File: `components.puml`**\n```plantuml\n@startuml\npackage \"Frontend\" {\n [UI Components]\n [State Manager]\n [API Client]\n}\n\npackage \"Backend\" {\n [REST API]\n [Business Logic]\n [Data Access]\n}\n\ndatabase \"PostgreSQL\" {\n [Users Table]\n [Orders Table]\n}\n\n[UI Components] --> [State Manager]\n[State Manager] --> [API Client]\n[API Client] ..> [REST API] : HTTP\n[REST API] --> [Business Logic]\n[Business Logic] --> [Data Access]\n[Data Access] --> [Users Table]\n[Data Access] --> [Orders Table]\n@enduml\n```\n\n### State Diagram\n\n**File: `state_machine.puml`**\n```plantuml\n@startuml\n[*] --> Idle\n\nIdle --> Processing : Start\nProcessing --> Success : Complete\nProcessing --> Failed : Error\nFailed --> Processing : Retry\nFailed --> Idle : Cancel\nSuccess --> [*]\n\nProcessing : Entry / Log start\nProcessing : Do / Process data\nProcessing : Exit / Cleanup\n\nFailed : Entry / Log error\n@enduml\n```\n\n### Use Case Diagram\n\n**File: `use_cases.puml`**\n```plantuml\n@startuml\nleft to right direction\nactor Customer\nactor Admin\n\nrectangle \"E-commerce System\" {\n Customer -- (Browse Products)\n Customer -- (Add to Cart)\n Customer -- (Checkout)\n Customer -- (Track Order)\n\n Admin -- (Manage Products)\n Admin -- (Process Orders)\n Admin -- (View Analytics)\n\n (Checkout) .> (Process Payment) : includes\n (Process Orders) .> (Send Notification) : includes\n}\n@enduml\n```\n\n### Entity-Relationship Diagram\n\n**File: `database_schema.puml`**\n```plantuml\n@startuml\nentity User {\n * user_id : int \u003c\u003cPK>>\n --\n email : varchar(255) \u003c\u003cUK>>\n username : varchar(50)\n password_hash : varchar(255)\n created_at : timestamp\n}\n\nentity Post {\n * post_id : int \u003c\u003cPK>>\n --\n * author_id : int \u003c\u003cFK>>\n title : varchar(255)\n content : text\n published_at : timestamp\n is_published : boolean\n}\n\nentity Comment {\n * comment_id : int \u003c\u003cPK>>\n --\n * post_id : int \u003c\u003cFK>>\n * user_id : int \u003c\u003cFK>>\n content : text\n created_at : timestamp\n parent_comment_id : int \u003c\u003cFK>>\n}\n\nentity Tag {\n * tag_id : int \u003c\u003cPK>>\n --\n name : varchar(50) \u003c\u003cUK>>\n slug : varchar(50)\n}\n\nUser ||--o{ Post : \"writes\"\nUser ||--o{ Comment : \"writes\"\nPost ||--o{ Comment : \"has\"\nPost }o--o{ Tag : \"tagged_with\"\nComment }o--o| Comment : \"replies to\"\n@enduml\n```\n\n---\n\n## Converting PlantUML to PDF/PNG\n\n### Command-Line Usage\n\n```bash\n# Convert to PDF (recommended for LaTeX)\nplantuml -tpdf diagram.puml\n\n# Convert to PNG\nplantuml -tpng diagram.puml\n\n# Convert to SVG\nplantuml -tsvg diagram.puml\n\n# High-resolution PNG\nplantuml -tpng -Sresolution=300 diagram.puml\n\n# Batch convert all .puml files\nplantuml -tpdf *.puml\n```\n\n### Using the Helper Script\n\n```bash\n# Basic usage (defaults to PDF)\nplantuml_to_pdf.sh diagram.puml\n\n# Specify output file\nplantuml_to_pdf.sh diagram.puml --output result.pdf\n\n# PNG format\nplantuml_to_pdf.sh diagram.puml --format png\n\n# SVG format\nplantuml_to_pdf.sh diagram.puml --format svg\n\n# Batch mode: convert all .puml files in directory\nplantuml_to_pdf.sh diagrams/ --format pdf\n```\n\n---\n\n## LaTeX Integration Best Practices\n\n### 1. Use PDF Format for Vector Quality\n\nAlways prefer PDF over PNG for scalability:\n```bash\ndot -Tpdf diagram.dot -o diagram.pdf\nplantuml -tpdf diagram.puml\n```\n\n### 2. Organize Diagram Files\n\n```\nproject/\n├── main.tex\n├── diagrams/\n│ ├── source/ # Source files\n│ │ ├── architecture.dot\n│ │ ├── sequence.puml\n│ │ └── states.dot\n│ └── generated/ # Generated PDFs\n│ ├── architecture.pdf\n│ ├── sequence.pdf\n│ └── states.pdf\n└── figures/ # Other images\n```\n\n### 3. Makefile for Automatic Conversion\n\n**File: `Makefile`**\n```makefile\n.PHONY: diagrams clean all\n\nDIAGRAMS_SRC = diagrams/source\nDIAGRAMS_OUT = diagrams/generated\n\nDOT_FILES = $(wildcard $(DIAGRAMS_SRC)/*.dot)\nPUML_FILES = $(wildcard $(DIAGRAMS_SRC)/*.puml)\n\nDOT_PDFS = $(patsubst $(DIAGRAMS_SRC)/%.dot,$(DIAGRAMS_OUT)/%.pdf,$(DOT_FILES))\nPUML_PDFS = $(patsubst $(DIAGRAMS_SRC)/%.puml,$(DIAGRAMS_OUT)/%.pdf,$(PUML_FILES))\n\ndiagrams: $(DOT_PDFS) $(PUML_PDFS)\n\n$(DIAGRAMS_OUT)/%.pdf: $(DIAGRAMS_SRC)/%.dot\n\t@mkdir -p $(DIAGRAMS_OUT)\n\tdot -Tpdf $\u003c -o $@\n\n$(DIAGRAMS_OUT)/%.pdf: $(DIAGRAMS_SRC)/%.puml\n\t@mkdir -p $(DIAGRAMS_OUT)\n\tplantuml -tpdf $\u003c -o $(DIAGRAMS_OUT)\n\nmain.pdf: main.tex diagrams\n\tpdflatex main.tex\n\tpdflatex main.tex\n\nall: main.pdf\n\nclean:\n\trm -f *.aux *.log *.out\n\trm -rf $(DIAGRAMS_OUT)/*.pdf\n```\n\nUsage:\n```bash\nmake diagrams # Generate all diagrams\nmake main.pdf # Compile LaTeX (auto-generates diagrams)\nmake clean # Remove generated files\n```\n\n### 4. Batch Conversion Script\n\n**File: `generate_diagrams.sh`**\n```bash\n#!/bin/bash\nset -e\n\nSRC_DIR=\"diagrams/source\"\nOUT_DIR=\"diagrams/generated\"\nmkdir -p \"$OUT_DIR\"\n\necho \"Converting Graphviz diagrams...\"\nfor dot_file in \"$SRC_DIR\"/*.dot; do\n if [ -f \"$dot_file\" ]; then\n filename=$(basename \"$dot_file\" .dot)\n echo \" $filename.dot -> $filename.pdf\"\n dot -Tpdf \"$dot_file\" -o \"$OUT_DIR/${filename}.pdf\"\n fi\ndone\n\necho \"Converting PlantUML diagrams...\"\nfor puml_file in \"$SRC_DIR\"/*.puml; do\n if [ -f \"$puml_file\" ]; then\n filename=$(basename \"$puml_file\" .puml)\n echo \" $filename.puml -> $filename.pdf\"\n plantuml -tpdf \"$puml_file\" -o \"$(realpath \"$OUT_DIR\")\"\n fi\ndone\n\necho \"Done! Generated diagrams in $OUT_DIR/\"\n```\n\n### 5. LaTeX Figure Environment\n\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{diagrams/generated/architecture.pdf}\n \\caption{System architecture showing component relationships and data flow}\n \\label{fig:architecture}\n\\end{figure}\n\n% Reference in text\nAs shown in Figure~\\ref{fig:architecture}, the system consists of three layers.\n```\n\n### 6. Sizing Options\n\n```latex\n% Fixed width\n\\includegraphics[width=0.8\\textwidth]{diagram.pdf}\n\n% Fixed height\n\\includegraphics[height=10cm]{diagram.pdf}\n\n% Scale\n\\includegraphics[scale=0.75]{diagram.pdf}\n\n% Maximum size (preserves aspect ratio)\n\\includegraphics[width=0.9\\textwidth,height=0.6\\textheight,keepaspectratio]{diagram.pdf}\n\n% Rotate\n\\includegraphics[angle=90,width=\\textwidth]{wide_diagram.pdf}\n```\n\n### 7. Side-by-Side Diagrams\n\n```latex\n\\usepackage{subcaption}\n\n\\begin{figure}[H]\n \\centering\n \\begin{subfigure}[b]{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{before.pdf}\n \\caption{Before refactoring}\n \\label{fig:before}\n \\end{subfigure}\n \\hfill\n \\begin{subfigure}[b]{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{after.pdf}\n \\caption{After refactoring}\n \\label{fig:after}\n \\end{subfigure}\n \\caption{Dependency graph comparison}\n \\label{fig:comparison}\n\\end{figure}\n```\n\n---\n\n## When to Use Which Tool\n\n### Graphviz vs PlantUML vs TikZ\n\n| Aspect | Graphviz | PlantUML | TikZ |\n|--------|----------|----------|------|\n| **Best For** | Graphs, dependencies | UML diagrams | Math diagrams |\n| **Layout** | Automatic | Automatic | Manual |\n| **Learning Curve** | Low | Low | High |\n| **Customization** | Limited | Limited | Full control |\n| **LaTeX Math** | Via dot2tex | No | Native |\n| **Professional UML** | No | Yes | Manual |\n| **Large Graphs** | Excellent | Good | Poor |\n\n### Use Graphviz For:\n- **Dependency graphs** (code modules, build systems)\n- **Network topologies** (servers, routers)\n- **State machines** (FSMs, protocols)\n- **Call graphs** (function relationships)\n- **Data structures** (trees, linked lists)\n- **Automatic layout** is desired\n\n### Use PlantUML For:\n- **UML diagrams** (class, sequence, component)\n- **Software architecture** (component diagrams)\n- **API documentation** (sequence diagrams)\n- **Database schemas** (ER diagrams)\n- **Use cases** (requirements)\n- **Professional UML** is required\n\n### Use TikZ For:\n- **Mathematical diagrams** (geometry, proofs)\n- **Precise control** over every element\n- **LaTeX math** embedded in diagrams\n- **Custom graphics** and illustrations\n- **Perfect alignment** with text\n\n### Hybrid Approach\n\nUse multiple tools in the same document:\n```latex\n\\documentclass{article}\n\\usepackage{graphicx}\n\\usepackage{tikz}\n\n\\begin{document}\n\n% Graphviz: dependency graph\n\\begin{figure}[H]\n \\includegraphics[width=0.8\\textwidth]{dependencies.pdf}\n \\caption{Module dependencies (Graphviz)}\n\\end{figure}\n\n% PlantUML: sequence diagram\n\\begin{figure}[H]\n \\includegraphics[width=0.9\\textwidth]{api_flow.pdf}\n \\caption{API interaction sequence (PlantUML)}\n\\end{figure}\n\n% TikZ: mathematical diagram\n\\begin{figure}[H]\n \\centering\n \\begin{tikzpicture}\n \\draw[->] (0,0) -- (3,0) node[right] {$x$};\n \\draw[->] (0,0) -- (0,3) node[above] {$y$};\n \\draw[blue] (0,0) circle (2);\n \\end{tikzpicture}\n \\caption{Unit circle (TikZ)}\n\\end{figure}\n\n\\end{document}\n```\n\n---\n\n## Troubleshooting\n\n### Graphviz Issues\n\n**Problem:** Graph layout looks cluttered or overlapping.\n\n**Solutions:**\n1. Try different layout engine: `neato`, `fdp`, or `sfdp`\n2. Adjust node spacing: `ranksep=1.5; nodesep=0.75;`\n3. Use `rankdir=LR` instead of `TB` for wide graphs\n4. Increase graph size: `size=\"8,6\";`\n\n**Problem:** Text is too small in PDF.\n\n**Solutions:**\n1. Increase font size: `node [fontsize=14];`\n2. Use higher DPI for PNG: `dot -Tpng -Gdpi=300`\n3. Adjust graph size attribute\n\n### PlantUML Issues\n\n**Problem:** \"Cannot find plantuml.jar\" or \"Java not found\".\n\n**Solutions:**\n1. Install Java: `sudo apt-get install default-jre`\n2. Download PlantUML JAR manually\n3. Use package manager installation\n\n**Problem:** Diagram text is cut off or too small.\n\n**Solutions:**\n1. Use `-Sresolution=300` for higher resolution\n2. Adjust diagram scale in source: `scale 1.5`\n3. Use PDF format instead of PNG\n\n### LaTeX Compilation Issues\n\n**Problem:** `File 'diagram.pdf' not found`.\n\n**Solutions:**\n1. Verify diagram file exists in correct location\n2. Use absolute paths or paths relative to .tex file\n3. Check file extension matches actual format\n4. Run diagram generation script first\n\n**Problem:** Diagram appears pixelated or low quality.\n\n**Solutions:**\n1. Use PDF format instead of PNG\n2. Increase resolution for PNG: `-Gdpi=300` or `-Sresolution=300`\n3. Regenerate diagram with vector output\n\n---\n\n## Helper Scripts Reference\n\n### graphviz_to_pdf.sh\n\n```bash\n# Basic usage\ngraphviz_to_pdf.sh input.dot\n\n# Specify output\ngraphviz_to_pdf.sh input.dot --output result.pdf\n\n# PNG format\ngraphviz_to_pdf.sh input.dot --format png\n\n# Different engine\ngraphviz_to_pdf.sh input.dot --engine neato\n\n# Batch mode\ngraphviz_to_pdf.sh diagrams/ --format pdf\n```\n\nFeatures:\n- Auto-installs Graphviz if missing\n- Supports all layout engines (dot, neato, circo, fdp, twopi, sfdp)\n- Batch processing for directories\n- Input validation\n\n### plantuml_to_pdf.sh\n\n```bash\n# Basic usage\nplantuml_to_pdf.sh diagram.puml\n\n# Specify output\nplantuml_to_pdf.sh diagram.puml --output result.pdf\n\n# PNG format\nplantuml_to_pdf.sh diagram.puml --format png\n\n# SVG format\nplantuml_to_pdf.sh diagram.puml --format svg\n\n# Batch mode\nplantuml_to_pdf.sh diagrams/ --format pdf\n```\n\nFeatures:\n- Auto-installs PlantUML if missing\n- Supports PDF, PNG, SVG formats\n- Batch processing for directories\n- Input validation\n\n---\n\n## External Resources\n\n### Graphviz\n- **Official Documentation**: https://graphviz.org/documentation/\n- **Gallery**: https://graphviz.org/gallery/\n- **Attribute Reference**: https://graphviz.org/doc/info/attrs.html\n- **Node Shapes**: https://graphviz.org/doc/info/shapes.html\n- **dot2tex**: https://dot2tex.readthedocs.io/\n\n### PlantUML\n- **Official Documentation**: https://plantuml.com/\n- **Sequence Diagrams**: https://plantuml.com/sequence-diagram\n- **Class Diagrams**: https://plantuml.com/class-diagram\n- **Activity Diagrams**: https://plantuml.com/activity-diagram-beta\n- **Online Server**: https://www.plantuml.com/plantuml/ (test diagrams online)\n- **Real-World Examples**: https://real-world-plantuml.com/\n\n### LaTeX Integration\n- **graphicx Package**: https://ctan.org/pkg/graphicx\n- **float Package**: https://ctan.org/pkg/float\n- **subcaption Package**: https://ctan.org/pkg/subcaption\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":24196,"content_sha256":"b3e44cf28ef5be4f39b1e25922d2f112392bebc8de4722a176c65dab2a6ee43f"},{"filename":"references/ieee-journal-twocolumn-guide.md","content":"# IEEE Journal Two-Column Typography Guide\n\nTutorial for producing camera-ready IEEE Transactions / Journal articles with the\nofficial `IEEEtran` class. Covers two-column body geometry, single-column vs.\nfull-width floats, math/Unicode handling under XeLaTeX, bibliography format,\nand the conversion path from a Markdown source.\n\n## Table of Contents\n- [When to Use This Guide](#when-to-use-this-guide)\n- [IEEEtran in 30 Seconds](#ieeetran-in-30-seconds)\n- [Document Class Options](#document-class-options)\n- [Page and Body Geometry](#page-and-body-geometry)\n- [Engine Choice: pdflatex vs. xelatex](#engine-choice-pdflatex-vs-xelatex)\n- [Two-Column Float Rules](#two-column-float-rules)\n- [Tables](#tables)\n- [Figures](#figures)\n- [Bibliography](#bibliography)\n- [hyperref Without Colored Boxes](#hyperref-without-colored-boxes)\n- [Markdown to IEEEtran via Pandoc](#markdown-to-ieeetran-via-pandoc)\n- [Compile Sequence](#compile-sequence)\n- [Common Mistakes](#common-mistakes)\n- [Self-Check Before Submission](#self-check-before-submission)\n\n---\n\n## When to Use This Guide\n\nRead this before the user asks for any of:\n- A paper for IEEE Transactions, IEEE Journal, IEEE Access, or any IEEE conference using IEEEtran.\n- \"IEEE format / IEEE typography / IEEE two-column\" applied to an existing draft.\n- Conversion of a Markdown / DOCX manuscript into camera-ready IEEEtran PDF + DOCX dual delivery.\n- A revision round that needs single-source rebuild (edit `.tex`, recompile to PDF, regenerate DOCX from the same MD).\n\nIf the target is a non-IEEE publisher (Springer LNCS, ACM, Elsevier, generic article class), use that publisher's class instead. This guide does not cover those.\n\n---\n\n## IEEEtran in 30 Seconds\n\n`IEEEtran.cls` is the official class shipped by IEEE and packaged in CTAN as\n`ieeetran`. It bakes in:\n\n- A4 / Letter selectable, two-column body, narrow margins (~0.5 in)\n- Title block, author block, IEEE running headers (`\\markboth`)\n- `\\IEEEauthorrefmark`, `\\IEEEmembership`, ORCID / IEEE membership grade glyphs\n- `\\IEEEPARstart` (drop-cap first letter for the first paragraph after the abstract)\n- Auto-numbered figure captions (`Fig. N.`) and table captions (`TABLE N`)\n- A simple `thebibliography` environment that produces IEEE-style numeric refs\n- Strict float rules tuned for two-column journal layout\n\nIt does NOT:\n- Set a typeface (uses Computer Modern by default; you opt-in to Times via `times` or `fontspec`)\n- Provide bib styles (use `\\bibliographystyle{IEEEtran}` if you keep BibTeX)\n- Support arbitrary Unicode under pdflatex (must switch to xelatex for Greek, em-dash, math symbols in body text)\n\nCTAN install (MiKTeX): `mpm.exe --install=ieeetran` — installs to\n`\u003cMiKTeX>/tex/latex/ieeetran/IEEEtran.cls`.\n\nCTAN install (TeX Live): `tlmgr install ieeetran`.\n\n---\n\n## Document Class Options\n\n```latex\n\\documentclass[journal,10pt]{IEEEtran}\n```\n\nCommon option set:\n\n| Option | Effect | When to use |\n|---|---|---|\n| `journal` | Two-column journal layout (Transactions, Access) | Default for TIFS, TPAMI, TKDE, TNNLS |\n| `conference` | Two-column conference layout, no running head | ICIP, INFOCOM, ICASSP camera-ready |\n| `technote` | Brief / correspondence layout | TIE Technote, IES Letter |\n| `10pt` / `11pt` | Body font size | `10pt` is the IEEE journal default |\n| `letterpaper` / `a4paper` | Page size | Letter for US journals; A4 if explicitly required |\n| `draft` / `final` | Show / hide overfull rules and timestamp | `final` for camera-ready |\n| `nofonttune` | Disable IEEEtran's micro font tweaks | Only when fontspec sets a custom font |\n\nAvoid `peerreview` and `peerreviewca` unless the journal explicitly requests them; they collapse to single-column manuscript style which defeats the two-column claim.\n\n---\n\n## Page and Body Geometry\n\nTrust the class. Do **not** load `geometry` to override margins. IEEEtran's\ndefaults are validated by IEEE's production system; any geometry change risks\ndesk rejection on layout grounds.\n\nTwo-column body:\n- Column width ≈ 3.5 in (Letter) / 88.9 mm (A4)\n- Column gutter ≈ 0.17 in (12 pt)\n- Body height ≈ 9.25 in\n- All floats default to top-of-column / top-of-page\n\nWhenever you write `\\textwidth` in a single-column scope, you are addressing the\nnarrow column width. Whenever you write `\\textwidth` inside a `figure*` /\n`table*` (full-page float), you are addressing the full page text width\n(both columns + gutter, ≈ 7.16 in).\n\n---\n\n## Engine Choice: pdflatex vs. xelatex\n\nUse **xelatex** when any of the following appear in the manuscript body:\n- Greek letters in non-math context (`τ`, `λ`, `μ`)\n- Em-dashes (`—`), en-dashes (`–`), curly quotes (`\"\"`)\n- Any non-ASCII glyph (`±`, `×`, `•`)\n- Author names with diacritics (`ñ`, `é`, `ø`)\n- IPA, CJK, RTL, Cyrillic\n\nOtherwise pdflatex compiles slightly faster and yields smaller PDFs.\n\nMinimal xelatex preamble snippet for Times-style typeface:\n\n```latex\n\\documentclass[journal,10pt]{IEEEtran}\n\\usepackage{cite}\n\\usepackage{amsmath,amssymb,amsfonts}\n\\usepackage{graphicx}\n\\usepackage{textcomp}\n\\usepackage{xcolor}\n\\usepackage{array}\n\\usepackage{booktabs}\n\\usepackage[hidelinks]{hyperref}\n\\usepackage{fontspec}\n\\usepackage{unicode-math}\n\\setmainfont{Times New Roman}\n\\setmathfont{Latin Modern Math}\n```\n\n---\n\n## Two-Column Float Rules\n\nThis is the single most common source of camera-ready layout problems.\n\n### Rule 1: Default to single-column floats\n\nUse `figure` and `table` (no star). They occupy one column. The text flows\naround them in the other column. This is what the journal expects.\n\n```latex\n\\begin{figure}[!t]\n \\centering\n \\includegraphics[width=\\columnwidth,keepaspectratio]{system-overview.png}\n \\caption{System overview.}\n \\label{fig:overview}\n\\end{figure}\n```\n\nNote `\\columnwidth` (≈ 3.5 in), not `\\textwidth`.\n\n### Rule 2: Use full-width floats only when content genuinely does not fit\n\n`figure*` and `table*` span both columns. Reserve them for:\n- Wide block diagrams with ≥ 4 horizontal stages\n- Tables with > 5 columns or with a column whose text routinely exceeds 25 characters\n- Comparison matrices with ≥ 5 method rows\n\nWrong default:\n```latex\n% Pulling a small 3-column table into table* is wasteful and ugly\n\\begin{table*}[!t] ... \\end{table*}\n```\n\nRight default:\n```latex\n\\begin{table}[!t] ... \\end{table} % start here\n\\begin{table*}[!t] ... \\end{table*} % only if it overflows the column\n```\n\n### Rule 3: `longtable` is incompatible with two-column journal layout\n\n`longtable` cannot float inside a two-column body. If pandoc emits a\n`longtable`, convert it to a fixed-size `tabular` inside `table` (or `table*`\nwhen wide). Keep the body short enough to fit one float; if it spills across\nmultiple pages, refactor the data.\n\n### Rule 4: Place at column / page top, not inline\n\nUse `[!t]` placement. Do not use `[H]` (`float` package's \"here\") inside a\njournal layout — it forces inline placement and breaks two-column balance.\nInline TikZ diagrams should be wrapped in `figure[!t]` like any other figure.\n\n---\n\n## Tables\n\n### Single-column table template\n\n```latex\n\\begin{table}[!t]\n \\renewcommand{\\arraystretch}{1.1}\n \\setlength{\\tabcolsep}{2pt}\n \\caption{Comparison of Methods on Benchmark X}\n \\label{tab:methods}\n \\centering\n \\scriptsize\n \\begin{tabular}{@{}>{\\raggedright\\arraybackslash}p{0.22\\columnwidth}\n >{\\raggedright\\arraybackslash}p{0.30\\columnwidth}\n >{\\raggedleft\\arraybackslash}p{0.18\\columnwidth}\n >{\\raggedleft\\arraybackslash}p{0.18\\columnwidth}@{}}\n \\toprule\n Method & Configuration & Metric A & Metric B \\\\\n \\midrule\n Ours & default + tweak X & 0.812 & 0.745 \\\\\n Baseline-1 & paper-reported & 0.643 & 0.589 \\\\\n Baseline-2 & re-implemented & 0.701 & 0.612 \\\\\n \\bottomrule\n \\end{tabular}\n\\end{table}\n```\n\nKey points:\n- `\\scriptsize` because column width is narrow; without it, content wraps to 3+ lines\n- `\\setlength{\\tabcolsep}{2pt}` reduces inter-column padding from default 6pt\n- `p{}` columns wrap text instead of overflowing; widths sum to ~0.88 of `\\columnwidth` to leave breathing room\n- `\\raggedright` for label columns, `\\raggedleft` for numeric columns\n- IEEEtran auto-prepends the label — do **not** write `TABLE I` inside `\\caption`\n\n### Full-width table\n\nSwitch `table` → `table*` and replace `\\columnwidth` with `\\textwidth`. Bump\n`\\scriptsize` to `\\footnotesize` because the row is wider.\n\n### Caption typography\n\nIEEE captions are uppercase Roman headers (`TABLE I`) followed by a\nsentence-case title underneath. IEEEtran handles this automatically when you\nwrite `\\caption{Comparison ...}` — never include \"TABLE N\" in the caption text.\n\n---\n\n## Figures\n\n### Single-column figure (default)\n\n```latex\n\\begin{figure}[!t]\n \\centering\n \\includegraphics[width=\\columnwidth,keepaspectratio]{pipeline.png}\n \\caption{Five-stage pipeline. Inputs flow left-to-right through the encoder, fusion head, and predictor.}\n \\label{fig:pipeline}\n\\end{figure}\n```\n\n### Full-width figure\n\n```latex\n\\begin{figure*}[!t]\n \\centering\n \\includegraphics[width=\\textwidth,keepaspectratio]{architecture-wide.png}\n \\caption{Full system architecture across seven processing stages.}\n \\label{fig:arch}\n\\end{figure*}\n```\n\n### Sub-figures\n\n```latex\n\\usepackage{subcaption}\n...\n\\begin{figure}[!t]\n \\centering\n \\begin{subfigure}{0.48\\columnwidth}\n \\includegraphics[width=\\linewidth]{a.png}\n \\caption{Phase A.}\\label{fig:a}\n \\end{subfigure}\\hfill\n \\begin{subfigure}{0.48\\columnwidth}\n \\includegraphics[width=\\linewidth]{b.png}\n \\caption{Phase B.}\\label{fig:b}\n \\end{subfigure}\n \\caption{Two phases of the experiment.}\n \\label{fig:phases}\n\\end{figure}\n```\n\n### Caption typography\n\nIEEEtran auto-prepends `Fig. N.`. Caption text is sentence-case starting with a capital. Do **not** write `Fig. 5.` inside `\\caption{...}` — you will get `Fig. 5. Fig. 5. ...`.\n\n---\n\n## Bibliography\n\nIEEEtran ships with a built-in bibliography style. Two viable paths:\n\n### Path A: Hand-written `thebibliography`\n\n```latex\n\\begin{thebibliography}{99}\n\\bibitem{ref1} A.~Author and B.~Author, ``Paper title,'' \\emph{IEEE Trans. X}, vol.~10, no.~2, pp.~100--110, 2024, doi: 10.1109/EXAMPLE.2024.123.\n\\bibitem{ref2} C.~Author, ``Conference paper,'' in \\emph{Proc. ABC Conf.}, 2023, pp.~1--8.\n\\end{thebibliography}\n```\n\nUse this when you have a small, fixed reference list (≤ 20 entries) and want full control.\n\n### Path B: BibTeX with IEEEtran style\n\n```latex\n\\bibliographystyle{IEEEtran}\n\\bibliography{refs}\n```\n\nRun `bibtex paper` between two `xelatex` passes. Use this when references are\nmanaged in a `.bib` file (e.g. exported from Zotero / Mendeley).\n\n### IEEE reference format requirements\n\n- Authors: `F.~M.~Last` (initial-period-tilde-initial pattern, never spelled-out first names)\n- Journal name: italic, abbreviated per IEEE Reference Guide\n- Volume / number / page range: `vol.~10, no.~2, pp.~100--110`\n- Month and year (when available): `Jun.~2024`\n- DOI as final field: `doi: 10.1109/...`\n- Conference: `in \\emph{Proc. ...}`, year, page range\n- Use `--` for page ranges (en-dash), not single hyphen\n- ASCII straight quotes in `.tex` source render as smart quotes only if `\\usepackage{csquotes}` or curly Unicode quotes are explicitly written\n\n---\n\n## hyperref Without Colored Boxes\n\nDefault hyperref draws colored frames around `\\cite`, `\\ref`, and URL hyperlinks.\nThis violates the IEEE camera-ready requirement that links must not be visually\ndistinguishable in the printed PDF.\n\n```latex\n\\usepackage[hidelinks]{hyperref}\n```\n\n`hidelinks` removes both color and frame on every link. Equivalent long form:\n\n```latex\n\\hypersetup{colorlinks=false,pdfborder={0 0 0}}\n```\n\nVerify by rendering the PDF and inspecting any `[1]` citation: the bracketed\nnumber must be the same color as body text, with no surrounding rectangle.\n\n---\n\n## Markdown to IEEEtran via Pandoc\n\nPandoc emits generic LaTeX. It does not produce IEEEtran-shaped output by\nitself. The two-stage pattern:\n\n```bash\n# Stage 1: Markdown -> intermediate LaTeX body\npandoc paper.md -o body.tex \\\n --from='markdown+tex_math_dollars+pipe_tables+yaml_metadata_block' \\\n --to=latex --wrap=preserve\n\n# Stage 2: post-process body.tex into IEEEtran-shaped paper.tex\npython build_ieee_latex.py\n```\n\nThe post-processor (sample template available; adapt per project):\n1. Reads the first `\\section` as the manuscript title; re-emits as `\\title{...}`\n2. Captures `\\textbf{Abstract}---...` and `\\textbf{Index Terms}---...` blocks; re-emits as `\\begin{abstract}...\\end{abstract}` and `\\begin{IEEEkeywords}...\\end{IEEEkeywords}`\n3. Promotes pandoc heading levels by one (level-2 `\\subsection` → IEEEtran `\\section`, level-3 `\\subsubsection` → `\\subsection`); strips numeric prefixes (`I.`, `A.`) that the source kept for visual reference\n4. Converts pandoc `longtable` into bounded `tabular` with explicit `p{}` widths\n5. Converts pandoc `\\textbf{Fig. N.} caption` paragraphs into `\\caption{...}` inside the preceding `figure` environment (and removes the now-orphan caption paragraph)\n6. Rewrites pandoc citation form `{[}N{]}` into `\\cite{refN}` keys\n\nThis pattern preserves single-source authoring (Markdown) while producing\ncamera-ready IEEEtran output. Edit the Markdown for content; rerun the\npipeline for PDF; pandoc + a docx reference template for the editable DOCX.\n\n---\n\n## Compile Sequence\n\nxelatex needs three passes for stable cross-references and TOC, four if you\nclear `.aux` between runs:\n\n```bash\nxelatex -interaction=nonstopmode paper.tex\nxelatex -interaction=nonstopmode paper.tex\nxelatex -interaction=nonstopmode paper.tex\n```\n\nIf switching engines or modifying the bibliography, delete `paper.aux paper.log paper.out paper.toc paper.bbl` first. The IEEEtran built-in bibliography does not need `bibtex`; the BibTeX path needs:\n\n```bash\nxelatex paper.tex\nbibtex paper\nxelatex paper.tex\nxelatex paper.tex\n```\n\nInspect the log for:\n- `LaTeX Warning: Citation 'refX' undefined` — bibitem missing or label mismatch\n- `Overfull \\hbox (... too wide)` — column overflow; tighten table widths or rewrap a long inline `\\texttt{...}` token\n- `LaTeX Font Warning: Font shape 'TU/ptm/...' undefined` — harmless when fontspec is the active font driver; fontspec serves the actual glyph\n\n---\n\n## Common Mistakes\n\n| Mistake | Symptom | Fix |\n|---|---|---|\n| `\\begin{table*}` for a 3-column 4-row table | Table spans both columns, surrounded by white space, looks lonely | Use `\\begin{table}` |\n| `\\includegraphics[width=\\textwidth]` in a `figure` (not `figure*`) | Figure overflows column into the gutter | Use `\\columnwidth` for `figure`, `\\textwidth` only for `figure*` |\n| `[H]` placement inside two-column body | Float forces inline placement, breaks balance | Use `[!t]` |\n| `longtable` left untouched after pandoc | `! Package longtable Error: longtable not in 1-column mode` | Convert to `tabular` inside `table` / `table*` |\n| `\\caption{Fig. 5. Pipeline...}` | Output reads `Fig. 5. Fig. 5. Pipeline...` | Caption text only; let IEEEtran prepend the label |\n| Manuscript with `τ` or `—` compiled with pdflatex | `! Package inputenc Error: Unicode character ... not set up` | Switch to xelatex + `\\usepackage{fontspec}` |\n| `\\usepackage{geometry}` overriding margins | IEEE production rejects on layout audit | Remove; trust IEEEtran defaults |\n| `hyperref` without `hidelinks` | Colored boxes around every `[N]` citation | `\\usepackage[hidelinks]{hyperref}` |\n| Including `TABLE I` in `\\caption{}` text | Output reads `TABLE I TABLE I Comparison...` | Caption text only |\n| Author block with full first name \"John Michael Smith\" | IEEE format requires `J.~M.~Smith` | Use initials with tilde for non-breaking space |\n\n---\n\n## Self-Check Before Submission\n\nRender the PDF and walk every page once:\n\n1. **Page 1**: Title centered, authors centered below, abstract italic single-column-equivalent block, Index Terms italic, then `I. Introduction` heading marks the start of two-column body.\n2. **Every figure**: Caption reads `Fig. N. \u003ctext>` exactly once. No green / red / blue boxes around any reference or URL. Figure does not exceed its column except `figure*` floats.\n3. **Every table**: Caption reads `TABLE N` then sentence-case title on next line. No column overflow into the gutter or right margin. Numeric columns right-aligned.\n4. **Citations**: Every `[N]` resolves to a `\\bibitem` (no `[?]` artifacts). Reference list at end is in IEEE numeric order, formatted with abbreviated journal names and DOI.\n5. **Running header**: `IEEE TRANSACTIONS ON ...` appears top of every page from page 2 onward; page numbers in expected position.\n6. **Page count**: Within journal limit (typically 12–14 for Transactions; 6–8 for letters/correspondence).\n7. **Overfull warnings**: Open `paper.log`; any `Overfull \\hbox > 5pt` in body text is visible; tighten table widths or break long inline tokens. Sub-5pt overfull is generally acceptable.\n8. **Anonymity** (double-blind submission): Author block reads `Anonymous Author`, no acknowledgements, no GitHub URLs revealing identity, all `\\cite{self}` self-references paraphrased as third-person.\n\nWhen all eight checks pass, the manuscript is camera-ready.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":17192,"content_sha256":"31260b6ca1cbc52e5d4e4dba6f76cb7bdaa962bb8fe3169778a6429fc7d5d1b0"},{"filename":"references/interactive-features.md","content":"# Interactive & Dynamic Content Features\n\n## 1. Fillable PDF Forms (hyperref)\n\nCreate fillable PDF forms with text inputs, checkboxes, radio buttons, dropdowns, and push buttons using the `hyperref` package's form field commands.\n\n### Setup\n\n```latex\n\\usepackage[colorlinks=true]{hyperref}\n\n% Wrap ALL form fields in the Form environment\n\\begin{Form}\n % ... form fields here ...\n\\end{Form}\n```\n\n**PDF Viewer Compatibility:**\n| Feature | Adobe Reader | Chrome/Edge | Firefox | Preview (macOS) | Evince |\n|---|---|---|---|---|---|\n| Text fields | Full | Full | Full | Partial | Partial |\n| Checkboxes | Full | Full | Full | Yes | Yes |\n| Radio buttons | Full | Full | Partial | No | Partial |\n| Dropdowns | Full | Full | Full | No | Partial |\n| JavaScript | Full | No | No | No | No |\n| Submit/Reset | Full | No | No | No | No |\n\n**Recommendation:** For maximum compatibility, use text fields and checkboxes. For JavaScript-dependent features (calculations, validation), document that Adobe Reader is required.\n\n### Text Fields\n\n```latex\n% Basic text field\n\\TextField[name=fieldName, width=10cm]{Label Text}\n\n% All options\n\\TextField[\n name=email, % Unique field name (required)\n width=10cm, % Field width\n height=0.6cm, % Field height\n bordercolor=blue, % Border color\n backgroundcolor={0.95 0.95 1.0}, % Background (RGB 0-1)\n charsize=10pt, % Font size inside field\n maxlen=50, % Maximum characters\n value={Default Text}, % Default value\n readonly=true, % Read-only field\n align=1, % 0=left, 1=center, 2=right\n multiline=true, % Multi-line text area\n]{Email:}\n\n% Multi-line text area\n\\TextField[name=comments, width=\\textwidth, height=3cm, multiline=true,\n bordercolor={0.4 0.5 0.7}, backgroundcolor={0.94 0.96 1.0},\n charsize=10pt]{Comments:}\n\n% Password field (characters shown as dots)\n\\TextField[name=password, width=6cm, password=true]{Password:}\n```\n\n### Checkboxes\n\n```latex\n% Basic checkbox\n\\CheckBox[name=agree]{I agree to terms}\n\n% Styled checkbox\n\\CheckBox[\n name=newsletter,\n width=12pt,\n height=12pt,\n bordercolor=blue,\n backgroundcolor={0.95 0.95 1.0},\n checked=true, % Pre-checked\n]{Subscribe to newsletter}\n```\n\n### Radio Buttons\n\n```latex\n% Radio button group (same name = mutually exclusive)\n\\ChoiceMenu[name=experience, radio,\n bordercolor=blue,\n backgroundcolor={0.95 0.95 1.0}]{}\n {0--2 years, 3--5 years, 6--10 years, 10+ years}\n```\n\n### Dropdown Menus (Combo Boxes)\n\n```latex\n% Basic dropdown\n\\ChoiceMenu[name=country, combo, width=6cm,\n bordercolor=blue,\n backgroundcolor={0.95 0.95 1.0}]{}\n {Select..., United States, Canada, United Kingdom, Germany, France, Other}\n\n% List box (multiple visible options)\n\\ChoiceMenu[name=skills, width=6cm, height=3cm,\n bordercolor=blue,\n backgroundcolor={0.95 0.95 1.0}]{}\n {Python, JavaScript, C++, Java, Rust, Go}\n```\n\n### Push Buttons\n\n```latex\n% Reset button (clears all fields)\n\\PushButton[name=resetBtn,\n bordercolor=red,\n backgroundcolor={1.0 0.9 0.9}]{Reset Form}\n\n% Print button\n\\PushButton[name=printBtn,\n bordercolor=blue,\n backgroundcolor={0.9 0.9 1.0}]{Print Form}\n```\n\n### Layout Best Practices\n\nUse `tabularx` for aligned two-column form layouts:\n\n```latex\n\\begin{tabularx}{\\textwidth}{@{}XX@{}}\n \\textbf{First Name:}\\newline\n \\TextField[name=first, width=\\linewidth, bordercolor=blue,\n backgroundcolor={0.94 0.96 1.0}]{} &\n \\textbf{Last Name:}\\newline\n \\TextField[name=last, width=\\linewidth, bordercolor=blue,\n backgroundcolor={0.94 0.96 1.0}]{} \\\\[12pt]\n \\textbf{Email:}\\newline\n \\TextField[name=email, width=\\linewidth, bordercolor=blue,\n backgroundcolor={0.94 0.96 1.0}]{} &\n \\textbf{Phone:}\\newline\n \\TextField[name=phone, width=\\linewidth, bordercolor=blue,\n backgroundcolor={0.94 0.96 1.0}]{} \\\\\n\\end{tabularx}\n```\n\n### Custom Helper Commands\n\nDefine reusable form field commands to keep templates clean:\n\n```latex\n% In preamble:\n\\newcommand{\\FormField}[3][10cm]{%\n \\noindent\\textbf{#2:}\\hspace{0.5em}%\n \\TextField[name=#3, width=#1, bordercolor={0.4 0.5 0.7},\n backgroundcolor={0.94 0.96 1.0}, charsize=10pt]{}%\n \\par\\vspace{6pt}}\n\n\\newcommand{\\FormTextArea}[4][10cm]{%\n \\noindent\\textbf{#2:}\\\\[4pt]%\n \\TextField[name=#3, width=#1, height=#4, multiline=true,\n bordercolor={0.4 0.5 0.7}, backgroundcolor={0.94 0.96 1.0},\n charsize=10pt]{}%\n \\par\\vspace{6pt}}\n\n\\newcommand{\\FormCheck}[2]{%\n \\CheckBox[name=#2, bordercolor={0.4 0.5 0.7},\n backgroundcolor={0.94 0.96 1.0},\n width=12pt, height=12pt]{#1}\\hspace{0.3em}}\n\n% Usage:\n\\FormField{Full Name}{fullName}\n\\FormField[15cm]{Email Address}{email}\n\\FormTextArea[\\textwidth]{Cover Letter}{coverLetter}{4cm}\n\\FormCheck{I accept the terms}{acceptTerms}\n```\n\n### Common Pitfalls\n\n1. **Missing `\\begin{Form}`**: All form fields MUST be inside `\\begin{Form}...\\end{Form}`.\n2. **Duplicate field names**: Each `name=` must be unique within the document. Duplicate names cause fields to sync (which may be desirable for repeated fields, but usually isn't).\n3. **Field names with spaces**: Use camelCase or underscores. Spaces in names cause issues.\n4. **`backgroundcolor` syntax**: Uses space-separated RGB values 0-1, NOT the same as `xcolor` syntax. Use `backgroundcolor={0.94 0.96 1.0}` not `backgroundcolor=blue!10`.\n5. **Forms + tikzposter**: Form fields do NOT work inside `tikzposter` class. Use `article` or `report` class.\n6. **Tab order**: PDF form tab order follows the order fields appear in the LaTeX source. Plan your layout accordingly.\n\n### Template\n\nSee `assets/templates/fillable-form.tex` for a complete working example with all field types.\n\n---\n\n## 2. Conditional Content (Template Variables & Toggles)\n\nControl document content, sections, and visual style through a configuration block at the top of the document. Uses `etoolbox` toggles for boolean features and `\\providecommand` for template variables.\n\n### Setup\n\n```latex\n\\usepackage{etoolbox} % For \\newtoggle, \\iftoggle, \\ifdefstring\n\\usepackage{comment} % For excluding large blocks (optional)\n```\n\n### Boolean Toggles (Show/Hide Sections)\n\n```latex\n% === Define toggles ===\n\\newtoggle{showAppendix}\n\\newtoggle{showWatermark}\n\\newtoggle{isDraft}\n\\newtoggle{isConfidential}\n\\newtoggle{showTOC}\n\\newtoggle{showAbstract}\n\n% === Set toggles ===\n\\toggletrue{showAppendix}\n\\toggletrue{showTOC}\n\\togglefalse{showWatermark}\n\\togglefalse{isDraft}\n\\togglefalse{isConfidential}\n\\toggletrue{showAbstract}\n\n% === Use in document body ===\n\\iftoggle{showTOC}{\n \\tableofcontents\n \\newpage\n}{}\n\n\\iftoggle{showAbstract}{\n \\begin{abstract}\n This document covers...\n \\end{abstract}\n}{}\n\n% ... main content ...\n\n\\iftoggle{showAppendix}{\n \\appendix\n \\section{Supplementary Data}\n ...\n}{}\n```\n\n### Template Variables\n\n```latex\n% === Define with defaults (providecommand won't override if already defined) ===\n\\providecommand{\\doctitle}{Default Title}\n\\providecommand{\\docauthor}{Author Name}\n\\providecommand{\\docdate}{\\today}\n\\providecommand{\\docversion}{1.0}\n\\providecommand{\\orgname}{Organization}\n\n% === Use in document ===\n\\title{\\doctitle}\n\\author{\\docauthor}\n\\date{\\docdate}\n\n% === Override from command line (CI/CD) ===\n% pdflatex \"\\def\\doctitle{Custom Title}\\def\\docversion{2.0}\\input{document.tex}\"\n```\n\n### Visual Profiles (Style Switching)\n\n```latex\n\\providecommand{\\docprofile}{corporate} % corporate | academic | minimal\n\n% Apply profile-specific settings\n\\makeatletter\n\\ifdefstring{\\docprofile}{corporate}{%\n \\definecolor{primaryColor}{RGB}{0, 51, 102}\n \\titleformat{\\section}{\\Large\\bfseries\\color{primaryColor}}{\\thesection}{1em}{}\n}{}\n\\ifdefstring{\\docprofile}{academic}{%\n \\definecolor{primaryColor}{RGB}{100, 30, 30}\n \\usepackage{palatino}\n \\titleformat{\\section}{\\Large\\bfseries}{\\thesection}{1em}{}\n}{}\n\\ifdefstring{\\docprofile}{minimal}{%\n \\definecolor{primaryColor}{RGB}{40, 40, 40}\n \\titleformat{\\section}{\\large\\bfseries}{\\thesection}{1em}{}\n \\geometry{margin=1.2in}\n}{}\n\\makeatother\n```\n\n### Conditional Packages\n\n```latex\n% Only load watermark package if needed\n\\iftoggle{showWatermark}{\n \\usepackage{draftwatermark}\n \\SetWatermarkText{\\watermarktext}\n \\SetWatermarkScale{1.5}\n \\SetWatermarkColor[gray]{0.85}\n}{}\n\n% Draft mode: add line numbers\n\\iftoggle{isDraft}{\n \\usepackage{lineno}\n \\linenumbers\n}{}\n```\n\n### Command-Line Variable Passing\n\nFor CI/CD or batch processing, pass variables at compile time:\n\n```bash\n# Override single variable\npdflatex \"\\def\\doctitle{Annual Report 2025}\\input{template.tex}\"\n\n# Override multiple variables\npdflatex \"\\def\\doctitle{Q4 Report}\\def\\docauthor{CFO}\\def\\docprofile{corporate}\\input{template.tex}\"\n\n# Toggle a feature on\npdflatex \"\\def\\showdraft{true}\\input{template.tex}\"\n```\n\nIn the template, handle command-line overrides:\n\n```latex\n% Check if variable was passed from command line\n\\ifdefined\\showdraft\n \\toggletrue{isDraft}\n\\fi\n```\n\n### Template\n\nSee `assets/templates/conditional-document.tex` for a complete working example with toggles, variables, and visual profiles.\n\n---\n\n## 3. Mail Merge (Batch Personalized Documents)\n\nGenerate N personalized documents from a CSV or JSON data source. The `mail_merge.py` script reads a LaTeX template with placeholders and a data file, renders one document per record, and optionally compiles all to PDF.\n\n### Quick Start\n\n```bash\n# Basic mail merge from CSV\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv --output-dir ./outputs\n\n# With compilation\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv \\\n --output-dir ./outputs \\\n --compile-script \u003cskill_path>/scripts/compile_latex.sh\n\n# Parallel compilation (4 workers)\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv \\\n --output-dir ./outputs --workers 4 \\\n --compile-script \u003cskill_path>/scripts/compile_latex.sh\n\n# Merge all PDFs into one\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv \\\n --output-dir ./outputs --merge --merge-name all_letters.pdf \\\n --compile-script \u003cskill_path>/scripts/compile_latex.sh\n\n# Custom output naming\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv \\\n --output-dir ./outputs --name-field \"last_name\" --prefix \"letter\"\n\n# Dry run (preview what will be generated)\npython3 \u003cskill_path>/scripts/mail_merge.py template.tex data.csv --dry-run\n```\n\n### Template Syntax\n\n#### Simple Mode (default) -- `{{variable}}` placeholders\n\n```latex\n\\documentclass{article}\n\\begin{document}\n\nDear {{name}},\n\nWe are pleased to inform you that your application for the {{position}}\nrole at {{company}} has been approved.\n\nYour start date is {{start_date}}.\n\nSincerely,\\\\\nHR Department\n\n\\end{document}\n```\n\n#### Advanced Mode (Jinja2) -- `\u003c\u003c >>` variables, `\u003c% %>` blocks\n\nFor conditionals, loops, and complex logic. Auto-detected when `\u003c%` or `\u003c\u003c` appears in template.\n\n```latex\n\\documentclass{article}\n\\begin{document}\n\nDear \u003c\u003c name >>,\n\n\u003c% if position == \"Manager\" %>\nAs a new manager, you will receive the leadership training package.\n\u003c% else %>\nWelcome to the team! Your orientation is scheduled for \u003c\u003c start_date >>.\n\u003c% endif %>\n\n\u003c% if items %>\nYour assigned equipment:\n\\begin{itemize}\n\u003c% for item in items %>\n \\item \u003c\u003c item >>\n\u003c% endfor %>\n\\end{itemize}\n\u003c% endif %>\n\n\\end{document}\n```\n\n### Data Source Formats\n\n#### CSV\n\n```csv\nname,title,company,position,start_date\nJohn Smith,Mr.,Acme Inc,Senior Engineer,2025-03-01\nJane Doe,Ms.,TechCorp,Product Manager,2025-03-15\n```\n\n#### JSON (array of objects)\n\n```json\n[\n {\n \"name\": \"John Smith\",\n \"title\": \"Mr.\",\n \"company\": \"Acme Inc\",\n \"position\": \"Senior Engineer\",\n \"start_date\": \"2025-03-01\"\n },\n {\n \"name\": \"Jane Doe\",\n \"title\": \"Ms.\",\n \"company\": \"TechCorp\",\n \"position\": \"Product Manager\",\n \"start_date\": \"2025-03-15\"\n }\n]\n```\n\n#### JSON with nested data (Jinja2 mode required)\n\n```json\n[\n {\n \"name\": \"John Smith\",\n \"address\": {\n \"street\": \"123 Main St\",\n \"city\": \"Springfield\",\n \"state\": \"IL\"\n },\n \"items\": [\"Laptop\", \"Monitor\", \"Keyboard\"]\n }\n]\n```\n\nTemplate for nested data:\n\n```latex\n\u003c\u003c name >>\\\\\n\u003c\u003c address.street >>\\\\\n\u003c\u003c address.city >>, \u003c\u003c address.state >>\n\nItems: \u003c% for item in items %>\u003c\u003c item >>\u003c% if not loop.last %>, \u003c% endif %>\u003c% endfor %>\n```\n\n### Script Options\n\n| Option | Description |\n|---|---|\n| `--output-dir DIR` | Output directory (default: ./outputs) |\n| `--name-field FIELD` | Data field for output filenames |\n| `--prefix TEXT` | Prefix for output filenames |\n| `--compile-script PATH` | Path to compile_latex.sh |\n| `--engine ENGINE` | pdflatex, xelatex, or lualatex |\n| `--workers N` | Parallel compilation workers |\n| `--merge` | Merge all PDFs into one file |\n| `--merge-name FILE` | Merged PDF filename |\n| `--no-compile` | Generate .tex only |\n| `--no-escape` | Disable LaTeX escaping |\n| `--jinja` | Force Jinja2 mode |\n| `--simple` | Force simple mode |\n| `--limit N` | Process first N records only |\n| `--dry-run` | Preview without generating |\n| `--copy-assets FILE...` | Copy additional files (images, .bib) |\n| `--verbose` | Detailed output |\n\n### Common Use Cases\n\n| Use Case | Data Fields | Template |\n|---|---|---|\n| Personalized letters | name, address, salutation | `mail-merge-letter.tex` |\n| Certificates/diplomas | name, course, date, grade | Custom certificate template |\n| Invoices | client, items[], amounts[], total | Jinja2 template with loops |\n| Report cards | student, grades{}, comments | Jinja2 template with conditionals |\n| Name badges | name, title, organization | Small format template |\n| Personalized exams | student, questions[] | Jinja2 template with shuffled content |\n\n### Special Character Handling\n\nData values are automatically escaped for LaTeX. Special characters like `&`, `%`, ` latex-document-skill — Skillopedia , `#`, `_` are converted to their LaTeX equivalents. To pass raw LaTeX through (e.g., math mode), prefix the value with `\\` in your data or use the `|raw` filter in Jinja2 mode:\n\n```latex\n% In Jinja2 mode, use |raw to prevent escaping\nThe formula is: \u003c\u003c formula|raw >>\n```\n\n### Template\n\nSee `assets/templates/mail-merge-letter.tex` for a complete working example.\n\n---\n\n## 4. Version Diffing (latexdiff)\n\nGenerate highlighted change-tracked PDFs between two versions of a LaTeX document using `latexdiff`. Shows additions (underlined blue) and deletions (struck-through red) in the compiled PDF.\n\n### Quick Start\n\n```bash\n# Basic diff between two files\nbash \u003cskill_path>/scripts/latex_diff.sh old_version.tex new_version.tex --compile --preview\n\n# Diff against a git revision\nbash \u003cskill_path>/scripts/latex_diff.sh paper.tex --git-rev HEAD~1 --compile\n\n# Diff between two git tags\nbash \u003cskill_path>/scripts/latex_diff.sh paper.tex --git-rev v1.0 --compile\n\n# Multi-file document (with \\input/\\include)\nbash \u003cskill_path>/scripts/latex_diff.sh old/main.tex new/main.tex --flatten --compile\n\n# Custom markup style\nbash \u003cskill_path>/scripts/latex_diff.sh old.tex new.tex --type CULINECHBAR --compile\n\n# Custom colors\nbash \u003cskill_path>/scripts/latex_diff.sh old.tex new.tex \\\n --color-add \"green!70!black\" --color-del \"red!80!black\" --compile\n```\n\n### Script Options\n\n| Option | Description |\n|---|---|\n| `--output FILE` | Output diff .tex file |\n| `--output-dir DIR` | Output directory |\n| `--type TYPE` | Markup type (see below) |\n| `--subtype SUBTYPE` | Markup subtype |\n| `--flatten` | Expand \\input/\\include (multi-file docs) |\n| `--math-markup MODE` | fine, coarse, off, whole |\n| `--color-add COLOR` | Color for additions (default: blue) |\n| `--color-del COLOR` | Color for deletions (default: red) |\n| `--compile` | Auto-compile diff to PDF |\n| `--preview` | Compile + generate PNG preview |\n| `--compile-script PATH` | Path to compile_latex.sh |\n| `--git-rev REV` | Diff against git revision |\n| `--exclude-safecmd CMDS` | Commands to exclude |\n| `--verbose` | Show detailed output |\n\n### Markup Types\n\n| Type | Additions | Deletions | Best For |\n|---|---|---|---|\n| **UNDERLINE** (default) | Underlined blue | Struck-through red | General use, reviewer-friendly |\n| **CTRADITIONAL** | Blue text | Red struck-through | Traditional change tracking |\n| **CFONT** | Sans-serif blue | Tiny red | Subtle changes |\n| **CHANGEBAR** | Change bar in margin | Change bar in margin | Minimal inline disruption |\n| **CCHANGEBAR** | Color + change bar | Color + change bar | Comprehensive tracking |\n| **CULINECHBAR** | Underline + change bar | Strike + change bar | Most visible changes |\n| **FONTSTRIKE** | Font change | Strikethrough | Simple visual diff |\n\n### Git Integration\n\nThe script integrates with git via the `--git-rev` flag:\n\n```bash\n# Diff against previous commit\nbash latex_diff.sh paper.tex --git-rev HEAD~1 --compile\n\n# Diff against specific commit\nbash latex_diff.sh paper.tex --git-rev abc1234 --compile\n\n# Diff against a branch\nbash latex_diff.sh paper.tex --git-rev main --compile\n\n# Diff against a tag\nbash latex_diff.sh paper.tex --git-rev v1.0 --compile\n```\n\n### Handling Common Problems\n\n**Problem: latexdiff fails on complex packages**\n\n```bash\n# Exclude problematic commands from diff processing\nbash latex_diff.sh old.tex new.tex --exclude-safecmd \"SI,qty,num\"\n```\n\n**Problem: Multi-file document with \\input**\n\n```bash\n# --flatten expands all \\input and \\include before diffing\nbash latex_diff.sh old/main.tex new/main.tex --flatten --compile\n```\n\n**Problem: Math changes not rendered correctly**\n\n```bash\n# Use coarse math markup (diffs entire equations, not individual symbols)\nbash latex_diff.sh old.tex new.tex --math-markup coarse --compile\n```\n\n**Problem: Tables cause compilation errors**\n\nThe diff document may have issues with complex table changes. Workaround: manually edit the diff .tex file to fix table markup, then compile.\n\n### Best Practices for Clean Diffs\n\n1. **One sentence per line** in your .tex files. This produces clean, meaningful diffs instead of entire-paragraph changes.\n2. **Use git** for version control of LaTeX documents.\n3. **Avoid reformatting** between versions (don't re-wrap lines).\n4. **Use `--flatten`** for any document with `\\input` or `\\include`.\n5. **Generate diff PDFs** as part of your paper submission workflow.\n6. **For journal revisions**, use `CULINECHBAR` type for maximum visibility.\n\n### Direct latexdiff Usage (without script)\n\nIf you need more control:\n\n```bash\n# Install latexdiff\nsudo apt-get install latexdiff\n\n# Basic diff\nlatexdiff old.tex new.tex > diff.tex\n\n# With options\nlatexdiff --type=UNDERLINE --math-markup=fine --allow-spaces old.tex new.tex > diff.tex\n\n# Flatten multi-file documents\nlatexdiff --flatten old/main.tex new/main.tex > diff.tex\n\n# Then compile\npdflatex diff.tex\npdflatex diff.tex # Second pass for references\n```\n\n### Installation\n\nThe `latex_diff.sh` script auto-installs `latexdiff` if not present. Manual installation:\n\n```bash\nsudo apt-get install latexdiff\n```\n\nRequires Perl (pre-installed on most systems).\n\n---\n\n## Package Dependencies Summary\n\n| Feature | Required Packages | Auto-Installed |\n|---|---|---|\n| Form fields | `hyperref` | Yes (texlive-latex-recommended) |\n| Conditional content | `etoolbox`, `comment` | Yes (texlive-latex-extra) |\n| Mail merge | Python 3 + `jinja2` + `pandas` | jinja2/pandas may need pip install |\n| Version diffing | `latexdiff` (Perl script) | Auto-installed by latex_diff.sh |\n\n### Install All Dependencies\n\n```bash\n# LaTeX packages (usually already installed with texlive-latex-extra)\nsudo apt-get install texlive-latex-extra texlive-latex-recommended\n\n# latexdiff\nsudo apt-get install latexdiff\n\n# Python dependencies for mail merge\npip3 install jinja2 pandas\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":20004,"content_sha256":"a38d26fccb08e4266e2f93a1e7bb0fa72d317e91161476b0f51a65887c227f01"},{"filename":"references/long-form-best-practices.md","content":"# Long-Form Document Best Practices\n\nThis reference is for documents **5+ pages** (reports, theses, books, strategic documents). It addresses systematic problems that silently degrade document quality in long-form LaTeX documents. Violations produce documents that compile fine but look unprofessional.\n\n---\n\n## Anti-Pattern 1: \"Wall of Bullets\" — Over-reliance on itemize/enumerate\n\n**The Problem:** When generating content about any complex topic, the default behavior is to put every group of related points into `\\begin{itemize}`. A 40-page report can easily end up with 50-80 itemize blocks, making it look like a PowerPoint outline rather than a professional document.\n\n**The Rule:** In reports and articles, **prose paragraphs are the default**. Bullet lists are the exception. Use this decision framework:\n\n| Content Type | Format | Example |\n|---|---|---|\n| Analysis, explanation, argument | **Prose paragraph** | Market trends, strategic rationale, findings |\n| Genuinely parallel items (specs, features) | **Table** (`tabularx` + `booktabs`) | Feature comparison, pricing tiers, specs |\n| 3-5 labeled concepts | **Bold-label paragraphs** | `\\textbf{Concept:} Explanation...` |\n| Personas, callouts, key findings | **tcolorbox cards** | Customer profiles, executive summaries |\n| Sequential steps (process, timeline) | **Numbered prose or table** | GTM phases, implementation roadmap |\n| Raw data points, reference lists | **Bullet list (only here)** | Bibliography, tool lists, prerequisites |\n\n**How to convert bullets to prose:** Take each bullet point and weave it into a flowing sentence. Connect points with transitions (furthermore, additionally, in contrast, this means that). Group related bullets into a single paragraph with a topic sentence.\n\n**Bad (wall of bullets):**\n```latex\n\\textbf{Market Trends:}\n\\begin{itemize}\n \\item Multi-model adoption is increasing\n \\item Open-source models growing at 46\\%\n \\item Startups adopt 3-5x faster than enterprises\n \\item Web development is the largest use case\n\\end{itemize}\n```\n\n**Good (prose with structure):**\n```latex\n\\textbf{Market Trends:} Multi-model adoption is accelerating, with nearly all\nenterprises now testing multiple AI providers rather than standardizing on one.\nOpen-source models are gaining traction---46\\% of organizations prefer them for\ncost and control. Startups adopt agentic tools 3--5x faster than enterprises,\nand web development represents the largest use case for AI coding tools.\n```\n\n**Good (bold-label paragraphs for distinct concepts):**\n```latex\n\\textbf{Multi-Model Adoption:} Nearly all enterprises now test multiple AI\nmodels rather than standardizing on one, favoring flexibility per task.\n\n\\textbf{Open-Source Surge:} 46\\% of organizations prefer open-source models\nfor cost and control, creating demand for platforms supporting both commercial\nand open-source models.\n```\n\n**Good (tcolorbox card for personas/profiles):**\n```latex\n\\usepackage[most]{tcolorbox}\n% ...\n\\begin{tcolorbox}[colback=blue!5, colframe=blue!70, title={\\textbf{Target Persona: Solo Developer}}, fonttitle=\\bfseries]\n\\textbf{Profile:} CS degree or bootcamp grad, 28--35, entrepreneurial mindset.\nActive on Hacker News and indie communities.\n\n\\textbf{Pain Points:} Spends 80\\% of time on boilerplate. Tool fatigue from\n10+ subscriptions. Deployment complexity slows iteration.\n\n\\textbf{Value Prop:} \\textit{``Ship your side project in a weekend, not a month.''}\n\\end{tcolorbox}\n```\n\n**Target:** A well-formatted 40-page report should have fewer than 15 itemize/enumerate blocks total. If you count more than 20, refactor.\n\n## Anti-Pattern 2: Excessive \\newpage Commands\n\n**The Problem:** Inserting `\\newpage` before every `\\section` creates pages that are 30-50% empty. This mimics slide-deck formatting and wastes space.\n\n**The Rule:** Let LaTeX handle page breaks naturally. Only use `\\newpage` in these cases:\n- Before `\\tableofcontents` and after it (standard)\n- Before the first `\\section` (after front matter)\n- Between truly independent major parts (e.g., between a 20-page analysis and a 10-page appendix)\n- When a figure/table would look awkward split across pages\n\n**Never** use `\\newpage` before every `\\section` or `\\subsection`. LaTeX's page-breaking algorithm is sophisticated — let it work.\n\n## Anti-Pattern 3: Oversized Images and Rigid Float Placement\n\n**The Problem:** Images at `width=0.95\\textwidth` consume almost the full page width, pushing surrounding text to the next page and creating whitespace. Combined with `[H]` float placement, this forces half-empty pages.\n\n**The Rules:**\n- Default image width: `0.75\\textwidth` to `0.85\\textwidth` (not 0.95)\n- Use `[htbp]` for most figures (allows LaTeX to optimize placement)\n- Only use `[H]` when the figure MUST appear at that exact spot (e.g., immediately after \"as shown below:\")\n- For AI-generated images (often 1-2MB), `0.75\\textwidth` is usually sufficient\n- For charts and graphs, `0.80-0.85\\textwidth` works well\n- For full-page figures, use `0.90\\textwidth` maximum\n\n```latex\n% Good: flexible placement, reasonable size\n\\begin{figure}[htbp]\n\\centering\n\\includegraphics[width=0.80\\textwidth]{chart.png}\n\\caption{Revenue growth by quarter}\n\\end{figure}\n\n% Only when exact placement is critical\n\\begin{figure}[H]\n\\centering\n\\includegraphics[width=0.75\\textwidth]{diagram.png}\n\\caption{Architecture diagram referenced in text above}\n\\end{figure}\n```\n\n## Anti-Pattern 4: No Global List Compaction\n\n**The Problem:** LaTeX's default list spacing (itemsep, topsep, parsep, partopsep) is generous. A 4-item bullet list can consume as much vertical space as a full paragraph. In a document with many lists, this creates enormous wasted space.\n\n**The Rule:** Always add global list compaction to the preamble for reports and articles:\n\n```latex\n\\usepackage{enumitem}\n\\setlist[itemize]{nosep, leftmargin=*, topsep=2pt, partopsep=0pt}\n\\setlist[enumerate]{nosep, leftmargin=*, topsep=2pt, partopsep=0pt}\n```\n\nThis reduces list spacing to match body text density without eliminating indentation or readability.\n\n## Anti-Pattern 5: Monotonous Section Structure\n\n**The Problem:** Every subsection follows the identical pattern: intro sentence → bullet list → bold conclusion. Over 40+ pages, this repetition makes the document feel generated rather than authored.\n\n**The Rule:** Vary presentation across sections. Use at least 3-4 different content formats throughout a long document:\n\n1. **Prose paragraphs** (analysis, narrative, argument)\n2. **Tables** (`booktabs` + `tabularx`) for comparisons and structured data\n3. **tcolorbox cards** for profiles, callouts, executive summaries\n4. **Bold-label paragraphs** for 3-5 distinct concepts\n5. **Figures with captions** for charts, diagrams, images\n6. **Longtable** for multi-page structured comparisons\n\nAdjacent sections should NOT use the same format. If Section 3.1 uses a table, Section 3.2 should use prose or tcolorbox, not another table.\n\n## Anti-Pattern 6: Silent Encoding Errors\n\n**The Problem:** Documents compile without errors but the PDF contains garbage characters (inverted question marks, missing symbols). The agent doesn't notice because compilation succeeds.\n\n**Common silent errors:**\n| You Write | PDF Shows | Fix |\n|---|---|---|\n| `\u003c5%` in text | ¿5% | `$\u003c$5\\%` |\n| `>50` in text | ¡50 | `$>$50` |\n| `~` in text | (nothing/tilde accent on next char) | `\\textasciitilde` |\n| `|` in text | (may render wrong) | `\\textbar` or `$\\vert latex-document-skill — Skillopedia |\n| `\\` in text | (starts a command) | `\\textbackslash` |\n| `{` or `}` in text | (grouping chars) | `\\{` or `\\}` |\n\n**The Rule:** After generating LaTeX content, scan for these characters in text mode (outside math `$... latex-document-skill — Skillopedia and commands). The most commonly missed are `\u003c` and `>`.\n\n## Anti-Pattern 7: Hardcoded Dimensions\n\n**The Problem:** Using absolute units (`12cm`, `5in`, `300pt`) for widths, margins, and spacing creates documents that break when paper size, font size, or column layout changes. A figure set to `width=15cm` overflows the margin on letter paper with 1-inch margins.\n\n**The Rule:** Always use relative units that adapt to the current layout:\n\n| Instead of | Use | Why |\n|---|---|---|\n| `width=15cm` | `width=0.8\\textwidth` | Adapts to margins and columns |\n| `\\hspace{2cm}` | `\\hspace{2em}` or `\\quad` | Scales with font size |\n| `\\vspace{1in}` | `\\vspace{\\baselineskip}` | Consistent with line spacing |\n| `\\parindent=20pt` | `\\parindent=1.5em` | Scales with font |\n| `\\setlength{\\tabcolsep}{12pt}` | `\\setlength{\\tabcolsep}{1em}` | Font-relative |\n\n**Exception:** Page margins in `geometry` package use absolute units by design (`margin=1in`).\n\n## Anti-Pattern 8: Missing \\noindent After Display Math\n\n**The Problem:** LaTeX treats text after a display math environment (`\\[ ... \\]`, `equation`, `align`) as a new paragraph, adding indentation. This creates a visual discontinuity when the text after the equation is a continuation of the same paragraph.\n\n**Wrong:**\n```latex\nThe quadratic formula is:\n\\[ x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a} \\]\nwhere $a$, $b$, and $c$ are coefficients. % ← Indented! Looks like new paragraph\n```\n\n**Correct:**\n```latex\nThe quadratic formula is:\n\\[ x = \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a} \\]\n\\noindent where $a$, $b$, and $c$ are coefficients. % ← Flush left, continuation\n```\n\n**The Rule:** If text after a display equation continues the same thought (starts with \"where\", \"for\", \"with\", \"so\", \"thus\"), add `\\noindent` to prevent false paragraph indentation.\n\n## Anti-Pattern 9: Widow and Orphan Lines\n\n**The Problem:** A single line of a paragraph appears alone at the bottom of a page (orphan) or top of the next page (widow). This looks unprofessional and wastes space. LaTeX's default penalties are too low to prevent this reliably.\n\n**The Rule:** Add these penalties to the preamble for any document over 5 pages:\n\n```latex\n\\widowpenalty=10000\n\\clubpenalty=10000\n```\n\nThis tells LaTeX to strongly avoid breaking paragraphs such that only one line ends up isolated. For additional control in critical documents:\n\n```latex\n\\widowpenalty=10000\n\\clubpenalty=10000\n\\brokenpenalty=10000 % Avoid page breaks after hyphenated lines\n\\predisplaypenalty=10000 % Avoid page breaks just before display math\n```\n\n---\n\n## Quick Reference: Report Preamble Best Practices\n\nEvery report-class document (10+ pages) should include this baseline preamble setup:\n\n```latex\n\\documentclass[11pt,a4paper]{article}\n\n% Core packages\n\\usepackage[margin=1in]{geometry}\n\\usepackage{graphicx}\n\\usepackage[colorlinks=true, linkcolor=blue, urlcolor=blue]{hyperref}\n\\usepackage[table]{xcolor}\n\\usepackage{colortbl}\n\\usepackage{booktabs}\n\\usepackage{tabularx}\n\\usepackage{float}\n\\usepackage{enumitem}\n\\usepackage{longtable}\n\\usepackage{amsmath, amssymb}\n\n% Recommended for professional reports\n\\usepackage[most]{tcolorbox} % colored boxes for callouts, personas, highlights\n\\usepackage{titlesec} % section heading customization\n\\usepackage{fancyhdr} % headers and footers\n\n% Global list compaction (ALWAYS include for reports)\n\\setlist[itemize]{nosep, leftmargin=*, topsep=2pt, partopsep=0pt}\n\\setlist[enumerate]{nosep, leftmargin=*, topsep=2pt, partopsep=0pt}\n```\n\n---\n\n## Content Generation Checklist (Run Before Compiling)\n\nBefore compiling a long-form document, verify:\n\n- [ ] **Bullet count:** Fewer than 15 itemize/enumerate blocks per 40 pages? If not, convert excess to prose.\n- [ ] **Angle brackets:** Search for `\u003c` and `>` outside math mode. Replace with `$\u003c latex-document-skill — Skillopedia /`$> latex-document-skill — Skillopedia or `\\textless`/`\\textgreater`.\n- [ ] **\\newpage abuse:** Are `\\newpage` commands only at major transitions, not before every section?\n- [ ] **Image sizing:** Are most images `0.75-0.85\\textwidth`? No images at `0.95\\textwidth` unless full-bleed is intended?\n- [ ] **List compaction:** Is `\\setlist[itemize]{nosep, leftmargin=*}` in the preamble?\n- [ ] **Format variety:** Do adjacent sections use different content formats (prose, table, tcolorbox, figure)?\n- [ ] **Float placement:** Are most figures `[htbp]`, with `[H]` only where exact placement matters?\n- [ ] **Special characters:** Are `%`, ` latex-document-skill — Skillopedia , `&`, `#`, `_`, `\u003c`, `>` properly escaped in text mode?\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":12151,"content_sha256":"fdb460ef6e8c7cb8ff1cbc3d718046254dda38951da95495cf5dc8eb97679f01"},{"filename":"references/mermaid-diagrams.md","content":"# Mermaid Diagrams in LaTeX\n\n## Overview\n\n**Mermaid** is a text-based diagramming tool that uses simple markdown-like syntax to create diagrams. It's particularly useful for software documentation, flowcharts, and technical diagrams.\n\n### What is Mermaid?\n\nMermaid allows you to create diagrams using plain text descriptions. For example:\n\n```mermaid\ngraph LR\n A[Start] --> B{Decision}\n B -->|Yes| C[Action 1]\n B -->|No| D[Action 2]\n```\n\nThis simple text generates a flowchart diagram.\n\n### Why Use Mermaid with LaTeX?\n\n**Advantages:**\n- **Simple syntax** - easier to write and maintain than TikZ\n- **Fast prototyping** - quick to create and iterate\n- **Version control friendly** - plain text, easy to diff\n- **No LaTeX learning curve** - accessible to non-LaTeX users\n- **Quick collaboration** - team members can edit without LaTeX knowledge\n\n**Disadvantages:**\n- **Requires extra step** - must convert to image format\n- **Less control** - not as customizable as TikZ\n- **Image quality** - raster formats may not scale as well\n- **Limited to diagram types** - not suitable for all visualizations\n\n### Typical Workflow\n\n```\n1. Write diagram in .mmd file\n ↓\n2. Convert to PNG/PDF using mermaid-cli\n ↓\n3. Include in LaTeX with \\includegraphics\n ↓\n4. Compile LaTeX document\n```\n\n---\n\n## Installation\n\n### Mermaid CLI (Required)\n\nInstall the Mermaid command-line interface:\n\n```bash\n# Using npm (recommended)\nnpm install -g @mermaid-js/mermaid-cli\n\n# Verify installation\nmmdc --version\n```\n\n### LaTeX Packages (Required)\n\n```latex\n\\usepackage{graphicx} % For \\includegraphics\n\\usepackage{float} % For H placement specifier\n```\n\n---\n\n## Using the mermaid_to_image.sh Script\n\nThe skill includes a helper script for converting Mermaid diagrams to images.\n\n### Basic Usage\n\n```bash\n# Convert to PNG (default)\nmermaid_to_image.sh diagram.mmd\n\n# Convert to PDF\nmermaid_to_image.sh diagram.mmd --format pdf\n\n# Convert to SVG\nmermaid_to_image.sh diagram.mmd --format svg\n\n# Specify output filename\nmermaid_to_image.sh diagram.mmd --output flowchart.png\n\n# Set theme\nmermaid_to_image.sh diagram.mmd --theme dark\n\n# Set dimensions\nmermaid_to_image.sh diagram.mmd --width 800 --height 600\n```\n\n### Script Features\n\n- **Auto-installs mermaid-cli** if missing\n- **Multiple format support** - PNG, PDF, SVG\n- **Theme support** - default, dark, forest, neutral\n- **Custom dimensions** - specify width and height\n- **Background options** - transparent or colored\n- **Error handling** - validates .mmd syntax\n\n---\n\n## Flowcharts\n\nFlowcharts show process flows and decision logic.\n\n### Complete Example\n\n**File: `process_flow.mmd`**\n```mermaid\nflowchart TD\n Start([Start Process]) --> Input[/Input Data/]\n Input --> Validate{Valid?}\n Validate -->|Yes| Process[Process Data]\n Validate -->|No| Error[/Display Error/]\n Error --> End1([End])\n Process --> Save[(Save to Database)]\n Save --> Success[/Show Success Message/]\n Success --> End2([End])\n\n style Start fill:#90EE90\n style End1 fill:#FFB6C1\n style End2 fill:#90EE90\n style Error fill:#FFB6C1\n```\n\n**Convert to Image:**\n```bash\nmermaid_to_image.sh process_flow.mmd --format pdf\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{process_flow.pdf}\n \\caption{Data processing flowchart showing validation and error handling}\n \\label{fig:process-flow}\n\\end{figure}\n\nAs shown in Figure~\\ref{fig:process-flow}, the process validates\ninput data before processing.\n```\n\n### Flowchart Syntax\n\n```mermaid\nflowchart LR\n A[Rectangle] --> B(Rounded Rectangle)\n B --> C([Stadium/Pill])\n C --> D[[Subroutine]]\n D --> E[(Database)]\n E --> F((Circle))\n F --> G{Diamond/Decision}\n G -->|Yes| H[/Parallelogram/]\n G -->|No| I[\\Parallelogram Alt\\]\n```\n\n**Directions:**\n- `LR` - Left to Right\n- `RL` - Right to Left\n- `TB` or `TD` - Top to Bottom\n- `BT` - Bottom to Top\n\n**Arrow Types:**\n- `-->` - Solid arrow\n- `-.->` - Dotted arrow\n- `==>` - Thick arrow\n- `--text-->` - Arrow with label\n\n---\n\n## Sequence Diagrams\n\nSequence diagrams show interactions between components over time.\n\n### Example: User Authentication\n\n**File: `auth_sequence.mmd`**\n```mermaid\nsequenceDiagram\n actor User\n participant Frontend\n participant Backend\n participant Database\n\n User->>Frontend: Enter credentials\n Frontend->>Backend: POST /api/login\n activate Backend\n Backend->>Database: Query user\n activate Database\n Database-->>Backend: User data\n deactivate Database\n Backend->>Backend: Verify password\n alt Password correct\n Backend-->>Frontend: JWT token\n Frontend-->>User: Redirect to dashboard\n else Password incorrect\n Backend-->>Frontend: 401 Unauthorized\n Frontend-->>User: Show error message\n end\n deactivate Backend\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.9\\textwidth]{auth_sequence.pdf}\n \\caption{Sequence diagram of user authentication flow}\n \\label{fig:auth-sequence}\n\\end{figure}\n```\n\n### Sequence Diagram Features\n\n- **Participants**: `participant Name`\n- **Actors**: `actor Name`\n- **Arrows**: `->`, `-->`, `->>`, `-->>` (various styles)\n- **Activation**: `activate`/`deactivate` blocks\n- **Notes**: `Note over A,B: Text`\n- **Loops**: `loop text ... end`\n- **Alternatives**: `alt ... else ... end`\n- **Parallel**: `par ... and ... end`\n\n---\n\n## Class Diagrams\n\nClass diagrams show object-oriented structure and relationships.\n\n### Example: E-commerce System\n\n**File: `ecommerce_classes.mmd`**\n```mermaid\nclassDiagram\n class User {\n +int userId\n +string email\n +string passwordHash\n +login()\n +logout()\n +updateProfile()\n }\n\n class Order {\n +int orderId\n +DateTime orderDate\n +decimal totalAmount\n +OrderStatus status\n +calculateTotal()\n +processPayment()\n }\n\n class Product {\n +int productId\n +string name\n +decimal price\n +int stockQuantity\n +updateStock()\n +getDetails()\n }\n\n class OrderItem {\n +int quantity\n +decimal priceAtPurchase\n +calculateSubtotal()\n }\n\n class ShoppingCart {\n +addItem()\n +removeItem()\n +checkout()\n }\n\n User \"1\" -- \"0..*\" Order : places\n Order \"1\" *-- \"1..*\" OrderItem : contains\n Product \"1\" -- \"0..*\" OrderItem : ordered in\n User \"1\" -- \"1\" ShoppingCart : has\n ShoppingCart \"1\" o-- \"0..*\" Product : contains\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=\\textwidth]{ecommerce_classes.pdf}\n \\caption{Class diagram of the e-commerce system architecture}\n \\label{fig:class-diagram}\n\\end{figure}\n```\n\n### Class Diagram Relationships\n\n- `--|>` - Inheritance\n- `--*` - Composition\n- `--o` - Aggregation\n- `-->` - Association\n- `--` - Link\n- `..|>` - Realization\n- `..>` - Dependency\n\n---\n\n## State Diagrams\n\nState diagrams show state transitions in a system.\n\n### Example: Order Status\n\n**File: `order_states.mmd`**\n```mermaid\nstateDiagram-v2\n [*] --> Pending\n Pending --> Processing : Payment confirmed\n Pending --> Cancelled : User cancels\n Processing --> Shipped : Items dispatched\n Processing --> Cancelled : Out of stock\n Shipped --> InTransit : Carrier picked up\n InTransit --> Delivered : Signed by recipient\n InTransit --> Failed : Delivery failed\n Failed --> InTransit : Retry delivery\n Failed --> Returned : Return to sender\n Delivered --> [*]\n Cancelled --> [*]\n Returned --> [*]\n\n Processing : Processing payment\n Processing : Preparing items\n Shipped : Tracking number assigned\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{order_states.pdf}\n \\caption{State diagram showing order lifecycle transitions}\n \\label{fig:order-states}\n\\end{figure}\n```\n\n---\n\n## Entity Relationship Diagrams (ERD)\n\nER diagrams show database structure and relationships.\n\n### Example: Blog Database\n\n**File: `blog_erd.mmd`**\n```mermaid\nerDiagram\n USER ||--o{ POST : writes\n USER ||--o{ COMMENT : writes\n POST ||--o{ COMMENT : has\n POST }o--o{ TAG : tagged_with\n POST ||--o{ POST_IMAGE : contains\n\n USER {\n int user_id PK\n string username\n string email UK\n string password_hash\n datetime created_at\n datetime last_login\n }\n\n POST {\n int post_id PK\n int author_id FK\n string title\n text content\n datetime published_at\n boolean is_published\n int view_count\n }\n\n COMMENT {\n int comment_id PK\n int post_id FK\n int user_id FK\n text content\n datetime created_at\n int parent_comment_id FK\n }\n\n TAG {\n int tag_id PK\n string name UK\n string slug\n }\n\n POST_IMAGE {\n int image_id PK\n int post_id FK\n string file_path\n string alt_text\n }\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=\\textwidth]{blog_erd.pdf}\n \\caption{Entity-relationship diagram of the blog database schema}\n \\label{fig:blog-erd}\n\\end{figure}\n```\n\n### ER Diagram Relationships\n\n- `||--||` - One to one\n- `||--o{` - One to many\n- `}o--o{` - Many to many\n- `||--o|` - One to zero or one\n\n---\n\n## Gantt Charts\n\nGantt charts show project timelines and task dependencies.\n\n### Example: Software Development\n\n**File: `project_timeline.mmd`**\n```mermaid\ngantt\n title Software Development Project Timeline\n dateFormat YYYY-MM-DD\n section Planning\n Requirements Analysis :done, req, 2026-01-01, 2026-01-15\n System Design :done, design, after req, 10d\n\n section Development\n Backend API :active, backend, 2026-01-26, 30d\n Frontend UI :frontend, after backend, 25d\n Database Setup :done, db, 2026-01-20, 15d\n\n section Testing\n Unit Testing :testing, after frontend, 10d\n Integration Testing :after testing, 7d\n UAT :after testing, 14d\n\n section Deployment\n Production Setup :prod, after testing, 5d\n Go Live :milestone, after prod, 1d\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=\\textwidth]{project_timeline.pdf}\n \\caption{Project Gantt chart showing development phases and milestones}\n \\label{fig:gantt}\n\\end{figure}\n```\n\n---\n\n## Pie Charts\n\nPie charts show proportional data.\n\n### Example: Budget Allocation\n\n**File: `budget_pie.mmd`**\n```mermaid\npie title Project Budget Allocation\n \"Development\" : 45\n \"Testing\" : 15\n \"Infrastructure\" : 20\n \"Marketing\" : 12\n \"Support\" : 8\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.6\\textwidth]{budget_pie.pdf}\n \\caption{Project budget distribution across departments}\n \\label{fig:budget}\n\\end{figure}\n```\n\n---\n\n## Mindmaps\n\nMindmaps show hierarchical relationships and brainstorming.\n\n### Example: Machine Learning Topics\n\n**File: `ml_mindmap.mmd`**\n```mermaid\nmindmap\n root((Machine Learning))\n Supervised Learning\n Classification\n Logistic Regression\n Decision Trees\n SVM\n Neural Networks\n Regression\n Linear Regression\n Ridge/Lasso\n Random Forest\n Unsupervised Learning\n Clustering\n K-Means\n DBSCAN\n Hierarchical\n Dimensionality Reduction\n PCA\n t-SNE\n UMAP\n Reinforcement Learning\n Q-Learning\n Policy Gradient\n Deep RL\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.9\\textwidth]{ml_mindmap.pdf}\n \\caption{Mindmap of machine learning taxonomy and algorithms}\n \\label{fig:ml-mindmap}\n\\end{figure}\n```\n\n---\n\n## Timeline Diagrams\n\nTimeline diagrams show chronological events.\n\n### Example: Product Evolution\n\n**File: `product_timeline.mmd`**\n```mermaid\ntimeline\n title Product Evolution Timeline\n section 2023\n Q1 : Initial Release\n : Beta Testing\n Q2 : Version 1.0\n : Mobile App Launch\n Q3 : API Release\n : Third-party Integrations\n Q4 : Enterprise Features\n : SSO Support\n section 2024\n Q1 : AI Features\n : Recommendation Engine\n Q2 : Version 2.0\n : Complete Redesign\n Q3 : International Expansion\n : Multi-language Support\n Q4 : Analytics Dashboard\n : Advanced Reporting\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=\\textwidth]{product_timeline.pdf}\n \\caption{Product development timeline showing major releases and features}\n \\label{fig:timeline}\n\\end{figure}\n```\n\n---\n\n## Styling and Themes\n\n### Available Themes\n\nMermaid supports several built-in themes:\n\n1. **default** - Standard blue and white theme\n2. **dark** - Dark background with light text\n3. **forest** - Green color scheme\n4. **neutral** - Grayscale theme\n\n### Applying Themes\n\n**Using Script:**\n```bash\nmermaid_to_image.sh diagram.mmd --theme dark\n```\n\n**Using Config File:**\n\nCreate `mermaid_config.json`:\n```json\n{\n \"theme\": \"dark\",\n \"themeVariables\": {\n \"primaryColor\": \"#BB2528\",\n \"primaryTextColor\": \"#fff\",\n \"primaryBorderColor\": \"#7C0000\",\n \"lineColor\": \"#F8B229\",\n \"secondaryColor\": \"#006100\",\n \"tertiaryColor\": \"#fff\"\n }\n}\n```\n\nConvert with config:\n```bash\nmmdc -i diagram.mmd -o diagram.pdf -c mermaid_config.json\n```\n\n### Custom Styling\n\nAdd style directives in the diagram:\n\n```mermaid\nflowchart LR\n A[Start] --> B[Process]\n B --> C[End]\n\n style A fill:#90EE90,stroke:#333,stroke-width:2px\n style B fill:#87CEEB,stroke:#333,stroke-width:2px\n style C fill:#FFB6C1,stroke:#333,stroke-width:2px\n```\n\n### Class Definitions\n\nDefine reusable styles:\n\n```mermaid\nflowchart TD\n A[Success]:::success --> B[Warning]:::warning\n B --> C[Error]:::error\n\n classDef success fill:#90EE90,stroke:#333,stroke-width:2px\n classDef warning fill:#FFD700,stroke:#333,stroke-width:2px\n classDef error fill:#FFB6C1,stroke:#333,stroke-width:2px\n```\n\n---\n\n## LaTeX Integration Tips\n\n### Sizing in LaTeX\n\nControl diagram size with `\\includegraphics` options:\n\n```latex\n% Fixed width\n\\includegraphics[width=0.8\\textwidth]{diagram.pdf}\n\n% Fixed height\n\\includegraphics[height=8cm]{diagram.pdf}\n\n% Scale\n\\includegraphics[scale=0.75]{diagram.pdf}\n\n% Maximum size (keeps aspect ratio)\n\\includegraphics[width=0.9\\textwidth,height=0.5\\textheight,keepaspectratio]{diagram.pdf}\n```\n\n### Caption and Label\n\nAlways add descriptive captions and labels:\n\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{flowchart.pdf}\n \\caption{User registration process flowchart showing validation steps and error handling}\n \\label{fig:user-registration}\n\\end{figure}\n\n% Reference in text\nSee Figure~\\ref{fig:user-registration} for the complete registration process.\n```\n\n### Figure Placement\n\nControl where figures appear:\n\n```latex\n% HERE (requires float package)\n\\begin{figure}[H]\n\n% Top of page\n\\begin{figure}[t]\n\n% Bottom of page\n\\begin{figure}[b]\n\n% Separate page\n\\begin{figure}[p]\n\n% Let LaTeX decide (default)\n\\begin{figure}[htbp]\n```\n\n### Multiple Diagrams Side-by-Side\n\nUse `subfigure` or `subcaption`:\n\n```latex\n\\usepackage{subcaption}\n\n\\begin{figure}[H]\n \\centering\n \\begin{subfigure}[b]{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{before.pdf}\n \\caption{Before optimization}\n \\label{fig:before}\n \\end{subfigure}\n \\hfill\n \\begin{subfigure}[b]{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{after.pdf}\n \\caption{After optimization}\n \\label{fig:after}\n \\end{subfigure}\n \\caption{System architecture comparison}\n \\label{fig:comparison}\n\\end{figure}\n```\n\n### Rotating Diagrams\n\nFor wide diagrams, rotate to landscape:\n\n```latex\n\\usepackage{rotating}\n\n\\begin{sidewaysfigure}\n \\centering\n \\includegraphics[width=0.9\\textwidth]{wide_diagram.pdf}\n \\caption{Complete system architecture (landscape view)}\n \\label{fig:architecture}\n\\end{sidewaysfigure}\n```\n\n---\n\n## When to Use Mermaid vs TikZ\n\n### Comparison Table\n\n| Aspect | Mermaid | TikZ |\n|--------|---------|------|\n| **Learning Curve** | Low - simple syntax | High - complex LaTeX |\n| **Speed** | Fast - quick prototypes | Slow - detailed coding |\n| **Customization** | Limited themes | Full control |\n| **Quality** | Good (raster/vector) | Excellent (native vector) |\n| **Collaboration** | Easy - non-LaTeX users | Hard - LaTeX experts only |\n| **Integration** | External (image) | Native LaTeX |\n| **Version Control** | Excellent (plain text) | Excellent (plain text) |\n| **Maintenance** | Easy to update | More complex |\n| **Best For** | Software diagrams, flowcharts | Mathematical diagrams, precise graphics |\n\n### Use Mermaid When:\n\n- Creating **software architecture diagrams**\n- Drawing **flowcharts and process diagrams**\n- Making **sequence diagrams** for API documentation\n- Building **ER diagrams** for database documentation\n- Collaborating with **non-LaTeX users**\n- Need **quick iterations** and prototypes\n- Diagram structure matters more than pixel-perfect appearance\n\n### Use TikZ When:\n\n- Creating **mathematical diagrams** (geometry, graphs)\n- Need **precise control** over every element\n- Drawing **complex custom shapes**\n- Creating **annotated mathematical proofs**\n- Want **native LaTeX integration** (no external images)\n- Need **perfect alignment** with text\n- Diagram requires **LaTeX math** embedded within it\n\n### Hybrid Approach\n\nYou can use both in the same document:\n\n- **Mermaid** for process flows and software architecture\n- **TikZ** for mathematical diagrams and precise illustrations\n\n```latex\n\\documentclass{article}\n\\usepackage{graphicx}\n\\usepackage{tikz}\n\n\\begin{document}\n\n% Mermaid diagram (included as image)\n\\begin{figure}[H]\n \\includegraphics[width=0.8\\textwidth]{architecture.pdf}\n \\caption{System architecture (created with Mermaid)}\n\\end{figure}\n\n% TikZ diagram (native LaTeX)\n\\begin{figure}[H]\n \\centering\n \\begin{tikzpicture}\n \\draw[->] (0,0) -- (2,0) node[right] {$x$};\n \\draw[->] (0,0) -- (0,2) node[above] {$y$};\n \\draw[domain=0:1.5,smooth,variable=\\x,blue] plot ({\\x},{\\x*\\x});\n \\end{tikzpicture}\n \\caption{Mathematical function (created with TikZ)}\n\\end{figure}\n\n\\end{document}\n```\n\n---\n\n## Workflow Best Practices\n\n### 1. Organize Diagram Files\n\n```\nproject/\n├── main.tex\n├── diagrams/\n│ ├── source/ # .mmd source files\n│ │ ├── flowchart.mmd\n│ │ ├── sequence.mmd\n│ │ └── erd.mmd\n│ └── generated/ # Generated images\n│ ├── flowchart.pdf\n│ ├── sequence.pdf\n│ └── erd.pdf\n└── figures/ # Other images\n```\n\n### 2. Conversion Script\n\nCreate `generate_diagrams.sh`:\n\n```bash\n#!/bin/bash\nfor mmd_file in diagrams/source/*.mmd; do\n filename=$(basename \"$mmd_file\" .mmd)\n mermaid_to_image.sh \"$mmd_file\" \\\n --format pdf \\\n --output \"diagrams/generated/${filename}.pdf\"\ndone\n```\n\n### 3. Makefile Integration\n\n```makefile\n.PHONY: diagrams clean\n\ndiagrams:\n\t@echo \"Generating Mermaid diagrams...\"\n\t@./generate_diagrams.sh\n\nmain.pdf: main.tex diagrams\n\tpdflatex main.tex\n\tpdflatex main.tex\n\nclean:\n\trm -f *.aux *.log *.out\n\trm -f diagrams/generated/*.pdf\n```\n\n### 4. Version Control\n\nAdd to `.gitignore`:\n```\n# Generated diagram files\ndiagrams/generated/*.png\ndiagrams/generated/*.pdf\n\n# But keep source files\n!diagrams/source/*.mmd\n```\n\nCommit `.mmd` source files but not generated images (can regenerate anytime).\n\n---\n\n## Troubleshooting\n\n### Diagram Not Rendering\n\n**Problem:** `mmdc` command fails or produces blank output.\n\n**Solutions:**\n1. Validate syntax at https://mermaid.live/\n2. Check for special characters that need escaping\n3. Ensure all required dependencies installed (Puppeteer, Chrome)\n4. Try different output format (PNG instead of PDF)\n\n### Text Overlapping in Diagram\n\n**Problem:** Labels and text overlap or are cut off.\n\n**Solutions:**\n1. Increase output dimensions: `--width 1200 --height 800`\n2. Shorten node labels\n3. Change layout direction (LR → TB)\n4. Adjust spacing in diagram definition\n\n### Poor Quality in PDF\n\n**Problem:** Diagram looks pixelated or blurry in PDF.\n\n**Solutions:**\n1. Use PDF output format: `--format pdf`\n2. Increase resolution for PNG: `--width 2400 --height 1800`\n3. Use SVG and convert to PDF with Inkscape\n4. Consider using TikZ for critical diagrams\n\n### LaTeX Compilation Error\n\n**Problem:** LaTeX fails to compile with included diagram.\n\n**Solutions:**\n1. Verify image file exists at specified path\n2. Check file extension matches actual format\n3. Ensure `graphicx` package is loaded\n4. Use absolute paths or paths relative to .tex file\n5. Check for spaces in filename (use underscores instead)\n\n---\n\n## Additional Resources\n\n- **Mermaid Documentation**: https://mermaid.js.org/\n- **Mermaid Live Editor**: https://mermaid.live/ (test diagrams online)\n- **Mermaid CLI**: https://github.com/mermaid-js/mermaid-cli\n- **Example Gallery**: https://mermaid.js.org/ecosystem/integrations.html\n- **TikZ vs Mermaid**: When to use each approach\n- **LaTeX graphicx**: https://ctan.org/pkg/graphicx\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":21559,"content_sha256":"092c4fbf50d76efdc0c396e56601a9c878e06596219d9c2567aa910ccf671f31"},{"filename":"references/packages.md","content":"# Common LaTeX Packages Quick Reference\n\n## Essential (include in most documents)\n\n**What this covers:** Fundamental packages that handle character encoding, page layout, and basic document features. These form the foundation of most LaTeX documents.\n\n| Package | Purpose |\n|---------|---------|\n| `inputenc` | UTF-8 input encoding (`\\usepackage[utf8]{inputenc}`) |\n| `fontenc` | T1 font encoding (`\\usepackage[T1]{fontenc}`) |\n| `geometry` | Page margins and dimensions |\n| `hyperref` | Clickable links, URLs, cross-references |\n| `xcolor` | Color definitions and usage |\n| `graphicx` | Image inclusion (`\\includegraphics`) |\n\n**Example:** Basic document setup\n```latex\n\\documentclass{article}\n\\usepackage[utf8]{inputenc} % UTF-8 input (default in modern TeX)\n\\usepackage[T1]{fontenc} % Better font encoding\n\\usepackage[margin=1in]{geometry} % Set all margins to 1 inch\n\\usepackage{xcolor} % For \\textcolor, \\colorbox\n\\usepackage{graphicx} % For \\includegraphics\n\\usepackage{hyperref} % LOAD LAST (almost always)\n\n\\hypersetup{\n colorlinks=true,\n linkcolor=blue,\n urlcolor=cyan\n}\n```\n\n**Common pitfalls:**\n- `hyperref` should be loaded last (with few exceptions like `cleveref`)\n- `inputenc` is not needed with XeLaTeX/LuaLaTeX\n- `geometry` package should come before `hyperref`\n- Color names require `\\usepackage[dvipsnames]{xcolor}` for extended names\n\n## Typography\n\n**What this covers:** Fine-tuning text appearance, spacing, fonts, and document layout. These packages control how your text looks on the page.\n\n| Package | Purpose |\n|---------|---------|\n| `titlesec` | Customize section heading styles |\n| `fancyhdr` | Custom headers and footers |\n| `parskip` | Paragraph spacing instead of indentation |\n| `microtype` | Improved text justification and kerning |\n| `lmodern` | Latin Modern fonts (scalable) |\n| `setspace` | Line spacing (`\\singlespacing`, `\\onehalfspacing`, `\\doublespacing`) |\n\n**Example:** Custom headers with chapter/section names\n```latex\n\\usepackage{fancyhdr}\n\\pagestyle{fancy}\n\\fancyhf{} % Clear all headers/footers\n\\fancyhead[L]{\\leftmark} % Chapter name on left\n\\fancyhead[R]{\\thepage} % Page number on right\n\\renewcommand{\\headrulewidth}{0.4pt}\n```\n\n**Example:** Professional typography setup\n```latex\n\\usepackage{microtype} % Improves spacing (load early)\n\\usepackage{lmodern} % Better fonts than Computer Modern\n\\usepackage[onehalfspacing]{setspace} % 1.5 line spacing\n\\usepackage{parskip} % Space between paragraphs instead of indent\n```\n\n**Common pitfalls:**\n- `microtype` should be loaded early, before fonts are set\n- `parskip` can conflict with `memoir` and KOMA-Script classes\n- `fancyhdr` requires `\\pagestyle{fancy}` to activate\n- `titlesec` conflicts with KOMA-Script and `memoir` (they have built-in alternatives)\n\n## Tables\n\n**What this covers:** Traditional table formatting with tabular environments. For modern alternatives, see \"Modern Matrix/Table Packages\" below.\n\n| Package | Purpose |\n|---------|---------|\n| `tabularx` | Tables with auto-width `X` columns |\n| `array` | Extended column definitions (`>{...}`, `p{width}`) |\n| `booktabs` | Professional rules: `\\toprule`, `\\midrule`, `\\bottomrule` |\n| `colortbl` | `\\rowcolor`, `\\cellcolor`, `\\columncolor` |\n| `multirow` | `\\multirow{rows}{width}{text}` |\n| `longtable` | Tables spanning multiple pages |\n\n**Example:** Professional table with `booktabs`\n```latex\n\\usepackage{booktabs}\n\\usepackage{tabularx}\n\n\\begin{table}[h]\n\\centering\n\\begin{tabularx}{0.8\\textwidth}{lXr}\n\\toprule\n\\textbf{Item} & \\textbf{Description} & \\textbf{Value} \\\\\n\\midrule\nA & Long text that wraps automatically & 123 \\\\\nB & Another row & 456 \\\\\n\\bottomrule\n\\end{tabularx}\n\\caption{A well-formatted table}\n\\end{table}\n```\n\n**Common pitfalls:**\n- Never use vertical lines with `booktabs` (looks unprofessional)\n- `\\hline` conflicts with `booktabs` spacing — use `\\midrule` instead\n- `tabularx` requires total width specification (e.g., `\\textwidth`)\n- `longtable` cannot be used inside a `table` float\n- Load order matters: `array` before `tabularx`, both before `booktabs`\n\n## Images and Drawing\n\n**What this covers:** Including external images and creating vector graphics programmatically within LaTeX.\n\n| Package | Purpose |\n|---------|---------|\n| `graphicx` | `\\includegraphics[width=..]{file}` |\n| `tikz` | Programmatic vector graphics, diagrams |\n| `wrapfig` | Wrap text around figures |\n| `subcaption` | Subfigures within a figure |\n| `float` | Force figure placement with `[H]` |\n| `caption` | Customize figure/table captions |\n\n**Example:** Responsive image sizing\n```latex\n\\usepackage{graphicx}\n\n% Best practice: scale relative to text width\n\\includegraphics[width=0.8\\textwidth]{diagram.pdf}\n\n% Maintain aspect ratio with max dimensions\n\\includegraphics[width=0.8\\textwidth,height=0.6\\textheight,keepaspectratio]{photo.jpg}\n```\n\n**Example:** Side-by-side subfigures\n```latex\n\\usepackage{subcaption}\n\n\\begin{figure}[htbp]\n \\centering\n \\begin{subfigure}{0.45\\textwidth}\n \\includegraphics[width=\\textwidth]{img1.png}\n \\caption{First subfigure}\n \\label{fig:sub1}\n \\end{subfigure}\n \\hfill\n \\begin{subfigure}{0.45\\textwidth}\n \\includegraphics[width=\\textwidth]{img2.png}\n \\caption{Second subfigure}\n \\label{fig:sub2}\n \\end{subfigure}\n \\caption{Combined caption}\n\\end{figure}\n```\n\n**Common pitfalls:**\n- File extensions: prefer PDF/PNG over JPG for diagrams (lossless)\n- `float` package's `[H]` often causes bad page breaks; use `[htbp]` instead\n- `subcaption` replaces older `subfig` and `subfigure` packages\n- TikZ can be slow to compile; externalize complex diagrams with `\\tikzexternalize`\n\n## Charts and Graphs\n\n**What this covers:** Data visualization with publication-quality plots, charts, and diagrams.\n\n| Package | Purpose |\n|---------|---------|\n| `pgfplots` | Line charts, bar charts, scatter plots, histograms |\n| `pgfplotstable` | Read and plot from CSV/TSV data files |\n| `tikz` | Flowcharts, timelines, custom diagrams |\n\n**Example:** Simple line plot with pgfplots\n```latex\n\\usepackage{pgfplots}\n\\pgfplotsset{compat=1.18} % Use latest compatibility mode\n\n\\begin{tikzpicture}\n\\begin{axis}[\n xlabel={Time (s)},\n ylabel={Position (m)},\n legend pos=north west\n]\n\\addplot[blue,thick] coordinates {\n (0,0) (1,2) (2,4) (3,8) (4,16)\n};\n\\legend{Exponential growth}\n\\end{axis}\n\\end{tikzpicture}\n```\n\n**Example:** Reading data from CSV\n```latex\n\\usepackage{pgfplots,pgfplotstable}\n\\pgfplotsset{compat=1.18}\n\n\\begin{tikzpicture}\n\\begin{axis}[xlabel=X, ylabel=Y]\n\\addplot table[x=col1, y=col2, col sep=comma] {data.csv};\n\\end{axis}\n\\end{tikzpicture}\n```\n\n**Common pitfalls:**\n- Always set `\\pgfplotsset{compat=1.18}` to use modern syntax\n- CSV files must be in same directory or use absolute paths\n- Large datasets can slow compilation significantly\n- Axis scaling issues: specify `xmin`, `xmax`, `ymin`, `ymax` explicitly if needed\n\n## Lists\n\n**What this covers:** Customizing bulleted, numbered, and description lists.\n\n| Package | Purpose |\n|---------|---------|\n| `enumitem` | Customize itemize/enumerate spacing, labels, nesting |\n\n**Example:** Compact lists with custom labels\n```latex\n\\usepackage{enumitem}\n\n% Globally compact lists\n\\setlist{noitemsep, topsep=0pt}\n\n% Custom enumerate labels\n\\begin{enumerate}[label=(\\roman*)]\n \\item First item\n \\item Second item\n\\end{enumerate}\n\n% Inline lists\nSome features: \\begin{enumerate*}[label=\\arabic*)]\n \\item compact, \\item inline, \\item enumeration\n\\end{enumerate*} in a sentence.\n```\n\n**Common pitfalls:**\n- Must use `\\setlist` in preamble, not inside document\n- Conflicts with beamer class (use beamer's built-in list customization)\n- Inline lists require starred version: `\\begin{enumerate*}`\n\n## Math\n\n**What this covers:** Mathematical typesetting, symbols, and theorem environments. For Unicode math, see \"Modern Font Handling\" below.\n\n| Package | Purpose |\n|---------|---------|\n| `amsmath` | Advanced math environments (`align`, `gather`, `cases`) |\n| `amssymb` | Additional math symbols (`\\mathbb`, `\\therefore`) |\n| `amsthm` | Theorem environments (`\\newtheorem`) |\n| `mathtools` | Extensions to amsmath (paired delimiters, cases) |\n| `mathrsfs` | Script math font (`\\mathscr`) |\n| `bbm` | Blackboard bold indicator (`\\mathbbm{1}`) |\n| `esint` | Extended surface integrals (`\\oiint`) |\n| `cancel` | Cancellation marks in equations (`\\cancel{x}`) |\n\n**Example:** Aligned equations with numbering\n```latex\n\\usepackage{amsmath}\n\n\\begin{align}\n E &= mc^2 \\label{eq:einstein} \\\\\n F &= ma \\label{eq:newton}\n\\end{align}\n\nSee equation \\eqref{eq:einstein} for relativity.\n```\n\n**Example:** Theorem environment\n```latex\n\\usepackage{amsthm}\n\\newtheorem{theorem}{Theorem}[section]\n\\newtheorem{lemma}[theorem]{Lemma}\n\n\\begin{theorem}[Pythagorean]\nIn a right triangle, $a^2 + b^2 = c^2$.\n\\end{theorem}\n```\n\n**Common pitfalls:**\n- Load order: `amsmath` before `mathtools`, both before most other math packages\n- Never use `$...$` (plain TeX); use `\\[...\\]` or equation environments\n- `align` automatically numbers all lines; use `align*` for unnumbered\n- `\\mathbb` requires `amssymb` or `amsfonts`\n\n## Presentations\n\n**What this covers:** Creating slide presentations with LaTeX.\n\n| Package | Purpose |\n|---------|---------|\n| `beamer` | Document class for slides/presentations |\n| Common themes | `Madrid`, `Berlin`, `CambridgeUS`, `Boadilla`, `Warsaw` |\n\n**Example:** Basic beamer presentation\n```latex\n\\documentclass{beamer}\n\\usetheme{Madrid}\n\\usecolortheme{beaver}\n\n\\title{My Presentation}\n\\author{Author Name}\n\\date{\\today}\n\n\\begin{document}\n\n\\frame{\\titlepage}\n\n\\begin{frame}\n\\frametitle{First Slide}\nContent here with \\pause incremental reveals.\n\\end{frame}\n\n\\end{document}\n```\n\n**Common pitfalls:**\n- Beamer is a document class, not a package (use `\\documentclass{beamer}`)\n- Many packages conflict with beamer (especially enumitem, parskip)\n- Fragile frames need `\\begin{frame}[fragile]` for verbatim content\n- Use `\\pause` for incremental reveals, not overlays unless needed\n\n## Bibliography\n\n**What this covers:** Managing citations and references. Use with BibTeX or Biber backend.\n\n| Package | Purpose |\n|---------|---------|\n| `natbib` | Author-year citations (`\\citet`, `\\citep`) |\n| `biblatex` | Modern bibliography management (more flexible than natbib) |\n\n**Example:** BibLaTeX with Biber (recommended)\n```latex\n\\usepackage[backend=biber, style=authoryear]{biblatex}\n\\addbibresource{references.bib}\n\n\\begin{document}\nAccording to \\textcite{author2020}, the results show...\nMultiple sources \\parencite{author2020,smith2019}.\n\n\\printbibliography\n\\end{document}\n\n% Compile: pdflatex -> biber -> pdflatex -> pdflatex\n```\n\n**Example:** NatBib (traditional)\n```latex\n\\usepackage[numbers]{natbib}\n\n\\begin{document}\n\\citet{author2020} found that... \\citep{smith2019}.\n\n\\bibliographystyle{plainnat}\n\\bibliography{references}\n\\end{document}\n\n% Compile: pdflatex -> bibtex -> pdflatex -> pdflatex\n```\n\n**Common pitfalls:**\n- `biblatex` and `natbib` are mutually exclusive (never load both)\n- Compile sequence matters: multiple passes required for references\n- `biblatex` requires Biber backend for full features (not BibTeX)\n- `.bib` file encoding must match document encoding\n\n## Modern Font Handling\n\n**What this covers:** Engine-agnostic font selection and Unicode support for modern TeX engines (XeLaTeX/LuaLaTeX).\n\n| Package | Purpose |\n|---------|---------|\n| `iftex` | Engine detection (`\\ifPDFTeX`, `\\ifXeTeX`, `\\ifLuaTeX`) for engine-agnostic preambles |\n| `fontspec` | System font access (XeLaTeX/LuaLaTeX only) |\n| `unicode-math` | Unicode math fonts (XeLaTeX/LuaLaTeX) |\n| `fontawesome5` | Icon glyphs (phone, email, LinkedIn, GitHub, etc.) |\n\n**Example:** Engine-agnostic preamble\n```latex\n\\usepackage{iftex}\n\\ifPDFTeX\n \\usepackage[utf8]{inputenc}\n \\usepackage[T1]{fontenc}\n \\usepackage{lmodern}\n\\else\n \\usepackage{fontspec}\n \\setmainfont{Linux Libertine O}\n \\setsansfont{Linux Biolinum O}\n \\setmonofont{Inconsolata}\n\\fi\n```\n\n**Example:** System fonts with fontspec\n```latex\n% XeLaTeX or LuaLaTeX only\n\\usepackage{fontspec}\n\\setmainfont{Helvetica Neue}[\n UprightFont = *,\n BoldFont = * Bold,\n ItalicFont = * Italic\n]\n```\n\n**Example:** Font Awesome icons\n```latex\n\\usepackage{fontawesome5}\n\n\\faPhone\\ +1-234-567-8900 \\\\\n\\faEnvelope\\ [email protected] \\\\\n\\faGithub\\ github.com/user \\\\\n\\faLinkedin\\ linkedin.com/in/user\n```\n\n**Common pitfalls:**\n- `fontspec` only works with XeLaTeX/LuaLaTeX, not pdfLaTeX\n- System fonts must be installed and accessible to the engine\n- `unicode-math` must load after `fontspec`\n- Font names are case-sensitive and OS-dependent\n- pdfLaTeX users should stick with `inputenc` and `fontenc`\n\n**Version notes:**\n- iftex replaces older `ifxetex`, `ifluatex`, `ifpdf` packages\n- fontspec requires XeTeX ≥0.9999 or LuaTeX ≥0.80\n\n## Modern Matrix/Table Packages\n\n**What this covers:** Next-generation table and matrix packages with enhanced features beyond traditional tabular.\n\n| Package | Purpose |\n|---------|---------|\n| `nicematrix` | Enhanced matrices with color, borders, named cells |\n| `tabularray` | Modern table package (replacement for tabular/tabularx) |\n| `nicetabular` | From nicematrix, for enhanced tables |\n\n**Example:** nicematrix with colored cells\n```latex\n\\usepackage{nicematrix}\n\n$\\begin{pNiceMatrix}[first-row,first-col]\n & C_1 & C_2 & C_3 \\\\\nR_1 & \\Block[fill=red!15]{2-2}{A} & & 0 \\\\\nR_2 & & & 0 \\\\\nR_3 & 0 & 0 & B \\\\\n\\end{pNiceMatrix}$\n```\n\n**Example:** tabularray modern table\n```latex\n\\usepackage{tabularray}\n\n\\begin{tblr}{\n colspec = {lXr},\n hlines, vlines,\n row{1} = {bg=azure8, font=\\bfseries}\n}\nItem & Description & Value \\\\\nA & Long text that wraps & 123 \\\\\nB & Another row & 456 \\\\\n\\end{tblr}\n```\n\n**Common pitfalls:**\n- `nicematrix` requires TikZ as dependency\n- `tabularray` syntax differs from traditional tabular\n- Both packages are relatively new (2020+)\n- Compile twice for proper cell positioning\n\n**Version notes:**\n- tabularray requires LaTeX 2020-10-01 or newer\n- nicematrix works with all major engines\n\n## Code Listing Packages\n\n**What this covers:** Syntax-highlighted code blocks in documents.\n\n| Package | Purpose |\n|---------|---------|\n| `listings` | Basic code highlighting (no external deps) |\n| `minted` | Superior highlighting via Pygments (requires -shell-escape) |\n| `tcolorbox` with `listings` | Code in colored boxes |\n\n**Example:** listings basic usage\n```latex\n\\usepackage{listings}\n\\usepackage{xcolor}\n\n\\lstset{\n language=Python,\n basicstyle=\\ttfamily\\small,\n keywordstyle=\\color{blue},\n commentstyle=\\color{gray},\n stringstyle=\\color{red},\n numbers=left,\n frame=single\n}\n\n\\begin{lstlisting}\ndef hello():\n print(\"Hello, world!\")\n\\end{lstlisting}\n```\n\n**Example:** minted with Pygments\n```latex\n\\usepackage{minted}\n\n\\begin{minted}[linenos, bgcolor=lightgray]{python}\ndef fibonacci(n):\n if n \u003c= 1:\n return n\n return fibonacci(n-1) + fibonacci(n-2)\n\\end{minted}\n\n% Compile with: pdflatex -shell-escape document.tex\n```\n\n**Example:** tcolorbox with listings\n```latex\n\\usepackage{tcolorbox}\n\\tcbuselibrary{listings, skins}\n\n\\begin{tcblisting}{\n colback=blue!5,\n colframe=blue!75!black,\n listing only,\n title=Python Code\n}\ndef greet(name):\n return f\"Hello, {name}!\"\n\\end{tcblisting}\n```\n\n**Common pitfalls:**\n- `minted` requires Python Pygments installed: `pip install Pygments`\n- Must compile with `-shell-escape` flag for minted (security risk)\n- `listings` has limited language support compared to minted\n- Verbatim code in `listings` requires `\\lstinline` not `\\verb`\n\n**Version notes:**\n- minted 2.x changed syntax from 1.x (check docs if using old code)\n- Pygments must be in system PATH\n\n## Document Structure\n\n**What this covers:** Cross-references, bookmarks, glossaries, and navigation aids.\n\n| Package | Purpose |\n|---------|---------|\n| `bookmark` | Enhanced PDF bookmarks (better than hyperref alone) |\n| `cleveref` | Smart cross-references (`\\cref{fig:x}` → \"Figure 1\") |\n| `glossaries` | Acronyms and glossary management |\n| `makeidx` | Index generation |\n\n**Example:** cleveref smart references\n```latex\n\\usepackage{hyperref} % Load hyperref first\n\\usepackage{cleveref} % Then cleveref\n\n\\begin{figure}\n \\includegraphics{plot.pdf}\n \\caption{Results}\n \\label{fig:results}\n\\end{figure}\n\nSee \\cref{fig:results} for details. % Outputs: \"Figure 1\"\n\\Cref{fig:results} shows... % Outputs: \"Figure 1\" (capitalized)\n```\n\n**Example:** glossaries for acronyms\n```latex\n\\usepackage{glossaries}\n\\makeglossaries\n\n\\newacronym{nasa}{NASA}{National Aeronautics and Space Administration}\n\n\\begin{document}\nFirst use: \\gls{nasa} % Outputs: National Aeronautics... (NASA)\nLater use: \\gls{nasa} % Outputs: NASA\n\n\\printglossary[type=\\acronymtype]\n\\end{document}\n\n% Compile: pdflatex -> makeglossaries -> pdflatex\n```\n\n**Example:** Index generation\n```latex\n\\usepackage{makeidx}\n\\makeindex\n\n\\begin{document}\nImportant term\\index{term} here.\nAnother concept\\index{concept!subconcept}.\n\n\\printindex\n\\end{document}\n\n% Compile: pdflatex -> makeindex -> pdflatex\n```\n\n**Common pitfalls:**\n- `cleveref` must load after `hyperref` and `amsmath`\n- `glossaries` requires external tool: `makeglossaries document`\n- Use `glossaries-extra` for more features\n- `bookmark` should load after `hyperref`\n\n**Version notes:**\n- cleveref requires ntheorem package for theorem support\n\n## Accessibility & Compliance\n\n**What this covers:** Making PDFs accessible for screen readers and archival compliance.\n\n| Package | Purpose |\n|---------|---------|\n| `pdfx` | PDF/A compliance for archival |\n| `tagpdf` | Tagged PDF for screen readers (experimental) |\n| `axessibility` | Math accessibility |\n\n**Example:** PDF/A-2b compliance\n```latex\n\\usepackage[a-2b]{pdfx}\n% Requires .xmpdata file with metadata\n\n\\begin{document}\nContent here...\n\\end{document}\n```\n\n**Example:** Tagged PDF (experimental)\n```latex\n\\DocumentMetadata{testphase=phase-III}\n\\documentclass{article}\n\\usepackage{tagpdf}\n\n\\tagpdfsetup{activate-all}\n\n\\begin{document}\nTagged content for accessibility...\n\\end{document}\n```\n\n**Common pitfalls:**\n- `pdfx` requires a `.xmpdata` file with metadata\n- `tagpdf` is experimental and syntax changes frequently\n- PDF/A prohibits some PDF features (transparency, encryption)\n- Accessibility is an active development area in LaTeX\n\n**Version notes:**\n- tagpdf requires LaTeX 2023-06-01 or newer\n- pdfx incompatible with some packages (check docs)\n\n## Science & Engineering\n\n**What this covers:** Specialized notation for scientific and technical fields.\n\n| Package | Purpose |\n|---------|---------|\n| `siunitx` | SI units with uncertainties (`\\qty{9.81}{m/s^2}`) |\n| `mhchem` | Chemical formulas (`\\ce{H2O}`) |\n| `circuitikz` | Circuit diagrams |\n| `tikz-feynman` | Feynman diagrams |\n\n**Example:** siunitx for units and numbers\n```latex\n\\usepackage{siunitx}\n\n\\qty{3.14159}{\\meter\\per\\second}\n\\qty{6.022e23}{\\per\\mole}\n\\qty{25.3(2)}{\\celsius} % With uncertainty\n\\numrange{10}{20}\n\\ang{45} % Angle: 45°\n```\n\n**Example:** mhchem for chemistry\n```latex\n\\usepackage{mhchem}\n\n\\ce{H2O} % Water\n\\ce{CO2 + H2O -> H2CO3} % Reaction\n\\ce{^{227}_{90}Th+} % Isotope notation\n\\ce{A \u003c=> B} % Equilibrium\n```\n\n**Example:** circuitikz for circuits\n```latex\n\\usepackage{circuitikz}\n\n\\begin{circuitikz}\n\\draw (0,0) to[battery, l=$V$] (0,2)\n to[R, l=$R$] (2,2)\n to[C, l=$C$] (2,0)\n -- (0,0);\n\\end{circuitikz}\n```\n\n**Common pitfalls:**\n- siunitx v3 syntax differs from v2 (`\\SI` → `\\qty`)\n- circuitikz uses TikZ syntax (requires TikZ knowledge)\n- tikz-feynman requires LuaLaTeX for automatic layout\n- mhchem conflicts with some math packages\n\n**Version notes:**\n- siunitx v3 (2021+): use `\\qty`, `\\unit`, `\\num` not `\\SI`\n- tikz-feynman requires LuaTeX for graph layout\n\n## Interactive / Dynamic Content\n\n**What this covers:** Conditional compilation, data-driven documents, and interactive PDF features.\n\n| Package | Purpose |\n|---------|---------|\n| `hyperref` (forms) | Fillable PDF form fields: `\\TextField`, `\\CheckBox`, `\\ChoiceMenu`, `\\PushButton` |\n| `etoolbox` | Boolean toggles for conditional content (`\\newtoggle`, `\\iftoggle`) |\n| `ifthen` | Conditional logic (`\\ifthenelse`, `\\equal`, `\\boolean`) |\n| `comment` | Block-level conditional inclusion/exclusion (`\\includecomment`, `\\excludecomment`) |\n| `xkeyval` | Key-value option parsing for document configuration |\n| `draftwatermark` | Conditional DRAFT/CONFIDENTIAL watermarks |\n| `lineno` | Line numbering for drafts and review copies |\n| `datatool` | Read CSV/databases directly in LaTeX (`\\DTLloaddb`, `\\DTLforeach`) |\n| `csvsimple` | Simpler CSV processing (`\\csvreader`, `\\csvautotabular`) |\n\n**Example:** Conditional content with etoolbox\n```latex\n\\usepackage{etoolbox}\n\n\\newtoggle{showsolutions}\n\\toggletrue{showsolutions} % or \\togglefalse\n\n\\begin{document}\nProblem: What is 2+2?\n\n\\iftoggle{showsolutions}{\n \\textbf{Solution:} 4\n}{}\n\\end{document}\n```\n\n**Example:** CSV data to table\n```latex\n\\usepackage{csvsimple}\n\n\\csvautotabular{data.csv} % Automatic table\n\n% Or custom formatting:\n\\csvreader[head to column names]{data.csv}{}{\n \\name: \\score points\n}\n```\n\n**Example:** Fillable PDF form\n```latex\n\\usepackage{hyperref}\n\n\\begin{Form}\nName: \\TextField[name=fullname, width=5cm]{}\n\n\\CheckBox[name=agree]{I agree to terms}\n\n\\PushButton[name=submit]{Submit}\n\\end{Form}\n```\n\n**Common pitfalls:**\n- PDF forms only work in Adobe Reader, not all PDF viewers\n- `datatool` is slow for large CSV files (use csvsimple instead)\n- `comment` package can break with verbatim content inside\n- Line numbers from `lineno` may conflict with equation numbering\n\n## Version Control / Diffing\n\n**What this covers:** Generating change-marked PDFs showing differences between document versions.\n\n| Tool | Purpose |\n|---------|---------|\n| `latexdiff` | Generate change-tracked LaTeX between two `.tex` files |\n| `latexdiff-vc` | Git-aware variant: diff against commits, branches, tags |\n| `latexrevise` | Accept/reject changes from latexdiff output |\n\n**Example:** Basic latexdiff usage\n```bash\n# Compare two files\nlatexdiff old.tex new.tex > diff.tex\npdflatex diff.tex\n\n# Result: PDF with deletions in red strikethrough, additions in blue\n```\n\n**Example:** Git integration\n```bash\n# Compare current file against previous commit\nlatexdiff-vc -r HEAD~1 document.tex\n\n# Compare against specific commit\nlatexdiff-vc -r abc123 document.tex\n\n# Compare between two commits\nlatexdiff-vc -r abc123 -r def456 document.tex\n```\n\n**Common pitfalls:**\n- latexdiff can fail on complex macros or environments\n- Use `--flatten` flag for multi-file documents with `\\input`\n- Math mode changes may not display correctly\n- Large documents may produce very slow-compiling diffs\n\n## Legal / Long Documents\n\n**What this covers:** Formatting for legal briefs, academic papers, and long-form professional documents.\n\n| Package | Purpose |\n|---------|---------|\n| `setspace` | Double/1.5 spacing for legal/academic docs |\n| `footmisc` | Footnote customization |\n| `lineno` | Line numbering (for legal documents, drafts) |\n| `multicol` | Multi-column layouts |\n\n**Example:** Legal document formatting\n```latex\n\\usepackage[doublespacing]{setspace}\n\\usepackage[left]{lineno}\n\\linenumbers\n\n\\usepackage[bottom]{footmisc} % Footnotes at page bottom\n\n\\begin{document}\n\\pagenumbering{roman} % i, ii, iii for front matter\n\\tableofcontents\n\n\\clearpage\n\\pagenumbering{arabic} % 1, 2, 3 for main content\n\nContent with line numbers and double spacing...\n\\end{document}\n```\n\n**Example:** Two-column layout\n```latex\n\\usepackage{multicol}\n\n\\begin{multicols}{2}\nText flows across two columns automatically.\nColumn breaks happen naturally.\n\\end{multicols}\n```\n\n**Common pitfalls:**\n- Line numbers from `lineno` may interfere with margin notes\n- `multicol` doesn't work with floats (figures/tables) by default\n- Double spacing affects equations unless you use `\\begin{singlespace}`\n- Footnote placement can be inconsistent with floats\n\n## Special Characters\n- `%` → `\\%`\n- ` latex-document-skill — Skillopedia → `\\ latex-document-skill — Skillopedia \n- `&` → `\\&`\n- `#` → `\\#`\n- `_` → `\\_`\n- `{` → `\\{`\n- `}` → `\\}`\n- `~` → `\\textasciitilde`\n- `^` → `\\textasciicircum`\n- `\\` → `\\textbackslash`\n- `--` → en-dash (ranges: 2019--2025)\n- `---` → em-dash (parenthetical)\n- `§` → `\\S` (section symbol)\n- `¶` → `\\P` (paragraph symbol)\n- `©` → `\\copyright`\n- `®` → `\\textregistered`\n- `™` → `\\texttrademark`\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":24477,"content_sha256":"93dd40e2065db642d412e6e093ac89e862f4b44b64d934d380e7ee67813fea25"},{"filename":"references/pdf-conversion.md","content":"# PDF-to-LaTeX Conversion Pipeline\n\n## Overview\n\nConvert PDFs of any type (handwritten notes, printed reports, legal contracts, math lectures) to LaTeX using a scaling strategy based on document size, with document-type profiles for accurate conversion.\n\n## Step 1: Determine Document Type\n\nScan a few representative pages and select the matching conversion profile:\n\n| Content Type | Profile | Key Indicators |\n|---|---|---|\n| Math / science | `references/profiles/math-notes.md` | Equations, theorems, proofs, Greek symbols, integrals |\n| Business | `references/profiles/business-document.md` | Data tables, bullet points, meeting notes, financial figures |\n| Legal | `references/profiles/legal-document.md` | Numbered clauses, \"WHEREAS\", signature blocks, articles/sections |\n| General | `references/profiles/general-notes.md` | Informal notes, mixed content, journals, letters |\n\nEach profile provides a suggested preamble, structural patterns to recognize, worker hints, and pitfalls.\n\n## Step 2: Prepare Images\n\n```bash\nbash \u003cskill_path>/scripts/pdf_to_images.sh input.pdf ./tmp/pages --dpi 200 --max-dim 2000\n```\n\nThis creates `page-001.png` through `page-NNN.png`, resized for API compatibility (max 2000px dimension).\n\n## Step 3: Apply Scaling Strategy\n\n### Empirical Basis\n\nTested on 15 identical pages with batch sizes 3, 5, 7, 10, and 15:\n\n| Batch Size | LaTeX Errors | Errors/Page | Content/Page | Structure Recognition |\n|---|---|---|---|---|\n| 3 | 0 | 0.00 | 22.3 lines | **Poor** (2 envs) -- structural blindness |\n| 5 | 1 | 0.07 | 24.3 lines | Good (9 envs) |\n| **7** | **0** | **0.00** | **24.8 lines** | **Best** (11 envs) |\n| 10 | 2 | 0.13 | 26.3 lines | Good (13 envs) |\n| 15 | 11 | 0.73 | 21.3 lines | Poor (5 envs) -- catastrophic errors |\n\n**Error analysis at 10 pages**: 2 structural errors -- an unclosed `\\begin{remark}` environment caused by a typo (`\\end{remark>}` instead of `\\end{remark}`). Not trivial, but fixable with one edit.\n\n**Error analysis at 15 pages**: 11 severe errors -- multiple unclosed environments, mismatched nesting (`\\begin{definition}` ended by `\\end{align*}`), stray `&` characters, math mode corruption. The model loses track of structural state past ~10 pages.\n\n### Scaling Thresholds\n\n| PDF Size | Strategy | Agents | Rationale |\n|---|---|---|---|\n| **1-10 pages** | Single agent | 1 | 0-2 minor errors, trivially fixable. Batching overhead (launching agents, merging files, fixing boundaries) exceeds the cost of fixing 2 errors. |\n| **11-20 pages** | Split in half | 2 | Error rate climbs steeply past 10 pages. Two agents of ~7-10 pages each stay in the low-error zone. One merge point to handle. |\n| **21+ pages** | Batch-7 pipeline | ceil(N/7) | Each agent gets 7 pages (0-error sweet spot). Full parallel processing with `run_in_background: true`. |\n\n### Why Not Always Batch at 7?\n\nBatching has real costs:\n- **Agent launch overhead**: Each agent needs the prompt, preamble reference, context about what comes before/after\n- **Merge complexity**: Concatenating files can introduce boundary errors (split mid-theorem, mid-proof)\n- **Coordination time**: Waiting for all agents, checking outputs, fixing merge points\n\nFor a 10-page PDF, splitting into 7+3 means: 2 agent launches + 1 merge point + potential boundary error vs. 1 agent with ~2 fixable errors. The single agent wins.\n\nFor a 25-page PDF, the single agent would produce ~15+ catastrophic errors. Three agents of ~8 each produce 0-2 errors total with 2 merge points. Batching wins decisively.\n\n## Step 4: Create Shared Preamble\n\nBefore launching workers, one agent scans 3-5 representative pages to build the preamble:\n\n1. Read the selected profile's suggested preamble as a starting point\n2. **For math-notes profile**: Default to **beautiful mode** -- copy the preamble from `assets/templates/lecture-notes.tex` (everything before `\\begin{document}`). This gives you tcolorbox theorem environments, TikZ graph styles, Palatino font, and microtype. Only use plain mode if the user explicitly requests it.\n3. Scan pages to identify additional packages or custom commands needed beyond the profile's base\n4. Write `tmp/preamble.tex` with everything from `\\documentclass` through the last `\\newcommand`\n5. Do NOT include `\\begin{document}` -- that goes in the assembly step\n\n## Step 5: Launch Workers\n\n### For single agent (1-10 pages):\n\nOne agent reads all page images and writes body-only LaTeX to `tmp/batch_001_NNN.tex`.\n\n### For split (11-20 pages):\n\nTwo agents, each with ~half the pages. Use `run_in_background: true` for the second agent.\n\n### For batch-7 pipeline (21+ pages):\n\nLaunch `ceil(N/7)` agents with `run_in_background: true`.\n\n**Worker prompt template**:\n```\nConvert pages [START]-[END] of the document to LaTeX body content.\n\nRead the preamble at [path/preamble.tex] for available commands and environments.\nRead the conversion profile at [path/profile.md] for structural patterns and hints.\nRead page images: [path/page-XXX.png] through [path/page-YYY.png]\n\nCONTEXT: You are continuing from [section/content context from previous batch].\nThe document is a [type: math notes / business report / legal contract / general notes].\n\nOUTPUT: Write ONLY to [path/batch_XXX_YYY.tex]\n\nRULES:\n- Output ONLY body content (no \\documentclass, \\usepackage, \\begin{document})\n- Use custom commands from preamble\n- Follow the structural patterns described in the profile\n- Be faithful to the original content\n- Close ALL open environments before the end of your output\n- Be CONCISE -- write the LaTeX, nothing else\n\nCRITICAL LATEX CONSTRAINTS (violation = compilation failure):\n\n1. UNDEFINED COMMANDS -- Do NOT use:\n - \\sout{} (use \\cancel{} instead, or plain strikethrough text)\n - \\circled{} (use \\textcircled{1} or the \\circled command if defined in preamble)\n - \\pentagon, \\hexagon, or invented symbol commands (draw shapes with TikZ instead)\n - Any command you are not certain exists. Check the preamble first.\n\n2. TIKZ SYNTAX:\n - EVERY \\node, \\draw, \\path command MUST end with semicolon ;\n - EVERY \\node MUST have label text in braces: \\node[vertex] (v1) at (0,0) {$v_1$};\n - Empty labels still need braces: \\node[vertex] (v1) at (0,0) {};\n - ALL TikZ commands MUST be inside \\begin{tikzpicture}...\\end{tikzpicture}\n - Use POLAR coordinates for circular layouts: (60:1.5cm) not ({cos(60)},{sin(60)})\n - edge/dedge/hedge are EDGE styles: use \\draw[edge], NEVER \\node[edge]\n\n3. ENVIRONMENT NESTING:\n - Do NOT use \\begin{table}[H] or \\begin{figure}[H] inside tcolorbox environments (theorem, example, definition, etc.)\n - Use \\begin{tabular} directly inside boxes (no table wrapper needed)\n - Do NOT put \\begin{tabular} inside align* or equation* environments\n - \\begin{proof} inside \\begin{example} is allowed, but you MUST close proof BEFORE closing example\n\n4. ENUMERATE/ITEMIZE:\n - Use \\begin{enumerate} without inline label options (labels are pre-configured in preamble)\n - First level: (i), (ii), (iii); second level: (a), (b), (c)\n - If you need a specific label, use: \\begin{enumerate}[label=(\\alph*)]\n\n5. COMMANDS AVAILABLE IN PREAMBLE (beautiful mode):\n - Number sets: \\R, \\N, \\Z, \\Q, \\C\n - Graph theory: \\V, \\E, \\deg, \\diam, \\dist, \\Aut, \\chr\n - Delimiters: \\abs{}, \\norm{}, \\floor{}, \\ceil{}\n - Circled numbers: \\circled{1}, \\circled{2}\n - Strikethrough: \\sout{text} (ulem loaded), \\cancel{expr} (in math)\n```\n\n## Step 6: Validate Batch Outputs\n\nBefore assembling, run the validation script on each batch file to catch errors early:\n\n```bash\npython3 \u003cskill_path>/scripts/validate_latex.py tmp/batch_*.tex --preamble tmp/preamble.tex\n```\n\nThis checks for:\n- Balanced `\\begin{}`/`\\end{}` environments\n- Undefined commands not present in preamble\n- `\\begin{table}[H]` or `\\begin{figure}[H]` inside tcolorbox environments\n- TikZ commands (`\\node`, `\\draw`) outside `\\begin{tikzpicture}`\n- Missing node labels (TikZ `\\node` without `{};`)\n\nFix any reported errors in the batch files BEFORE assembling.\n\n## Step 7: Assemble and Compile\n\nAfter all workers complete and validation passes:\n\n```bash\n# 1. Build the full document\ncat tmp/preamble.tex > outputs/document.tex\necho '' >> outputs/document.tex\necho '\\begin{document}' >> outputs/document.tex\necho '\\maketitle' >> outputs/document.tex # if title/author set in preamble\necho '\\tableofcontents' >> outputs/document.tex # if document has sections\necho '\\newpage' >> outputs/document.tex\nfor f in $(ls tmp/batch_*.tex | sort); do\n echo \"\" >> outputs/document.tex\n echo \"% === $(basename $f) ===\" >> outputs/document.tex\n cat \"$f\" >> outputs/document.tex\ndone\necho '' >> outputs/document.tex\necho '\\end{document}' >> outputs/document.tex\n\n# 2. Compile\nbash \u003cskill_path>/scripts/compile_latex.sh outputs/document.tex --preview --preview-dir outputs\n```\n\n### If compilation fails:\n\n1. Read the `.log` file for error details\n2. For large documents (20+ pages), use **parallel error-fixing agents**: split the body into N sections (e.g., 5), assign each to an agent, fix independently, then reassemble\n3. Common fixes:\n - **Mismatched `\\begin`/`\\end`**: Find and close orphaned environments\n - **Misplaced `&`**: Ensure `&` only appears inside tabular/align environments\n - **Undefined commands**: Add missing `\\newcommand` to preamble or remove the command usage\n - **Package conflicts**: Remove `hyperref` if `\\set@color` errors appear\n - **Missing ` latex-document-skill — Skillopedia **: Find unclosed inline math\n - **`\\newcommand` conflict**: Use `\\renewcommand` if overriding a built-in command (e.g., `\\deg`)\n - **CT@row@color errors**: Caused by `\\begin{tabular}` inside math environments -- move tabular outside\n - **\"Not in outer par mode\"**: Caused by `\\begin{table}[H]` inside tcolorbox -- remove the `table` wrapper\n - **TikZ \"Undefined control sequence\"**: TikZ commands outside `\\begin{tikzpicture}` -- find and wrap them\n4. Fix errors in the `.tex` file and recompile\n\n## Scaling Examples\n\n| Document | Pages | Agents | Batch Config |\n|---|---|---|---|\n| Meeting notes | 3 | 1 | Single agent |\n| Contract | 8 | 1 | Single agent |\n| Quarterly report | 15 | 2 | 8 + 7 |\n| Thesis chapter | 20 | 2 | 10 + 10 |\n| Full textbook chapter | 30 | 5 | 7+7+7+7+2 |\n| Course notes | 50 | 8 | 7 each, last gets 1 |\n| Full textbook | 100 | 15 | 7 each, last gets 2 |\n| Lecture series | 115 | 17 | 7 each, last gets 3 |\n| Large manual | 200 | 29 | 7 each, last gets 4 |\n\n## Common Pitfalls (All Document Types)\n\n1. **Do NOT use `sed` to clean control characters**. Regex `[^[:print:][:space:]]` strips `\\b`, `\\t`, `\\n`, `\\e` which destroys `\\begin`, `\\tableofcontents`, `\\newpage`, `\\end`.\n\n2. **Do NOT use `hyperref` in converted documents**. Causes `\\set@color` / `\\@pdfcolorstack` errors with theorem environments and colored text.\n\n3. **Always compile from a clean directory** if the compile script has issues with stale aux files.\n\n4. **Workers must be CONCISE**. Agents that add verbose comments or explanations waste context window and may overflow.\n\n5. **Close environments at batch boundaries**. If a proof/theorem/table spans the end of a batch, close it and add a comment: `% continues in next batch`.\n\n6. **Select the correct profile**. A math profile on a business document will produce unnecessary theorem environments. A business profile on math notes will miss structural patterns.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11321,"content_sha256":"7e654317e4a6aa169d9a59cae4e51771247a62d646e01acb34d2143c2174ae78"},{"filename":"references/pdf-extraction-prompts.md","content":"# PDF-to-Cheatsheet: LLM Prompt Templates\n\nReady-to-use prompts for each stage of extracting content from large academic PDFs and compressing into cheat sheets.\n\n---\n\n## Stage 1: Document Structure Analysis\n\n### Prompt: Build Structure Map\n```\nYou are analyzing an academic document to create a cheat sheet. This is the beginning of a [PAGES]-page document.\n\nAnalyze the content and produce a structured outline:\n\nFor each chapter/major section:\n- Title\n- Approximate page range\n- Key topics covered\n- Content type: THEORY | APPLIED | EXAMPLES | EXERCISES | REFERENCE\n- Importance for exams: HIGH | MEDIUM | LOW\n\nImportance signals:\n- Boxed content, numbered theorems = HIGH\n- Worked examples showing techniques = MEDIUM\n- Historical context, motivation = LOW\n- End-of-chapter summaries = HIGH (professor-curated)\n\nOutput as a structured list. Be thorough.\n```\n\n---\n\n## Stage 2: Content Extraction\n\n### Prompt: Mathematics (Calculus, Linear Algebra, Analysis)\n```\nExtract ALL exam-relevant content from this mathematics section. Be exhaustive.\n\nEXTRACT:\n1. **Formulas**: Every equation, with all variables defined\n2. **Theorems**: Name + formal statement + conditions for applicability\n3. **Definitions**: Term + precise mathematical definition\n4. **Lemmas/Corollaries**: Statement + which theorem they support\n5. **Proof techniques**: Name + core trick (not full proof)\n6. **Common pitfalls**: Mistakes students frequently make\n\nFORMAT each item as:\n[TYPE] Name/Label\nContent in LaTeX: $...$\nWhen to use: (one line)\nPrerequisites: (what must be known)\n\nPRESERVE all LaTeX mathematical notation exactly as written.\nUse \\frac, \\sum, \\int, \\lim, etc. for all math expressions.\nSKIP: motivational text, history, lengthy explanations, full proofs.\n```\n\n### Prompt: Computer Science (Algorithms, Data Structures, Theory)\n```\nExtract ALL exam-relevant content from this computer science section. Be exhaustive.\n\nEXTRACT:\n1. **Algorithms**: Name, key steps (compact pseudocode), time complexity O(...), space complexity\n2. **Data structures**: Operations with complexities, when to use each\n3. **Theorems**: Formal statements (especially: NP-completeness, decidability, lower bounds)\n4. **Definitions**: Precise CS definitions (e.g., \"a graph G is bipartite iff...\")\n5. **Comparison tables**: X vs Y (e.g., BFS vs DFS, array vs linked list)\n6. **Design patterns**: Name + when to apply + core idea\n\nFORMAT:\n- Algorithms as numbered step-lists (max 5-7 steps)\n- Complexities in Big-O notation\n- Tables as | col1 | col2 | col3 | format\n\nSKIP: implementation details, code in specific languages (keep pseudocode), long proofs.\n```\n\n### Prompt: Physics (Mechanics, E&M, Quantum, Thermo)\n```\nExtract ALL exam-relevant content from this physics section. Be exhaustive.\n\nEXTRACT:\n1. **Equations**: In standard form with SI units for EVERY variable\n2. **Laws/Principles**: Name + equation + applicability conditions\n3. **Constants**: Symbol, value, units (e.g., $c = 3 \\times 10^8$ m/s)\n4. **Approximations**: When valid (e.g., \"for $v \\ll c$\", \"small angle: $\\sin\\theta \\approx \\theta$\")\n5. **Sign conventions**: Which direction is positive, reference frames\n6. **Key relationships**: How quantities relate (e.g., \"F and a are in same direction\")\n\nFORMAT:\n- Each equation on its own line with variable legend\n- Note which form to use when (e.g., \"use $F=qv\\times B$ for moving charges\")\n- Group by topic (e.g., Kinematics, Dynamics, Energy)\n\nSKIP: derivations (unless the derivation technique itself is testable), history.\n```\n\n### Prompt: Chemistry (Organic, Inorganic, Physical)\n```\nExtract ALL exam-relevant content from this chemistry section. Be exhaustive.\n\nEXTRACT:\n1. **Reactions**: Reactants → Products, with conditions (catalyst, temperature, solvent)\n2. **Mechanisms**: Step-by-step with arrow notation (nucleophilic attack, etc.)\n3. **Equilibrium expressions**: Ka, Kb, Ksp, Kw with formulas\n4. **Nomenclature rules**: IUPAC naming conventions, functional group priorities\n5. **Periodic trends**: Electronegativity, atomic radius, ionization energy patterns\n6. **Constants**: Gas constant R, Avogadro's number, Faraday constant, etc.\n\nFORMAT:\n- Reactions: A + B → C + D (conditions above arrow)\n- Mechanisms: numbered steps\n- Use standard chemistry notation\n\nSKIP: historical discovery, detailed lab procedures.\n```\n\n### Prompt: Biology (Molecular, Genetics, Ecology)\n```\nExtract ALL exam-relevant content from this biology section. Be exhaustive.\n\nEXTRACT:\n1. **Processes/Cycles**: Stage-by-stage (e.g., \"Krebs: 1) Acetyl-CoA + OAA → Citrate, 2)...\")\n2. **Pathways**: Input → [steps] → Output, with key enzymes\n3. **Classifications**: Taxonomic hierarchies, domain/kingdom/phylum\n4. **Comparative tables**: Feature comparison (e.g., DNA vs RNA, mitosis vs meiosis)\n5. **Key molecules**: Name, function, location\n6. **Regulatory mechanisms**: What activates/inhibits what\n\nFORMAT:\n- Cycles as numbered stage-lists\n- Pathways as: Input →(enzyme)→ Intermediate →(enzyme)→ Output\n- Comparisons as tables\n\nSKIP: detailed experimental methods, case studies.\n```\n\n### Prompt: Statistics & Probability\n```\nExtract ALL exam-relevant content from this statistics/probability section. Be exhaustive.\n\nEXTRACT:\n1. **Distributions**: Name, PDF/PMF formula, mean, variance, when to use\n2. **Formulas**: All statistical formulas (mean, variance, std dev, correlation, regression)\n3. **Theorems**: CLT, LLN, Bayes' theorem, etc. with formal statements\n4. **Test procedures**: Name, null hypothesis form, test statistic, rejection rule\n5. **Assumptions**: What each test requires (normality, independence, etc.)\n6. **Tables**: Critical values, common distribution parameters\n\nFORMAT:\n- Distributions: Name | $f(x) = ...$ | $E[X] = ...$ | $Var(X) = ...$ | Use when: ...\n- Tests: Name | $H_0$ | Test stat | Reject when | Assumptions\n\nSKIP: lengthy examples, simulation descriptions.\n```\n\n### Prompt: Engineering (General)\n```\nExtract ALL exam-relevant content from this engineering section. Be exhaustive.\n\nEXTRACT:\n1. **Design equations**: With all variables, units, and applicable standards\n2. **Procedures**: Step-by-step design/analysis methods\n3. **Safety factors**: Required values for different scenarios\n4. **Material properties**: Tables of values (yield strength, modulus, etc.)\n5. **Code references**: AISC, ASME, NEC, etc. with relevant clause numbers\n6. **Conversion factors**: Between unit systems\n\nFORMAT:\n- Equations with units explicitly stated\n- Procedures as numbered checklists\n- Reference values in tables\n\nSKIP: detailed case studies, historical context.\n```\n\n---\n\n## Stage 3: Content Compression\n\n### Prompt: Compress to Cheat Sheet Density\n```\nYou have [N] extracted items for a cheat sheet. The target is 2 pages (approximately 60-80 items, ~1000 words of content).\n\nCurrent items:\n[INSERT ALL EXTRACTED ITEMS HERE]\n\nTasks:\n1. RANK all items by exam-lookup-probability (how likely a student needs this during an exam)\n2. MERGE items that are redundant or highly related (e.g., multiple forms of same equation)\n3. COMPRESS each item to minimum words while preserving meaning:\n - Definitions: one-line maximum\n - Formulas: just the equation + variable legend\n - Theorems: statement + conditions only\n - Procedures: max 5 numbered steps\n4. CUT lowest-priority items to hit the page target\n5. ORGANIZE remaining items by topic in logical lookup order\n\nApply these compression techniques:\n- Use symbols: → ⇒ ∀ ∃ ⇔ ∴ s.t. iff wrt\n- Eliminate filler: \"is defined as\" → \":\", \"it follows that\" → \"⇒\"\n- Inline short equations instead of display mode\n- Stack related formulas horizontally where possible\n\nOutput: The final compressed content, organized by section, ready for LaTeX formatting.\n```\n\n### Prompt: Convert to LaTeX Format\n```\nConvert this cheat sheet content into LaTeX using the [exam/general/code] template format.\n\nTemplate environments available:\n- \\sheetsection{Title} — major section headers\n- \\sheetsubsection{Title} — subsection headers\n- \\begin{thmbox}{Name} — for theorems (most important results)\n- \\begin{defbox}{Name} — for definitions\n- \\begin{formulabox}{Name} — for formulas/equations\n- \\begin{procbox}{Name} — for procedures/algorithms\n\nRules:\n- NO blank lines between consecutive box environments\n- Use $...$ for inline math, \\begin{align*} for display math\n- Use \\tfrac not \\frac in inline math\n- Use \\textstyle in align* environments for compact math\n- Use \\hfill to put two short formulas on one line\n- Use @{} in tabular column specs to remove padding\n- Keep variable definitions on same line as formula where possible\n- Use \\fontsize{5.5pt}{6.5pt}\\selectfont for less-critical content\n\nContent to format:\n[INSERT COMPRESSED CONTENT HERE]\n\nOutput: Complete LaTeX code for the content area (between \\begin{multicols} and \\end{multicols}).\n```\n\n---\n\n## Stage 4: Quality & Space Management\n\n### Prompt: Verify Mathematical Correctness\n```\nReview these LaTeX math expressions for correctness:\n\n[INSERT ALL MATH EXPRESSIONS]\n\nFor each expression, check:\n1. Is the LaTeX syntax valid? (matching braces, proper commands)\n2. Is the mathematical content correct? (signs, indices, limits)\n3. Are variable definitions consistent across the document?\n4. Are there any missing conditions or constraints?\n\nReport any errors found with corrections.\n```\n\n### Prompt: Space Budget Check\n```\nThis cheat sheet content must fit on [1/2] page(s) with these settings:\n- Font: [6pt/7pt]\n- Columns: [2/3/4]\n- Orientation: [portrait/landscape]\n- Paper: [letter/A4]\n\nEstimated capacity: [N] lines per column × [M] columns × [P] pages = [TOTAL] lines\n\nCurrent content has approximately [X] items.\n\nIf over budget: suggest specific items to cut or compress further.\nIf under budget: suggest what to add from the source material.\nIf close to budget: suggest using \\scalebox{0.95} or \\enlargethispage{1cm} for fine adjustment.\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9887,"content_sha256":"fed7ed4a0d4751cd9906e617da0c4bfde35542a56dc69c0d4745b4144f24b136"},{"filename":"references/pdf-operations.md","content":"# PDF Operations Reference Guide\n\nComprehensive reference for advanced PDF manipulation beyond the LaTeX compilation pipeline. Covers form filling, text/table extraction, OCR, programmatic creation, watermarking, rotation, metadata, and more.\n\n## Python Libraries Overview\n\n| Library | License | Best For |\n|---|---|---|\n| **pypdf** | BSD | Form filling, merging, splitting, metadata, watermarking, rotation, encryption |\n| **pdfplumber** | MIT | Text extraction with coordinates, table extraction with fine-tuned settings |\n| **reportlab** | BSD | Programmatic PDF creation from scratch (Canvas API + Platypus high-level) |\n| **pypdfium2** | Apache/BSD | Fast rendering, text extraction, alternative to poppler |\n| **pytesseract** | Apache | OCR for scanned PDFs (wrapper around Tesseract) |\n| **pdf2image** | MIT | Convert PDF pages to PIL images (wrapper around poppler) |\n\nAll Python libraries auto-install via `_ensure_package()` in the skill's scripts.\n\n---\n\n## Form Filling Workflow\n\n### Step 1: Check if the PDF has fillable fields\n\n```bash\npython3 \u003cskill_path>/scripts/pdf_check_form.py form.pdf\n```\n\nThis determines which workflow to follow:\n- **Fillable** -- use `pdf_extract_fields.py` + `pdf_fill_form.py`\n- **Non-fillable** -- use `pdf_fill_annotations.py` with visual analysis\n\n### Fillable PDF Workflow\n\n```bash\n# 1. Extract field metadata to JSON\npython3 \u003cskill_path>/scripts/pdf_extract_fields.py form.pdf field_info.json\n\n# 2. Create field_values.json with values for each field\n# Format: [{\"field_id\": \"name\", \"page\": 1, \"value\": \"John Smith\"}, ...]\n\n# 3. Fill the form (validates field IDs, pages, and values before writing)\npython3 \u003cskill_path>/scripts/pdf_fill_form.py form.pdf field_values.json filled.pdf\n```\n\n**Field types supported:**\n\n| Type | JSON Format | Example |\n|---|---|---|\n| Text | `{\"field_id\": \"name\", \"page\": 1, \"value\": \"John\"}` | Free text entry |\n| Checkbox | `{\"field_id\": \"agree\", \"page\": 1, \"value\": \"/Yes\"}` | Use `checked_value` or `unchecked_value` from field_info |\n| Radio group | `{\"field_id\": \"gender\", \"page\": 1, \"value\": \"/Male\"}` | Use one of `radio_options[].value` |\n| Choice/dropdown | `{\"field_id\": \"country\", \"page\": 2, \"value\": \"US\"}` | Use one of `choice_options[].value` |\n\n### Non-Fillable PDF Workflow\n\n```bash\n# 1. Convert PDF to images for visual analysis\nbash \u003cskill_path>/scripts/pdf_to_images.sh form.pdf ./tmp/pages\n\n# 2. Examine images and create fields.json with bounding boxes\n# (See fields.json format below)\n\n# 3. Create validation images to verify bounding box accuracy\npython3 \u003cskill_path>/scripts/pdf_validate_boxes.py fields.json \\\n --image ./tmp/pages/page-001.png --output validation.png --page 1\n\n# 4. Validate bounding boxes (no intersections, adequate height)\npython3 \u003cskill_path>/scripts/pdf_validate_boxes.py fields.json\n\n# 5. Fill the form with text annotations\npython3 \u003cskill_path>/scripts/pdf_fill_annotations.py form.pdf fields.json filled.pdf\n```\n\n**fields.json format:**\n```json\n{\n \"pages\": [\n {\"page_number\": 1, \"image_width\": 1654, \"image_height\": 2339}\n ],\n \"form_fields\": [\n {\n \"page_number\": 1,\n \"description\": \"Last name field\",\n \"field_label\": \"Last name\",\n \"label_bounding_box\": [30, 125, 95, 142],\n \"entry_bounding_box\": [100, 125, 280, 142],\n \"entry_text\": {\n \"text\": \"Johnson\",\n \"font_size\": 14,\n \"font_color\": \"000000\"\n }\n }\n ]\n}\n```\n\nBounding boxes use image coordinates: `[left, top, right, bottom]` with origin at top-left.\n\n---\n\n## Text & Table Extraction (pdfplumber)\n\n### Basic text extraction\n\n```python\nimport pdfplumber\n\nwith pdfplumber.open(\"document.pdf\") as pdf:\n for page in pdf.pages:\n text = page.extract_text()\n print(text)\n```\n\n### Text with coordinates\n\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n page = pdf.pages[0]\n for word in page.extract_words():\n print(f\"{word['text']} at ({word['x0']:.1f}, {word['top']:.1f})\")\n```\n\n### Table extraction\n\n```python\nwith pdfplumber.open(\"document.pdf\") as pdf:\n page = pdf.pages[0]\n tables = page.extract_tables()\n for table in tables:\n for row in table:\n print(row)\n```\n\n### Advanced table settings\n\n```python\ntable_settings = {\n \"vertical_strategy\": \"lines\", # \"lines\", \"text\", \"explicit\"\n \"horizontal_strategy\": \"lines\",\n \"snap_tolerance\": 3,\n \"join_tolerance\": 3,\n \"edge_min_length\": 3,\n \"min_words_vertical\": 3,\n \"min_words_horizontal\": 1,\n}\n\ntables = page.extract_tables(table_settings)\n```\n\n### Export to pandas/Excel\n\n```python\nimport pandas as pd\nimport pdfplumber\n\nwith pdfplumber.open(\"report.pdf\") as pdf:\n all_tables = []\n for page in pdf.pages:\n tables = page.extract_tables()\n for table in tables:\n df = pd.DataFrame(table[1:], columns=table[0])\n all_tables.append(df)\n\n # Combine and export\n combined = pd.concat(all_tables, ignore_index=True)\n combined.to_excel(\"extracted_tables.xlsx\", index=False)\n```\n\n---\n\n## OCR for Scanned PDFs\n\n### Basic OCR with pytesseract\n\n```python\nimport pytesseract\nfrom pdf2image import convert_from_path\n\ndef ocr_pdf(pdf_path):\n \"\"\"Extract text from a scanned PDF using OCR.\"\"\"\n images = convert_from_path(pdf_path, dpi=300)\n text = \"\"\n for i, image in enumerate(images):\n page_text = pytesseract.image_to_string(image)\n text += f\"\\n--- Page {i+1} ---\\n{page_text}\"\n return text\n```\n\n### OCR with language support\n\n```python\n# For non-English documents\ntext = pytesseract.image_to_string(image, lang='fra') # French\ntext = pytesseract.image_to_string(image, lang='deu') # German\ntext = pytesseract.image_to_string(image, lang='jpn') # Japanese\ntext = pytesseract.image_to_string(image, lang='eng+fra') # Multi-language\n```\n\n### OCR with bounding boxes\n\n```python\n# Get word-level bounding boxes\ndata = pytesseract.image_to_data(image, output_type=pytesseract.Output.DICT)\nfor i, word in enumerate(data['text']):\n if word.strip():\n x, y, w, h = data['left'][i], data['top'][i], data['width'][i], data['height'][i]\n conf = data['conf'][i]\n print(f\"{word} at ({x},{y},{w},{h}) confidence={conf}\")\n```\n\n### Smart extraction (try text first, fall back to OCR)\n\n```python\nimport pdfplumber\nimport pytesseract\nfrom pdf2image import convert_from_path\n\ndef extract_text_smart(pdf_path):\n \"\"\"Try pdfplumber first; if no text found, fall back to OCR.\"\"\"\n with pdfplumber.open(pdf_path) as pdf:\n text = \"\"\n for page in pdf.pages:\n page_text = page.extract_text()\n if page_text and page_text.strip():\n text += page_text + \"\\n\"\n\n if text.strip():\n return text\n\n # Fall back to OCR\n images = convert_from_path(pdf_path, dpi=300)\n ocr_text = \"\"\n for image in images:\n ocr_text += pytesseract.image_to_string(image) + \"\\n\"\n return ocr_text\n```\n\n---\n\n## Programmatic PDF Creation (reportlab)\n\n### Canvas API (low-level)\n\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.pdfgen import canvas\n\nc = canvas.Canvas(\"output.pdf\", pagesize=letter)\nwidth, height = letter\n\n# Text\nc.setFont(\"Helvetica-Bold\", 24)\nc.drawString(72, height - 72, \"Document Title\")\n\nc.setFont(\"Helvetica\", 12)\nc.drawString(72, height - 120, \"This is body text.\")\n\n# Shapes\nc.setStrokeColorRGB(0.2, 0.5, 0.8)\nc.setFillColorRGB(0.9, 0.95, 1.0)\nc.rect(72, height - 200, 200, 50, fill=1)\n\n# Lines\nc.line(72, height - 220, 540, height - 220)\n\n# Images\nc.drawImage(\"logo.png\", 72, height - 350, width=150, height=100)\n\nc.save()\n```\n\n### Platypus (high-level with flowables)\n\n```python\nfrom reportlab.lib.pagesizes import letter\nfrom reportlab.lib.styles import getSampleStyleSheet\nfrom reportlab.lib.units import inch\nfrom reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle\nfrom reportlab.lib import colors\n\ndoc = SimpleDocTemplate(\"report.pdf\", pagesize=letter)\nstyles = getSampleStyleSheet()\nstory = []\n\n# Title\nstory.append(Paragraph(\"Monthly Report\", styles['Title']))\nstory.append(Spacer(1, 0.5 * inch))\n\n# Body text\nstory.append(Paragraph(\"This report covers Q4 performance metrics.\", styles['Normal']))\nstory.append(Spacer(1, 0.25 * inch))\n\n# Table\ndata = [\n ['Metric', 'Q3', 'Q4', 'Change'],\n ['Revenue', '$1.2M', '$1.5M', '+25%'],\n ['Users', '10,000', '15,000', '+50%'],\n ['Churn', '5%', '3%', '-40%'],\n]\ntable = Table(data, colWidths=[1.5*inch, 1*inch, 1*inch, 1*inch])\ntable.setStyle(TableStyle([\n ('BACKGROUND', (0, 0), (-1, 0), colors.HexColor('#2C3E50')),\n ('TEXTCOLOR', (0, 0), (-1, 0), colors.white),\n ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),\n ('ALIGN', (1, 0), (-1, -1), 'CENTER'),\n ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),\n ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.HexColor('#ECF0F1')]),\n]))\nstory.append(table)\n\ndoc.build(story)\n```\n\n---\n\n## Watermarking Existing PDFs\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom reportlab.pdfgen import canvas\nfrom reportlab.lib.pagesizes import letter\nimport io\n\ndef add_watermark(input_pdf, output_pdf, watermark_text=\"CONFIDENTIAL\"):\n \"\"\"Add a diagonal text watermark to every page.\"\"\"\n # Create watermark PDF in memory\n packet = io.BytesIO()\n c = canvas.Canvas(packet, pagesize=letter)\n c.setFont(\"Helvetica-Bold\", 60)\n c.setFillColorRGB(0.85, 0.85, 0.85) # Light gray\n c.saveState()\n c.translate(300, 400)\n c.rotate(45)\n c.drawCentredString(0, 0, watermark_text)\n c.restoreState()\n c.save()\n packet.seek(0)\n\n watermark_reader = PdfReader(packet)\n watermark_page = watermark_reader.pages[0]\n\n reader = PdfReader(input_pdf)\n writer = PdfWriter()\n\n for page in reader.pages:\n page.merge_page(watermark_page)\n writer.add_page(page)\n\n with open(output_pdf, \"wb\") as f:\n writer.write(f)\n```\n\n---\n\n## Page Rotation & Cropping\n\n### Rotation\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n page.rotate(90) # 90, 180, 270 degrees clockwise\n writer.add_page(page)\n\nwith open(\"rotated.pdf\", \"wb\") as f:\n writer.write(f)\n```\n\n### Cropping\n\n```python\nfrom pypdf import PdfReader, PdfWriter\n\nreader = PdfReader(\"input.pdf\")\nwriter = PdfWriter()\n\nfor page in reader.pages:\n # Crop to specific region (in PDF points, 72 points = 1 inch)\n page.mediabox.lower_left = (72, 72) # 1 inch from left, 1 inch from bottom\n page.mediabox.upper_right = (540, 720) # 7.5 inches wide, 10 inches tall\n writer.add_page(page)\n\nwith open(\"cropped.pdf\", \"wb\") as f:\n writer.write(f)\n```\n\n---\n\n## Metadata Extraction\n\n```python\nfrom pypdf import PdfReader\n\nreader = PdfReader(\"document.pdf\")\n\n# Basic metadata\nmeta = reader.metadata\nprint(f\"Title: {meta.title}\")\nprint(f\"Author: {meta.author}\")\nprint(f\"Subject: {meta.subject}\")\nprint(f\"Creator: {meta.creator}\")\nprint(f\"Producer: {meta.producer}\")\nprint(f\"Creation date: {meta.creation_date}\")\nprint(f\"Modification date: {meta.modification_date}\")\n\n# Page count and dimensions\nprint(f\"Pages: {len(reader.pages)}\")\nfor i, page in enumerate(reader.pages):\n box = page.mediabox\n print(f\" Page {i+1}: {float(box.width):.0f} x {float(box.height):.0f} points\")\n```\n\n---\n\n## Image Extraction (CLI)\n\n```bash\n# Extract all images from a PDF using poppler-utils\npdfimages -all document.pdf ./images/prefix\n\n# Extract as PNG only\npdfimages -png document.pdf ./images/prefix\n\n# Extract from specific pages\npdfimages -f 1 -l 5 -png document.pdf ./images/prefix\n\n# List images without extracting\npdfimages -list document.pdf\n```\n\n---\n\n## JavaScript Libraries\n\n### pdf-lib (Node.js -- create and modify PDFs)\n\n```javascript\nconst { PDFDocument, rgb, StandardFonts } = require('pdf-lib');\nconst fs = require('fs');\n\nasync function createPDF() {\n const doc = await PDFDocument.create();\n const page = doc.addPage([612, 792]); // Letter size\n const font = await doc.embedFont(StandardFonts.HelveticaBold);\n\n page.drawText('Hello from pdf-lib!', {\n x: 50, y: 700, size: 30, font, color: rgb(0, 0.2, 0.6)\n });\n\n const bytes = await doc.save();\n fs.writeFileSync('output.pdf', bytes);\n}\n\nasync function modifyPDF() {\n const bytes = fs.readFileSync('existing.pdf');\n const doc = await PDFDocument.load(bytes);\n const pages = doc.getPages();\n const firstPage = pages[0];\n\n firstPage.drawText('Added text', {\n x: 50, y: 50, size: 14, color: rgb(1, 0, 0)\n });\n\n const modified = await doc.save();\n fs.writeFileSync('modified.pdf', modified);\n}\n```\n\n### pdfjs-dist (Browser/Node.js -- read and render PDFs)\n\n```javascript\nconst pdfjsLib = require('pdfjs-dist');\n\nasync function extractText(pdfPath) {\n const doc = await pdfjsLib.getDocument(pdfPath).promise;\n for (let i = 1; i \u003c= doc.numPages; i++) {\n const page = await doc.getPage(i);\n const content = await page.getTextContent();\n const text = content.items.map(item => item.str).join(' ');\n console.log(`Page ${i}: ${text}`);\n }\n}\n```\n\n---\n\n## Advanced CLI Operations\n\n### poppler-utils\n\n```bash\n# Extract text with layout preservation\npdftotext -layout document.pdf output.txt\n\n# Extract text from specific pages\npdftotext -f 3 -l 7 document.pdf output.txt\n\n# Get PDF info (page count, dimensions, metadata)\npdfinfo document.pdf\n\n# Get bounding box layout info\npdftotext -bbox-layout document.pdf output.html\n\n# High-quality image conversion\npdftoppm -png -r 300 document.pdf output_prefix\npdftoppm -jpeg -r 150 -f 1 -l 1 document.pdf single_page\n```\n\n### qpdf (repair and debug)\n\n```bash\n# Check PDF integrity\nqpdf --check document.pdf\n\n# Repair a corrupted PDF\nqpdf --replace-input document.pdf\n\n# Linearize for web (fast first-page display)\nqpdf --linearize input.pdf output.pdf\n\n# Decrypt a PDF (if you have the password)\nqpdf --decrypt --password=secret encrypted.pdf decrypted.pdf\n\n# Show PDF structure (debugging)\nqpdf --show-object=1 document.pdf\nqpdf --show-pages document.pdf\n```\n\n---\n\n## Batch Processing Patterns\n\n### Process multiple PDFs with error handling\n\n```python\nfrom pathlib import Path\nimport logging\n\nlogging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')\nlogger = logging.getLogger(__name__)\n\ndef batch_process(input_dir, output_dir, process_func):\n \"\"\"Process all PDFs in a directory with error handling.\"\"\"\n input_path = Path(input_dir)\n output_path = Path(output_dir)\n output_path.mkdir(parents=True, exist_ok=True)\n\n pdfs = sorted(input_path.glob(\"*.pdf\"))\n logger.info(f\"Found {len(pdfs)} PDFs to process\")\n\n results = {\"success\": 0, \"failed\": 0, \"errors\": []}\n for pdf in pdfs:\n try:\n out_file = output_path / pdf.name\n process_func(str(pdf), str(out_file))\n results[\"success\"] += 1\n logger.info(f\"OK: {pdf.name}\")\n except Exception as e:\n results[\"failed\"] += 1\n results[\"errors\"].append((pdf.name, str(e)))\n logger.error(f\"FAIL: {pdf.name}: {e}\")\n\n logger.info(f\"Done: {results['success']} succeeded, {results['failed']} failed\")\n return results\n```\n\n### Parallel processing with concurrent.futures\n\n```python\nfrom concurrent.futures import ProcessPoolExecutor, as_completed\n\ndef batch_process_parallel(input_dir, output_dir, process_func, max_workers=4):\n \"\"\"Process PDFs in parallel.\"\"\"\n input_path = Path(input_dir)\n output_path = Path(output_dir)\n output_path.mkdir(parents=True, exist_ok=True)\n\n pdfs = sorted(input_path.glob(\"*.pdf\"))\n\n with ProcessPoolExecutor(max_workers=max_workers) as executor:\n futures = {}\n for pdf in pdfs:\n out_file = output_path / pdf.name\n future = executor.submit(process_func, str(pdf), str(out_file))\n futures[future] = pdf.name\n\n for future in as_completed(futures):\n name = futures[future]\n try:\n future.result()\n print(f\"OK: {name}\")\n except Exception as e:\n print(f\"FAIL: {name}: {e}\")\n```\n\n---\n\n## Performance Optimization\n\n### Large PDF handling\n\n```python\n# Stream reading for large files (pypdf)\nfrom pypdf import PdfReader\n\nreader = PdfReader(\"large.pdf\")\n# Process one page at a time instead of loading all\nfor i in range(len(reader.pages)):\n page = reader.pages[i]\n text = page.extract_text()\n # Process text immediately, don't accumulate\n process_page(i, text)\n```\n\n### Memory management for pdfplumber\n\n```python\nimport pdfplumber\n\n# Process pages individually to avoid memory issues\nwith pdfplumber.open(\"large.pdf\") as pdf:\n for i, page in enumerate(pdf.pages):\n tables = page.extract_tables()\n text = page.extract_text()\n # Process and discard\n save_results(i, tables, text)\n # pdfplumber releases page resources automatically\n```\n\n### Chunked merging for many PDFs\n\n```python\nfrom pypdf import PdfReader, PdfWriter\nfrom pathlib import Path\n\ndef merge_pdfs_chunked(pdf_paths, output_path, chunk_size=50):\n \"\"\"Merge many PDFs in chunks to avoid memory issues.\"\"\"\n if len(pdf_paths) \u003c= chunk_size:\n writer = PdfWriter()\n for path in pdf_paths:\n writer.append(str(path))\n with open(output_path, \"wb\") as f:\n writer.write(f)\n return\n\n # Merge in chunks, then merge the chunks\n temp_files = []\n for i in range(0, len(pdf_paths), chunk_size):\n chunk = pdf_paths[i:i + chunk_size]\n temp_path = f\"/tmp/chunk_{i}.pdf\"\n writer = PdfWriter()\n for path in chunk:\n writer.append(str(path))\n with open(temp_path, \"wb\") as f:\n writer.write(f)\n temp_files.append(temp_path)\n\n # Final merge of chunks\n merge_pdfs_chunked(temp_files, output_path, chunk_size)\n```\n\n---\n\n## Troubleshooting Common Issues\n\n### Encrypted PDFs\n\n```python\nfrom pypdf import PdfReader\n\ntry:\n reader = PdfReader(\"encrypted.pdf\")\n if reader.is_encrypted:\n reader.decrypt(\"password\")\nexcept Exception as e:\n print(f\"Failed to decrypt: {e}\")\n```\n\n### Corrupted PDFs\n\n```bash\n# Check and repair with qpdf\nqpdf --check corrupted.pdf\nqpdf --replace-input corrupted.pdf\n```\n\n### Text extraction returns empty\n\n```python\n# Likely a scanned PDF -- fall back to OCR\nimport pytesseract\nfrom pdf2image import convert_from_path\n\ndef extract_text_with_ocr(pdf_path):\n images = convert_from_path(pdf_path, dpi=300)\n text = \"\"\n for image in images:\n text += pytesseract.image_to_string(image)\n return text\n```\n\n### pypdf form filling bug with selection lists\n\nThe skill's `pdf_fill_form.py` includes a monkey-patch for a pypdf bug where `get_inherited` returns list-of-pairs instead of strings for selection list options. This is handled automatically.\n\n---\n\n## License Information\n\n- **pypdf**: BSD License\n- **pdfplumber**: MIT License\n- **pypdfium2**: Apache/BSD License\n- **reportlab**: BSD License\n- **poppler-utils**: GPL-2 License\n- **qpdf**: Apache License\n- **pdf-lib**: MIT License\n- **pdfjs-dist**: Apache License\n- **pytesseract**: Apache License\n- **pdf2image**: MIT License\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":19178,"content_sha256":"79f7fcc3f585f9f046b4234b440053522372f50d9608afc4196f7c943fef9472"},{"filename":"references/poster-design-guide.md","content":"# Poster Design Guide\n\nComprehensive reference for creating professional academic conference posters. Read this when creating any poster.\n\n## Conference Size Presets\n\nAlways ask the user which conference the poster is for. Use these presets:\n\n| Preset | Orientation | Dimensions | tikzposter Options | Conferences |\n|---|---|---|---|---|\n| `a0-portrait` | Portrait | 841mm x 1189mm | `a0paper, portrait` | **DEFAULT.** Interspeech, SIGMOD, APS, AACR, AGU, most European |\n| `a0-landscape` | Landscape | 1189mm x 841mm | `a0paper, landscape` | Some engineering, AAAI |\n| `us-portrait` | Portrait | 36\"x48\" (914x1219mm) | `a0paper, portrait` (close fit) | Most US conferences, SfN, biomedical |\n| `neurips-main` | Landscape | 96\"x48\" (2438x1219mm) | Custom paper size | NeurIPS main |\n| `neurips-ws` | Portrait | 24\"x36\" (610x914mm) | Custom paper size | NeurIPS workshops |\n| `icml-main` | Landscape | 36\"Hx48-72\"W | Custom paper size | ICML main |\n| `icml-ws` | Portrait | 24\"x36\" (610x914mm) | Custom paper size | ICML workshops |\n| `cvpr` | Landscape | 84\"x42\" (2133x1067mm) | Custom paper size | CVPR (2:1 ratio) |\n| `iclr-main` | Landscape | 194cm x 95cm | Custom paper size | ICLR main |\n| `iclr-ws` | Portrait | 24\"x36\" (610x914mm) | Custom paper size | ICLR workshops |\n\n### Custom Paper Size (for non-A0 dimensions)\n\n```latex\n% Example: CVPR 84\"x42\" (2133mm x 1067mm)\n\\documentclass[25pt, landscape, margin=15mm,\n innermargin=15mm, blockverticalspace=12mm, colspace=20mm]{tikzposter}\n\\usepackage{geometry}\n\\geometry{paperwidth=2133mm, paperheight=1067mm}\n```\n\n### When Conference Is Unknown\n\nDefault to **A0 portrait** (841mm x 1189mm). This fits most conference boards worldwide.\n\n## Typography Standards\n\n### Font Sizes (A0 poster, 841mm x 1189mm)\n\n| Element | Size | tikzposter Default | Notes |\n|---|---|---|---|\n| Title | 72-120pt | `\\Huge` or `\\veryHuge` | Readable from 15-20 feet / 5-6 meters |\n| Authors | 48-60pt | `\\LARGE` | Below title |\n| Affiliations | 36-48pt | `\\Large` | Below authors |\n| Section headings | 48-60pt | `\\large` (block titles) | Bold, contrasting color |\n| Body text | 28-36pt | Default (~25pt at 25pt base) | Minimum 24pt |\n| Bullet items | 28-36pt | Default | Same as body |\n| Figure captions | 24-28pt | `\\small` or `\\normalsize` | Below figures |\n| Table text | 24-28pt | `\\large` in table env | Match or slightly smaller than body |\n| References | 18-24pt | `\\small` or `\\footnotesize` | Smallest text on poster |\n\n### Font Scaling for Non-A0 Sizes\n\nScale base font size proportionally to poster area:\n- A0 (841x1189mm): 25pt base (default)\n- 36\"x48\" (914x1219mm): 25pt base (similar to A0)\n- 24\"x36\" (610x914mm): 18-20pt base (smaller poster)\n- CVPR 84\"x42\": 25-30pt base (wide poster, same viewing distance)\n- NeurIPS 96\"x48\": 28-32pt base (very wide poster)\n\n### Font Family\n\n- **Sans-serif** preferred: Better readability at distance\n- tikzposter default: `\\renewcommand{\\familydefault}{\\sfdefault}`\n- Acceptable alternatives: Helvetica (`helvet`), Liberation Sans, Open Sans (via fontspec/XeLaTeX)\n- Serif OK for body text if design calls for it (use `lmodern` or `mathpazo`)\n- Maximum 2-3 font families per poster\n\n## Color Schemes\n\n### Scheme 1: Navy + Amber (Default in template)\n\nProfessional, high contrast, works for any field.\n\n```latex\n\\definecolor{navyblue}{HTML}{1E3A8A}\n\\definecolor{steelblue}{HTML}{3B82F6}\n\\definecolor{amber}{HTML}{F59E0B}\n\\definecolor{darktext}{HTML}{1F2937}\n\\definecolor{lightbg}{HTML}{F8FAFC}\n```\n\n### Scheme 2: Forest Green (Biology / Environmental)\n\n```latex\n\\definecolor{forestgreen}{HTML}{166534}\n\\definecolor{leafgreen}{HTML}{4ADE80}\n\\definecolor{earthbrown}{HTML}{92400E}\n\\definecolor{darktext}{HTML}{1C1917}\n\\definecolor{lightbg}{HTML}{F0FDF4}\n```\n\n### Scheme 3: Medical Teal (Healthcare / Clinical)\n\n```latex\n\\definecolor{tealdark}{HTML}{0F766E}\n\\definecolor{teallight}{HTML}{5EEAD4}\n\\definecolor{coral}{HTML}{F43F5E}\n\\definecolor{darktext}{HTML}{1E293B}\n\\definecolor{lightbg}{HTML}{F0FDFA}\n```\n\n### Scheme 4: Tech Purple (CS / ML / AI)\n\n```latex\n\\definecolor{deeppurple}{HTML}{6D28D9}\n\\definecolor{lavender}{HTML}{A78BFA}\n\\definecolor{hotpink}{HTML}{EC4899}\n\\definecolor{darktext}{HTML}{1E1B4B}\n\\definecolor{lightbg}{HTML}{FAF5FF}\n```\n\n### Scheme 5: Minimal Dark (High Contrast / Modern)\n\n```latex\n\\definecolor{charcoal}{HTML}{1F2937}\n\\definecolor{midgray}{HTML}{6B7280}\n\\definecolor{crimson}{HTML}{DC2626}\n\\definecolor{darktext}{HTML}{111827}\n\\definecolor{lightbg}{HTML}{F9FAFB}\n```\n\n### Applying a Color Scheme\n\nReplace the color definitions in the template, then update `\\colorlet` assignments:\n\n```latex\n\\colorlet{backgroundcolor}{white} % or lightbg\n\\colorlet{titlebgcolor}{PRIMARY_COLOR} % e.g., navyblue\n\\colorlet{titlefgcolor}{white}\n\\colorlet{blocktitlebgcolor}{PRIMARY_COLOR}\n\\colorlet{blocktitlefgcolor}{white}\n\\colorlet{blockbodybgcolor}{white}\n\\colorlet{blockbodyfgcolor}{darktext}\n```\n\n## Layout Archetypes\n\n### Traditional Column Layout (Recommended Default)\n\nBest for: Most conferences, physics, biology, medicine, engineering.\n\n**Portrait (2 columns):**\n```\n+------------------------------------------+\n| TITLE BANNER |\n| Authors, Affiliations, Contact |\n+--------------------+---------------------+\n| Introduction | Results |\n| | [Chart/Plot] |\n+--------------------+ |\n| Methods | [Chart/Plot] |\n| [Diagram] | |\n| +---------------------+\n+--------------------+ Conclusions |\n| Experimental | |\n| Setup [Table] +---------------------+\n| | References |\n+--------------------+ [QR Code] |\n+------------------------------------------+\n```\n\n**Landscape (3 columns):**\n```\n+----------------------------------------------------------------------+\n| TITLE BANNER |\n| Authors, Affiliations, Contact |\n+---------------------+-------------------------+----------------------+\n| Introduction | Results | Analysis |\n| | [Main Chart/Plot] | [Chart/Plot] |\n+---------------------+ | |\n| Methods | [Table] +----------------------+\n| [Flow Diagram] | | Conclusions |\n| +-------------------------+ |\n+---------------------+ More Results +----------------------+\n| Setup [Table] | [Chart/Plot] | References |\n| | | [QR Code] |\n+---------------------+-------------------------+----------------------+\n```\n\n### #BetterPoster Layout (Growing Trend)\n\nBest for: Maximum \"drive-by\" readability. Stand out at poster sessions.\n\n```\n+------------------------------------------+\n| TITLE BANNER |\n+----------+-----------------+-------------+\n| | | |\n| Methods | ONE KEY | Additional |\n| & Setup | FINDING | Results |\n| | IN LARGE | |\n| (small | TEXT | (small |\n| text) | (60-80pt) | text) |\n| | | |\n| | [QR Code] | |\n| | Scan for | |\n| | full paper | |\n+----------+-----------------+-------------+\n| References (tiny) |\n+------------------------------------------+\n```\n\n### Visual-Heavy / Results-First Layout\n\nBest for: Data visualization, astronomy, medical imaging.\n\n```\n+------------------------------------------+\n| TITLE BANNER |\n+--------------------+---------------------+\n| Introduction | |\n| (brief) | MAIN RESULT |\n+--------------------+ [LARGE FIGURE] |\n| Methods | (40-50% of area) |\n| (brief) | |\n+--------------------+---------------------+\n| Supporting Results | Conclusions |\n| [Small charts] | References |\n+------------------------------------------+\n```\n\n## Content Guidelines\n\n### Word Count\n\n| Poster Size | Target | Maximum |\n|---|---|---|\n| A0 portrait | 400-500 words | 800 words |\n| 24\"x36\" (workshop) | 200-300 words | 500 words |\n| Landscape (CS/ML) | 300-500 words | 700 words |\n| CVPR ultra-wide | 400-600 words | 800 words |\n\n### Content Ratio\n\n- **40% text, 60% visuals** (ideal)\n- **20-30% white space** (breathing room)\n- **Maximum 2-3 key equations** (poster is NOT the paper)\n- **3-6 figures/charts** depending on poster size\n- **References:** Limit to 3-5 most relevant\n\n### Section-by-Section Guide\n\n| Section | Length | Content |\n|---|---|---|\n| **Title** | 1-2 lines | Short, compelling, result-hinting |\n| **Introduction/Motivation** | 50-80 words | Problem statement, why it matters |\n| **Methods** | 80-120 words | Approach overview, key steps (not full detail) |\n| **Results** | 100-150 words | Key findings with supporting visuals |\n| **Conclusions** | 50-80 words | Main takeaway, impact, future work |\n| **References** | 3-5 entries | Most relevant citations only |\n\n## QR Code Placement\n\n```latex\n\\usepackage{qrcode}\n\n% Option 1: In references block\n\\block{References \\& Resources}{\n {\\small [1] Author et al. (2024). Paper Title. \\textit{Conf}.}\n \\vspace{1em}\n \\begin{center}\n \\qrcode[height=4cm]{https://arxiv.org/abs/XXXX.XXXXX}\\\\[0.5em]\n {\\normalsize Scan for full paper \\& code}\n \\end{center}\n}\n\n% Option 2: Standalone block\n\\block{}{\n \\begin{center}\n \\qrcode[height=5cm]{https://github.com/user/repo}\\\\[0.5em]\n {\\large Paper \\& Code}\n \\end{center}\n}\n```\n\n- Place in bottom-right corner or references section\n- Size: 3-5cm height on A0 poster\n- Include brief label below QR code\n- Link to: arXiv paper, GitHub repo, project page, or demo\n\n## Common Mistakes to Avoid\n\n1. **Too much text** -- poster is NOT a paper printout. Max 800 words.\n2. **Font too small** -- minimum 24pt for any text on A0. Test: can you read it from 4 feet?\n3. **No visual hierarchy** -- title should be readable from 15 feet, key finding from 10 feet\n4. **Wall of text blocks** -- break up with figures, bullet points, white space\n5. **Fixed dimensions for figures** -- use `width=0.9\\linewidth`, not `width=20cm`\n6. **Using `\\begin{figure}` in tikzposter** -- use `\\begin{tikzfigure}[Caption]` instead\n7. **Cluttered layout** -- 20-30% white space is necessary for readability\n8. **Low-contrast colors** -- yellow text on white, light gray on white = unreadable\n9. **Too many fonts** -- max 2-3 font families\n10. **Tiny references section** -- if references are unreadable, omit them and use a QR code instead\n11. **No contact info** -- always include email, optionally GitHub/website\n12. **Landscape for non-CS conference** -- check the conference guidelines first\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":11113,"content_sha256":"493a526ec5f517a28ec0824c435d54485c1197cee093069acb51cf08c531857c"},{"filename":"references/profiles/business-document.md","content":"# Conversion Profile: Business Documents\n\nUse this profile when the PDF contains: reports, meeting notes, memos, proposals, financial data, org charts, executive summaries, action items, bullet points, data tables.\n\n## Suggested Preamble\n\n```latex\n\\documentclass[12pt,a4paper]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{graphicx}\n\\usepackage{xcolor}\n\\usepackage{titlesec}\n\\usepackage{fancyhdr}\n\\usepackage{tabularx}\n\\usepackage{array}\n\\usepackage{colortbl}\n\\usepackage{booktabs}\n\\usepackage{multirow}\n\\usepackage{longtable}\n\\usepackage{enumitem}\n\\usepackage{parskip}\n\n% Professional colors\n\\definecolor{headerblue}{RGB}{0, 102, 204}\n\\definecolor{lightgray}{RGB}{240, 240, 240}\n\\definecolor{darkgray}{RGB}{80, 80, 80}\n\n% Section styling\n\\titleformat{\\section}{\\Large\\bfseries\\color{headerblue}}{\\thesection}{0.5em}{}\n\\titleformat{\\subsection}{\\large\\bfseries}{}{0em}{}\n\n% Headers/footers\n\\pagestyle{fancy}\n\\fancyhf{}\n\\fancyhead[L]{\\small\\textcolor{darkgray}{Document Title}}\n\\fancyhead[R]{\\small\\textcolor{darkgray}{\\today}}\n\\fancyfoot[C]{\\small\\thepage}\n\\renewcommand{\\headrulewidth}{0.4pt}\n```\n\n## Structural Patterns to Recognize\n\n- **Section headings**: Bold or underlined text, often numbered -> `\\section{}` or `\\subsection{}`\n- **Executive summary**: Opening paragraph with key findings -> dedicated `\\section{Executive Summary}`\n- **Bullet points**: Dashes or dots -> `\\begin{itemize}...\\end{itemize}`\n- **Numbered lists**: Sequential numbers -> `\\begin{enumerate}...\\end{enumerate}`\n- **Action items**: Checkboxes or \"TODO\" markers -> itemize with bold labels\n- **Data tables**: Rows and columns of data -> `tabularx` with `booktabs` rules\n- **Financial figures**: Currency amounts, percentages -> right-aligned columns with `r`\n- **Headers/footers**: Recurring text at page top/bottom -> capture in `fancyhdr` setup\n- **Signatures**: Signature lines -> `\\rule{5cm}{0.4pt}` with name below\n- **Date/time stamps**: Meeting dates, deadlines -> format consistently\n- **Company logos**: Letterhead images -> `\\includegraphics` or note as placeholder\n\n## Worker Agent Hints\n\n- Use `\\section{}` with numbers (not `\\section*{}`) -- business docs typically have numbered sections\n- Preserve table structure carefully: count columns, align data types (text left, numbers right)\n- For financial tables: use `booktabs` (`\\toprule`, `\\midrule`, `\\bottomrule`), right-align currency\n- Meeting notes: use `\\textbf{Date:}`, `\\textbf{Attendees:}`, etc. for metadata blocks\n- Bullet points: use `\\begin{itemize}[itemsep=0.3em]` for compact lists\n- For emphasis: use `\\textbf{}` for bold, `\\textit{}` for italic -- match the original\n- When text references a chart or image that isn't transcribable: `% [Figure: description of chart/image]`\n- Close ALL environments before the end of your batch\n\n## Common Pitfalls\n\n1. **Table column count mismatch**: Count `&` separators carefully. Each row must have exactly N-1 `&` for N columns.\n2. **Stray `&` in text**: Business text often contains `&` (e.g., \"R&D\", \"P&L\"). Escape as `\\&` outside tables.\n3. **Dollar signs in financial data**: `$100` in text needs escaping: `\\$100`.\n4. **Percentage signs**: `50%` comments out the rest of the line in LaTeX. Use `50\\%`.\n5. **Long tables**: If a table spans many rows, use `longtable` instead of `tabularx` to allow page breaks.\n6. **Missing `colortbl`**: If using `\\rowcolor{}`, the `colortbl` package must be loaded.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3465,"content_sha256":"67215467600584fc64e5b40e0e32d4e4b53f6440a08bd8a6ae1ee251482807ab"},{"filename":"references/profiles/general-notes.md","content":"# Conversion Profile: General / Mixed Notes\n\nUse this profile when the PDF contains: handwritten notes, personal journals, lecture notes (non-math), letters, mixed content that doesn't clearly fit math/business/legal categories.\n\n## Suggested Preamble\n\n```latex\n\\documentclass[11pt,a4paper]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{graphicx}\n\\usepackage{xcolor}\n\\usepackage{enumitem}\n\\usepackage{parskip}\n\\usepackage{titlesec}\n\\usepackage{tabularx}\n\\usepackage{booktabs}\n\n% Colors for annotations\n\\definecolor{notecolor}{rgb}{1,0,0}\n\\definecolor{highlight}{RGB}{255,255,200}\n\n% Section styling\n\\titleformat{\\section}{\\Large\\bfseries}{}\n {0em}{}[\\titlerule]\n\\titleformat{\\subsection}{\\large\\bfseries}{}\n {0em}{}\n```\n\n## Structural Patterns to Recognize\n\n- **Headings**: Larger or underlined text -> `\\section{}` or `\\subsection{}`\n- **Bullet points / dashes**: Listed items -> `\\begin{itemize}...\\end{itemize}`\n- **Numbered items**: Sequential points -> `\\begin{enumerate}...\\end{enumerate}`\n- **Paragraphs**: Regular text blocks -> standard paragraphs with blank line separation\n- **Emphasized text**: Underlined, circled, or highlighted -> `\\textbf{}`, `\\emph{}`, or `\\underline{}`\n- **Colored annotations**: Red/blue marks -> `{\\color{notecolor}text}`\n- **Diagrams / drawings**: Sketches -> `% [Figure: description of drawing]`\n- **Tables / grids**: Organized data -> `tabularx` or `tabular`\n- **Dates**: Date headers on notes -> `\\subsection*{Date}` or bold text\n- **Arrows / connections**: Flow indicators -> describe in text or use TikZ\n\n## Worker Agent Hints\n\n- Be faithful to the content -- transcribe what's written, don't reinterpret\n- For illegible text: use `[illegible]` or `[?]` markers\n- Handwriting with crossed-out text: omit the crossed-out content unless it's clearly important\n- Marginal notes: include as `\\marginpar{note}` or inline with `{\\color{notecolor}note}`\n- Preserve the general flow and organization of the original\n- If the notes switch topics abruptly, use `\\bigskip` or `\\section*{}` to mark the transition\n- For simple diagrams described in text: use a centered italic description\n ```latex\n \\begin{center}\n \\textit{[Diagram: flowchart showing process A → B → C]}\n \\end{center}\n ```\n- Close ALL environments before the end of your batch\n\n## Common Pitfalls\n\n1. **Over-structuring**: Handwritten notes are often informal. Don't force them into rigid theorem/definition environments unless the content clearly matches.\n2. **Illegible content**: Don't guess at illegible handwriting. Mark it clearly.\n3. **Mixed languages**: If notes contain non-English text, ensure UTF-8 encoding handles the characters. Add `\\usepackage[language]{babel}` if needed.\n4. **Doodles and sketches**: Don't try to reproduce complex drawings in TikZ. Describe them or note them as figures.\n5. **Inconsistent formatting**: Notes may change style mid-page. Follow the original's structure even if inconsistent.\n6. **Special characters**: Handwritten ampersands, dollar signs, percent signs all need escaping in LaTeX.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3108,"content_sha256":"44b904c7b89ffaf41853ae36d7dc6da5a0af5fce0b9d5b508ac0e8c3341990d1"},{"filename":"references/profiles/legal-document.md","content":"# Conversion Profile: Legal Documents\n\nUse this profile when the PDF contains: contracts, agreements, regulations, statutes, terms and conditions, legal briefs, numbered paragraphs, footnotes, citations, definitions sections.\n\n## Suggested Preamble\n\n```latex\n\\documentclass[12pt,a4paper]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{graphicx}\n\\usepackage{xcolor}\n\\usepackage{titlesec}\n\\usepackage{fancyhdr}\n\\usepackage{enumitem}\n\\usepackage{parskip}\n\\usepackage{setspace}\n\\usepackage{footmisc}\n\n% Legal document spacing (often double-spaced)\n\\onehalfspacing\n\n% Section numbering: Article I, Section 1.1, etc.\n\\renewcommand{\\thesection}{\\Roman{section}}\n\\renewcommand{\\thesubsection}{\\thesection.\\arabic{subsection}}\n\\renewcommand{\\thesubsubsection}{\\thesubsection.\\alph{subsubsection}}\n\n\\titleformat{\\section}{\\large\\bfseries\\centering}{\\thesection.}{0.5em}{}\n\\titleformat{\\subsection}{\\normalsize\\bfseries}{\\thesubsection}{0.5em}{}\n\n% Headers/footers\n\\pagestyle{fancy}\n\\fancyhf{}\n\\fancyfoot[C]{\\small\\thepage}\n\\renewcommand{\\headrulewidth}{0pt}\n\n% Indented paragraphs for legal clauses\n\\setlength{\\parindent}{2em}\n\\setlength{\\parskip}{0.5em}\n```\n\n## Structural Patterns to Recognize\n\n- **Articles / Sections**: \"ARTICLE I\", \"Section 1.1\" -> `\\section{}`, `\\subsection{}`\n- **Numbered clauses**: \"(a)\", \"(b)\", \"(i)\", \"(ii)\" -> nested `enumerate` with custom labels\n- **Definitions**: \"Term\" means... -> `\\textbf{\"Term\"}` with definition text\n- **Recitals / Whereas clauses**: \"WHEREAS...\" paragraphs -> regular paragraphs with `\\textsc{Whereas}`\n- **Signature blocks**: Party names, dates, signature lines -> formatted block with `\\rule`\n- **Footnotes**: Superscript numbers with notes -> `\\footnote{}`\n- **Block quotes**: Indented cited text -> `\\begin{quote}...\\end{quote}`\n- **ALL CAPS headings**: Section titles in uppercase -> `\\section{\\texorpdfstring{\\MakeUppercase{Title}}{Title}}`\n- **Cross-references**: \"See Section 3.2\" -> keep as plain text (don't try to `\\ref`)\n- **Page numbers**: \"Page X of Y\" -> handled by `fancyhdr`\n\n## Worker Agent Hints\n\n- Legal docs have deeply nested numbering: Article > Section > Subsection > (a) > (i). Use nested `enumerate`:\n ```latex\n \\begin{enumerate}[label=(\\alph*)]\n \\item First clause\n \\begin{enumerate}[label=(\\roman*)]\n \\item Sub-clause\n \\end{enumerate}\n \\end{enumerate}\n ```\n- Preserve exact wording -- legal text is precise, don't paraphrase or summarize\n- ALL CAPS headers: use `\\textbf{\\MakeUppercase{heading text}}`\n- Signature blocks:\n ```latex\n \\vspace{2cm}\n \\noindent\\rule{6cm}{0.4pt} \\\\\n Name \\\\\n Title \\\\\n Date: \\rule{3cm}{0.4pt}\n ```\n- For \"WHEREAS\" recitals: start each with `\\noindent\\textsc{Whereas},`\n- Footnotes: place `\\footnote{text}` immediately after the reference mark\n- Close ALL environments before the end of your batch\n\n## Common Pitfalls\n\n1. **Section numbering mismatch**: Legal documents use Roman numerals (I, II, III) or custom numbering. Match the original scheme.\n2. **Nested list depth**: LaTeX supports 4 levels of nesting. For deeper nesting, customize `enumitem` labels.\n3. **Quotation marks**: Use `` ` `` and `'` for quotes in LaTeX (`` `single' `` and ``` ``double'' ```), not straight quotes.\n4. **Long paragraphs**: Legal text can be very dense. Preserve paragraph breaks as they appear in the original.\n5. **Escaping special chars**: Legal text often has `§` (use `\\S`), `¶` (use `\\P`), and `©` (use `\\copyright`).\n6. **Cross-references**: Don't try to create `\\label`/`\\ref` pairs -- just write \"Section 3.2\" as plain text.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":3610,"content_sha256":"c556f329c025517d3e2c6b810ac72d5e19cb4ae80edfa94bcae106465aeed6be"},{"filename":"references/profiles/math-notes.md","content":"# Conversion Profile: Math / Science Notes\n\nUse this profile when the PDF contains: equations, theorems, proofs, definitions, lemmas, Greek symbols, matrices, integrals, mathematical notation.\n\n## Formatting Mode\n\nThis profile supports two formatting modes. **Default to beautiful mode** unless the user explicitly requests plain output.\n\n### Beautiful Mode (Default)\n\nUse the `lecture-notes.tex` template from `assets/templates/`. This produces professional, textbook-quality output with:\n- KOMA-Script document class (`scrartcl`) with Palatino font\n- Color-coded `tcolorbox` theorem environments (blue theorems, green definitions, orange examples)\n- TikZ graph/diagram generation from hand-drawn figures\n- Styled section headings, headers/footers, and micro-typography\n\n### Plain Mode\n\nUse the plain preamble below for maximum compatibility and minimal styling. Suitable when the user wants raw LaTeX output or needs to integrate into an existing document.\n\n## Suggested Preamble (Plain Mode)\n\n```latex\n\\documentclass[11pt,a4paper]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage[margin=1in]{geometry}\n\\usepackage{amsmath,amssymb,amsthm}\n\\usepackage{mathtools}\n\\usepackage{mathrsfs}\n\\usepackage{graphicx}\n\\usepackage{xcolor}\n\\usepackage{tikz}\n\\usepackage{enumitem}\n\\usepackage{parskip}\n\\usepackage{bbm}\n\\usepackage{esint}\n\\usepackage{cancel}\n\n% Number sets\n\\newcommand{\\R}{\\mathbb{R}}\n\\newcommand{\\N}{\\mathbb{N}}\n\\newcommand{\\Z}{\\mathbb{Z}}\n\\newcommand{\\Q}{\\mathbb{Q}}\n\\newcommand{\\C}{\\mathbb{C}}\n\n% Derivatives\n\\newcommand{\\pd}[2]{\\frac{\\partial #1}{\\partial #2}}\n\\newcommand{\\dd}[2]{\\frac{d #1}{d #2}}\n\n% Norms and delimiters\n\\newcommand{\\norm}[1]{\\left\\|#1\\right\\|}\n\\newcommand{\\abs}[1]{\\left|#1\\right|}\n\\newcommand{\\inner}[2]{\\langle #1,\\, #2 \\rangle}\n\n% Theorem environments\n\\theoremstyle{plain}\n\\newtheorem{theorem}{Theorem}[section]\n\\newtheorem{lemma}[theorem]{Lemma}\n\\newtheorem{proposition}[theorem]{Proposition}\n\\newtheorem{corollary}[theorem]{Corollary}\n\n\\theoremstyle{definition}\n\\newtheorem{definition}[theorem]{Definition}\n\\newtheorem{example}[theorem]{Example}\n\n\\theoremstyle{remark}\n\\newtheorem{remark}[theorem]{Remark}\n\\newtheorem{note}[theorem]{Note}\n\n\\renewcommand{\\qedsymbol}{$\\blacksquare$}\n```\n\n## Suggested Preamble (Beautiful Mode)\n\nUse the preamble from `assets/templates/lecture-notes.tex` directly. It includes everything from the plain preamble plus:\n\n- **Font**: `mathpazo` (Palatino) with `microtype` for professional typography\n- **Document class**: `scrartcl` (KOMA-Script) for better type area and section styling\n- **Colored theorem environments**: via `tcolorbox` with `tcbuselibrary{theorems, skins, breakable}`\n - `theorem` (blue, sharp corners) -- important statements\n - `lemma` (lighter blue) -- supporting results\n - `corollary` (blue-gray) -- consequences\n - `definition` (green, rounded corners) -- introduces concepts\n - `example` (orange, left accent bar) -- worked illustrations\n - `remark` (purple left border) -- observations\n - `notebox` (red left border) -- warnings / important notes\n - `proof` (gray-blue left border) -- derivations with auto QED\n- **TikZ graph styles**: pre-defined `vertex`, `svertex`, `hvertex`, `edge`, `dedge`, `hedge` styles and reusable macros (`\\CompleteGraph`, `\\CycleGraph`, `\\PathGraph`)\n- **Section styling**: `titlesec` with colored headings and underline rule\n- **Headers/footers**: `fancyhdr` with section name and page number\n- **Navigation**: `hyperref` + `cleveref` for smart cross-references\n- **Graph theory commands**: `\\V`, `\\E`, `\\deg`, `\\diam`, `\\dist`, `\\Aut`, `\\chr`\n\n**Important**: The beautiful mode preamble uses `hyperref`. This is safe because the theorem environments are defined with `tcolorbox` (not `amsthm`), which avoids the `\\set@color` conflict. Do NOT mix `amsthm` theorem definitions with `hyperref` -- use `tcolorbox` theorems exclusively in beautiful mode.\n\n## Structural Patterns to Recognize\n\n- **Theorem/Lemma/Proposition**: Boxed or labeled statements\n - Plain mode: `\\begin{theorem}...\\end{theorem}`\n - Beautiful mode: `\\begin{theorem}{Title}{label}...\\end{theorem}` (tcolorbox takes title + label args)\n- **Definitions**: Usually underlined key term\n - Plain mode: `\\begin{definition}...\\end{definition}`\n - Beautiful mode: `\\begin{definition}{Title}{label}...\\end{definition}`\n- **Proofs**: Starts with \"Proof:\" or \"Pf:\", ends with QED symbol -> `\\begin{proof}...\\end{proof}`\n- **Examples**: Starts with \"Example:\" or \"Ex:\"\n - Plain mode: `\\begin{example}...\\end{example}`\n - Beautiful mode: `\\begin{example}{Title}{label}...\\end{example}`\n- **Remarks**: Side notes, observations\n - Plain mode: `\\begin{remark}...\\end{remark}`\n - Beautiful mode: `\\begin{remark}...\\end{remark}` (no title/label args)\n- **Important notes**: Warnings, critical observations\n - Beautiful mode only: `\\begin{notebox}...\\end{notebox}`\n- **Multi-line derivations**: Aligned at `=` signs -> `align*` environment\n- **Single important equations**: Standalone display -> `equation*` environment\n- **Matrices**: Arrays of numbers in brackets -> `pmatrix` or `bmatrix`\n- **Diagrams/Graphs**: Convert to TikZ code (see Diagram Conversion below)\n\n## Diagram Conversion (Beautiful Mode)\n\nWhen converting handwritten notes with diagrams, **generate TikZ code** instead of skipping figures or using `\\includegraphics`. The template provides pre-defined styles:\n\n### Node Styles\n- `vertex` -- standard circle node (blue fill, 8mm)\n- `svertex` -- small vertex for dense graphs (5mm)\n- `hvertex` -- highlighted vertex (red border)\n- `rvertex`, `bvertex`, `gvertex`, `yvertex` -- red/blue/green/yellow filled vertices (for graph coloring)\n\n### Edge Styles\n- `edge` -- standard thick gray edge\n- `dedge` -- directed edge with arrow\n- `hedge` -- highlighted edge (red, very thick)\n- `weight` -- edge label style (white background)\n\n### Reusable Macros\n- `\\CompleteGraph[radius]{n}` -- draws K_n in a circle\n- `\\CycleGraph[radius]{n}` -- draws C_n in a circle\n- `\\PathGraph{n}` -- draws P_n horizontally\n\n### Common Graph Patterns\n\n**Complete graph K_n:**\n```latex\n\\begin{tikzpicture}\n \\CompleteGraph[1.5cm]{5}\n\\end{tikzpicture}\n```\n\n**Complete bipartite K_{m,n}:**\n```latex\n\\begin{tikzpicture}\n % Left partition\n \\foreach \\i in {1,...,3} {\n \\node[bvertex] (l\\i) at (0, {2.5 - 1.25*(\\i-1)}) {$u_{\\i}$};\n }\n % Right partition\n \\foreach \\i in {1,...,3} {\n \\node[rvertex] (r\\i) at (4, {2.5 - 1.25*(\\i-1)}) {$v_{\\i}$};\n }\n \\foreach \\i in {1,...,3} {\n \\foreach \\j in {1,...,3} {\n \\draw[edge, opacity=0.7] (l\\i) -- (r\\j);\n }\n }\n\\end{tikzpicture}\n```\n\n**Petersen graph:**\n```latex\n\\begin{tikzpicture}[scale=1.3]\n \\foreach \\i in {1,...,5} {\n \\node[vertex] (out\\i) at ({90 + 72*(\\i-1)}:2cm) {};\n }\n \\foreach \\i in {1,...,5} {\n \\node[vertex] (in\\i) at ({90 + 72*(\\i-1)}:0.9cm) {};\n }\n \\foreach \\i in {1,...,5} {\n \\pgfmathtruncatemacro{\\next}{mod(\\i, 5) + 1}\n \\draw[edge] (out\\i) -- (out\\next);\n }\n \\foreach \\i in {1,...,5} {\n \\pgfmathtruncatemacro{\\next}{mod(\\i + 1, 5) + 1}\n \\draw[edge] (in\\i) -- (in\\next);\n }\n \\foreach \\i in {1,...,5} {\n \\draw[edge, dashed] (out\\i) -- (in\\i);\n }\n\\end{tikzpicture}\n```\n\n**Graph with adjacency matrix (side-by-side):**\n```latex\n\\begin{tikzpicture}\n \\node[vertex] (v1) at (0,2) {$v_1$};\n \\node[vertex] (v2) at (2,2) {$v_2$};\n \\node[vertex] (v3) at (2,0) {$v_3$};\n \\node[vertex] (v4) at (0,0) {$v_4$};\n \\draw[edge] (v1)--(v2) (v2)--(v3) (v3)--(v4) (v4)--(v1) (v1)--(v3);\n \\node at (4,1) {\\Large$\\longrightarrow$};\n \\node at (7,1) {$A(G) = \\begin{pmatrix} 0&1&1&1 \\\\ 1&0&1&0 \\\\ 1&1&0&1 \\\\ 1&0&1&0 \\end{pmatrix}$};\n\\end{tikzpicture>\n```\n\n**Graph coloring:**\n```latex\n\\begin{tikzpicture}\n \\node[rvertex] (v1) at ({90}:1.5cm) {$1$};\n \\node[bvertex] (v2) at ({18}:1.5cm) {$2$};\n \\node[gvertex] (v3) at ({-54}:1.5cm) {$3$};\n \\node[rvertex] (v4) at ({-126}:1.5cm) {$4$};\n \\node[bvertex] (v5) at ({-198}:1.5cm) {$5$};\n \\draw[edge] (v1)--(v2)--(v3)--(v4)--(v5)--(v1);\n\\end{tikzpicture>\n```\n\n**Euler/Hamilton path highlighting:**\n```latex\n% Draw all edges in light gray first, then overlay the path in color\n\\draw[edge, gray!40] (v1) -- (v2); % background\n\\draw[hedge, -{Stealth[length=3mm]}, HighlightRed] (v1) -- (v2); % highlighted path\n```\n\n**Tree structure:**\n```latex\n\\begin{tikzpicture}[\n level 1/.style={sibling distance=3cm},\n level 2/.style={sibling distance=1.5cm}\n]\n \\node[vertex] {1}\n child {node[vertex] {2}\n child {node[vertex] {4}}\n child {node[vertex] {5}}\n }\n child {node[vertex] {3}\n child {node[vertex] {6}}\n child {node[vertex] {7}}\n };\n\\end{tikzpicture>\n```\n\n### Diagram Conversion Rules\n\n1. **Always attempt TikZ generation** for graph diagrams -- nodes + edges are structurally simple enough\n2. **Describe what you see** before generating code: count vertices, identify edges, note layout\n3. **Use pre-defined styles** (`vertex`, `edge`, etc.) for consistency\n4. **For complex or ambiguous diagrams**: generate best-effort TikZ and add a comment `% TODO: verify diagram matches original`\n5. **For non-graph diagrams** (coordinate systems, function plots): use `pgfplots` or describe in a comment for manual recreation\n6. **Place diagrams in `\\begin{center}...\\end{center}`** inside example/theorem boxes, or as standalone figures\n\n## Worker Agent Hints\n\n- Use `\\section*{}` for unnumbered section headings (matching handwritten headers)\n- Red or colored annotations in original: `{\\color{red}text}` (or use `{\\color{NoteRed}text}` in beautiful mode)\n- When equations span multiple lines, prefer `align*` with `&` alignment at `=`\n- Close ALL environments before the end of your batch -- if a proof spans your boundary, close it and note `% continues in next batch`\n- Subscript notation: be careful with `D_{x_i}f` vs `\\frac{\\partial f}{\\partial x_i}`\n- Use `\\left( \\right)` for auto-sized delimiters around fractions\n- Inline math for short expressions: `$f(x) = x^2 latex-document-skill — Skillopedia \n- Display math for important results: `\\[ f'(x) = 2x \\]`\n\n### Beautiful Mode Specific Hints\n\n- **tcolorbox theorem syntax**: `\\begin{theorem}{Title}{label}` not `\\begin{theorem}` alone. Title can be descriptive (e.g., \"Handshaking Lemma\"). Label is a short key (e.g., \"handshaking\").\n- **Remark and notebox** do NOT take title/label arguments: just `\\begin{remark}...\\end{remark}`\n- **Proof** uses standard `\\begin{proof}...\\end{proof}` (rendered with left border via tcolorbox)\n- **Diagrams inside boxes**: Place `\\begin{center}\\begin{tikzpicture}...\\end{tikzpicture}\\end{center}` inside example environments\n- **Section headings**: Use numbered sections (`\\section{}`) -- they auto-style with blue headings and underline\n- **Labeled vertices in TikZ**: Use `{$v_1$}` or `{$1$}` for math-mode labels\n\n## Critical LaTeX Constraints (Beautiful Mode)\n\nWorker agents MUST follow these rules. Violation causes compilation failure.\n\n### Commands You MUST NOT Invent\n\nDo NOT use any command that is not defined in the preamble. Common mistakes:\n- `\\pentagon`, `\\hexagon`, `\\octagon` -- these do NOT exist. Draw shapes with TikZ `\\node[regular polygon, regular polygon sides=5]` or use `\\draw` commands.\n- Any `\\foo` command that \"seems like it should exist\" -- verify it is in the preamble first.\n\n### Commands Available in the Preamble\n\n| Command | Purpose | Example |\n|---|---|---|\n| `\\R`, `\\N`, `\\Z`, `\\Q`, `\\C` | Number sets | `$f: \\R \\to \\R latex-document-skill — Skillopedia |\n| `\\V`, `\\E` | Vertex/edge set | `$\\V(G) = \\{1,2,3\\} latex-document-skill — Skillopedia |\n| `\\deg` | Vertex degree | `$\\deg(v) = 3 latex-document-skill — Skillopedia |\n| `\\diam`, `\\dist` | Diameter, distance | `$\\diam(G) = 4 latex-document-skill — Skillopedia |\n| `\\Aut`, `\\chr` | Automorphism, chromatic | `$\\chr(G) = 3 latex-document-skill — Skillopedia |\n| `\\abs{}`, `\\norm{}`, `\\floor{}`, `\\ceil{}` | Delimiters | `$\\abs{x-y} latex-document-skill — Skillopedia |\n| `\\circled{n}` | Circled number (annotation) | `$\\circled{1} latex-document-skill — Skillopedia |\n| `\\sout{text}` | Strikethrough text | `\\sout{deleted}` |\n| `\\cancel{expr}` | Strikethrough in math | `$\\cancel{x+1} latex-document-skill — Skillopedia |\n\n### TikZ Strict Rules\n\n1. **Every command ends with `;`**: `\\node[vertex] (v1) at (0,0) {$v_1$};`\n2. **Every `\\node` has label braces**: Even empty: `\\node[vertex] (v1) at (0,0) {};`\n3. **All TikZ inside tikzpicture**: Never write `\\node` or `\\draw` outside `\\begin{tikzpicture}...\\end{tikzpicture}`\n4. **Polar coordinates for circular layouts**: Use `(60:1.5cm)` NOT `({cos(60)},{sin(60)})`\n5. **`edge`/`dedge`/`hedge` are EDGE styles**: Use `\\draw[edge]`, NEVER `\\node[edge]`\n6. **`vertex`/`svertex`/`hvertex` are NODE styles**: Use `\\node[vertex]`, NEVER `\\draw[vertex]`\n\n### Environment Nesting Rules\n\n1. **No floats inside tcolorbox**: Do NOT use `\\begin{table}[H]` or `\\begin{figure}[H]` inside `theorem`, `example`, `definition`, `lemma`, `corollary`, `remark`, `notebox`, or `proof`. Use `\\begin{tabular}` directly (no `table` wrapper).\n2. **No `tabular` inside math**: Do NOT put `\\begin{tabular}` inside `align*` or `equation*`. End the math first, then start the tabular.\n3. **`proof` inside `example`**: Allowed, but MUST close `\\end{proof}` BEFORE `\\end{example}`.\n4. **Enumerate labels**: Use `\\begin{enumerate}` without options (labels pre-configured: level 1 = (i), level 2 = (a)). For custom labels: `\\begin{enumerate}[label=(\\alph*)]`.\n\n## Common Pitfalls\n\n1. **Mismatched environments**: The #1 error source. Always pair `\\begin{X}` with `\\end{X}`. Count your opens and closes before finishing.\n2. **Stray `&` characters**: `&` is a column separator in tables/align. Outside these environments it causes errors. Escape as `\\&` in text.\n3. **Missing ` latex-document-skill — Skillopedia delimiters**: Forgetting to close inline math mode. Every ` latex-document-skill — Skillopedia needs a matching ` latex-document-skill — Skillopedia .\n4. **Nested environments**: `align*` inside `theorem` is fine. But don't cross-nest (`\\begin{theorem}...\\begin{align*}...\\end{theorem}...\\end{align*}` = error).\n5. **Beautiful mode tcolorbox args**: `\\begin{theorem}{Title}{label}` requires BOTH title AND label. Use `{}` for empty label if not needed: `\\begin{theorem}{My Theorem}{}`.\n6. **hyperref in plain mode**: Do NOT include `hyperref` in plain mode with `amsthm` theorems -- causes `\\set@color` errors. In beautiful mode (tcolorbox theorems), `hyperref` is safe and included in the template.\n7. **TikZ inside tcolorbox**: Works fine, but ensure `breakable` is set on the box if the diagram is large. The template already sets `breakable` on example boxes.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":14240,"content_sha256":"1034a3faebf00d2df0f414f4bade902da7234b1e65ecd4e316bdb941e167959b"},{"filename":"references/python-charts.md","content":"# Python Charts for LaTeX\n\n## Overview\n\n**Matplotlib** is Python's most popular plotting library for creating high-quality charts and visualizations. It produces publication-ready figures that integrate seamlessly with LaTeX documents.\n\n### When to Use Matplotlib vs pgfplots\n\n**Matplotlib:**\n- Complex data processing with pandas/numpy\n- Quick exploratory analysis\n- Custom visualizations\n- Python-based workflow\n- External data sources (databases, APIs)\n\n**pgfplots:**\n- Simple data, small datasets\n- Perfect LaTeX integration\n- Vector graphics with LaTeX fonts\n- Direct CSV reading in LaTeX\n- No external dependencies\n\n---\n\n## Installation\n\n### Required Packages\n\n```bash\n# Install matplotlib and dependencies\npip install matplotlib numpy pandas seaborn\n\n# For additional chart types\npip install scipy scikit-learn\n```\n\n### LaTeX Packages\n\n```latex\n\\usepackage{graphicx} % For \\includegraphics\n\\usepackage{float} % For H placement\n```\n\n---\n\n## Using the generate_chart.py Script\n\nThe skill includes a helper script for generating charts.\n\n### Basic Usage\n\n```bash\n# Generate from Python data\npython generate_chart.py \\\n --type bar \\\n --data \"Category A:10,Category B:15,Category C:8\" \\\n --output chart.png \\\n --title \"Sales by Category\"\n\n# Generate from CSV file\npython generate_chart.py \\\n --type line \\\n --csv data.csv \\\n --x-col \"Month\" \\\n --y-col \"Revenue\" \\\n --output revenue_trend.pdf \\\n --title \"Monthly Revenue\"\n\n# Multiple series line chart\npython generate_chart.py \\\n --type line \\\n --csv quarterly_data.csv \\\n --x-col \"Quarter\" \\\n --y-cols \"Product A,Product B,Product C\" \\\n --output products.pdf \\\n --title \"Product Sales Comparison\"\n\n# Scatter plot with regression\npython generate_chart.py \\\n --type scatter \\\n --csv experiment.csv \\\n --x-col \"Temperature\" \\\n --y-col \"Yield\" \\\n --regression \\\n --output scatter.pdf\n```\n\n### Script Options\n\n- `--type` - Chart type (bar, line, scatter, pie, heatmap, box, histogram, area, radar)\n- `--data` - Inline data (format varies by type)\n- `--csv` - CSV file path\n- `--x-col`, `--y-col`, `--y-cols` - Column names\n- `--output` - Output filename (PNG or PDF)\n- `--title` - Chart title\n- `--xlabel`, `--ylabel` - Axis labels\n- `--style` - Style preset (default, seaborn, ggplot, bmh)\n- `--colormap` - Color palette\n- `--dpi` - Resolution (default: 300)\n- `--figsize` - Figure size in inches (e.g., \"8x6\")\n- `--regression` - Add trend line (scatter plots)\n\n---\n\n## Bar Charts\n\nBar charts compare categorical data.\n\n### Vertical Bar Chart\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Data\ncategories = ['Q1', 'Q2', 'Q3', 'Q4']\nvalues = [23, 45, 56, 78]\n\n# Create figure with appropriate size for LaTeX\nfig, ax = plt.subplots(figsize=(6, 4))\n\n# Create bars\nbars = ax.bar(categories, values, color='steelblue', edgecolor='black', linewidth=0.7)\n\n# Add value labels on top of bars\nfor bar in bars:\n height = bar.get_height()\n ax.text(bar.get_x() + bar.get_width()/2., height,\n f'{height}',\n ha='center', va='bottom', fontsize=10)\n\n# Styling\nax.set_xlabel('Quarter', fontsize=12)\nax.set_ylabel('Sales (thousands)', fontsize=12)\nax.set_title('Quarterly Sales Performance', fontsize=14, fontweight='bold')\nax.grid(axis='y', alpha=0.3, linestyle='--')\nax.set_axisbelow(True)\n\n# Save with high resolution for LaTeX\nplt.tight_layout()\nplt.savefig('quarterly_sales.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n**LaTeX Integration:**\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.7\\textwidth]{quarterly_sales.pdf}\n \\caption{Quarterly sales performance showing consistent growth trend}\n \\label{fig:quarterly-sales}\n\\end{figure}\n```\n\n### Grouped Bar Chart\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Data\ncategories = ['Product A', 'Product B', 'Product C', 'Product D']\nyear_2023 = [23, 34, 45, 29]\nyear_2024 = [28, 39, 52, 35]\n\nx = np.arange(len(categories))\nwidth = 0.35\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\n# Create grouped bars\nbars1 = ax.bar(x - width/2, year_2023, width, label='2023',\n color='lightcoral', edgecolor='black', linewidth=0.7)\nbars2 = ax.bar(x + width/2, year_2024, width, label='2024',\n color='steelblue', edgecolor='black', linewidth=0.7)\n\n# Styling\nax.set_xlabel('Products', fontsize=12)\nax.set_ylabel('Sales (thousands)', fontsize=12)\nax.set_title('Year-over-Year Product Sales Comparison', fontsize=14, fontweight='bold')\nax.set_xticks(x)\nax.set_xticklabels(categories)\nax.legend(fontsize=10, frameon=True, shadow=True)\nax.grid(axis='y', alpha=0.3, linestyle='--')\nax.set_axisbelow(True)\n\nplt.tight_layout()\nplt.savefig('yoy_comparison.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Stacked Bar Chart\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\ncategories = ['Q1', 'Q2', 'Q3', 'Q4']\nonline = [15, 22, 28, 35]\nretail = [8, 12, 15, 18]\nwholesale = [5, 11, 13, 25]\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\n# Create stacked bars\nax.bar(categories, online, label='Online', color='#3498db')\nax.bar(categories, retail, bottom=online, label='Retail', color='#2ecc71')\nax.bar(categories, wholesale, bottom=np.array(online) + np.array(retail),\n label='Wholesale', color='#e74c3c')\n\nax.set_xlabel('Quarter', fontsize=12)\nax.set_ylabel('Revenue (millions)', fontsize=12)\nax.set_title('Revenue by Channel', fontsize=14, fontweight='bold')\nax.legend(fontsize=10)\nax.grid(axis='y', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('stacked_revenue.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Horizontal Bar Chart\n\n```python\nimport matplotlib.pyplot as plt\n\ncategories = ['Customer Service', 'Product Quality', 'Delivery Speed',\n 'Price Value', 'Website UX']\nscores = [4.2, 4.5, 3.8, 4.0, 4.3]\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\n# Create horizontal bars\nbars = ax.barh(categories, scores, color='mediumseagreen', edgecolor='black', linewidth=0.7)\n\n# Add value labels\nfor i, bar in enumerate(bars):\n width = bar.get_width()\n ax.text(width + 0.05, bar.get_y() + bar.get_height()/2.,\n f'{scores[i]:.1f}',\n ha='left', va='center', fontsize=10, fontweight='bold')\n\nax.set_xlabel('Rating (out of 5)', fontsize=12)\nax.set_title('Customer Satisfaction Ratings', fontsize=14, fontweight='bold')\nax.set_xlim(0, 5)\nax.grid(axis='x', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('satisfaction_ratings.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Line Charts\n\nLine charts show trends over time.\n\n### Single Line Chart\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Data\nmonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']\nusers = [120, 135, 158, 172, 198, 225, 245, 268, 290, 315, 342, 380]\n\nfig, ax = plt.subplots(figsize=(9, 5))\n\n# Create line plot\nax.plot(months, users, marker='o', linewidth=2.5, markersize=6,\n color='steelblue', markerfacecolor='white', markeredgewidth=2)\n\n# Styling\nax.set_xlabel('Month', fontsize=12)\nax.set_ylabel('Active Users (thousands)', fontsize=12)\nax.set_title('Monthly Active User Growth', fontsize=14, fontweight='bold')\nax.grid(True, alpha=0.3, linestyle='--')\nax.set_axisbelow(True)\n\n# Annotate peak\npeak_idx = users.index(max(users))\nax.annotate(f'Peak: {max(users)}k',\n xy=(peak_idx, max(users)),\n xytext=(peak_idx-1, max(users)+20),\n arrowprops=dict(arrowstyle='->', color='red', lw=1.5),\n fontsize=10, fontweight='bold', color='red')\n\nplt.tight_layout()\nplt.savefig('user_growth.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Multi-Series Line Chart\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nmonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']\nproduct_a = [23, 25, 28, 32, 35, 40]\nproduct_b = [18, 21, 24, 23, 26, 30]\nproduct_c = [15, 16, 19, 22, 25, 28]\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\n# Plot multiple lines\nax.plot(months, product_a, marker='o', linewidth=2, label='Product A', color='#e74c3c')\nax.plot(months, product_b, marker='s', linewidth=2, label='Product B', color='#3498db')\nax.plot(months, product_c, marker='^', linewidth=2, label='Product C', color='#2ecc71')\n\nax.set_xlabel('Month', fontsize=12)\nax.set_ylabel('Sales (thousands)', fontsize=12)\nax.set_title('Product Sales Trends', fontsize=14, fontweight='bold')\nax.legend(fontsize=10, loc='upper left', frameon=True, shadow=True)\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('product_trends.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Line Chart with Confidence Interval\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nx = np.linspace(0, 10, 50)\ny = 2 * x + 3 + np.random.randn(50) * 2\ny_smooth = 2 * x + 3\ny_upper = y_smooth + 4\ny_lower = y_smooth - 4\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\n# Plot confidence interval\nax.fill_between(x, y_lower, y_upper, alpha=0.2, color='steelblue', label='95% CI')\n# Plot mean line\nax.plot(x, y_smooth, linewidth=2.5, color='steelblue', label='Mean')\n# Plot actual data\nax.scatter(x, y, s=20, alpha=0.5, color='darkblue', label='Observed')\n\nax.set_xlabel('Time (hours)', fontsize=12)\nax.set_ylabel('Temperature (°C)', fontsize=12)\nax.set_title('Temperature Measurements with Confidence Interval', fontsize=14, fontweight='bold')\nax.legend(fontsize=10)\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('confidence_interval.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Scatter Plots\n\nScatter plots show relationships between two variables.\n\n### Basic Scatter Plot\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Generate sample data\nnp.random.seed(42)\nx = np.random.randn(100) * 10 + 50\ny = 2.5 * x + np.random.randn(100) * 20 + 10\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\n# Create scatter plot\nax.scatter(x, y, s=50, alpha=0.6, color='steelblue', edgecolors='black', linewidth=0.5)\n\nax.set_xlabel('Study Hours', fontsize=12)\nax.set_ylabel('Test Score', fontsize=12)\nax.set_title('Relationship Between Study Time and Test Performance', fontsize=14, fontweight='bold')\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('scatter_basic.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Scatter Plot with Trend Line\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom scipy import stats\n\nnp.random.seed(42)\nx = np.random.randn(100) * 10 + 50\ny = 2.5 * x + np.random.randn(100) * 20 + 10\n\n# Calculate regression line\nslope, intercept, r_value, p_value, std_err = stats.linregress(x, y)\nline = slope * x + intercept\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\n# Scatter plot\nax.scatter(x, y, s=50, alpha=0.6, color='steelblue',\n edgecolors='black', linewidth=0.5, label='Data points')\n\n# Regression line\nax.plot(x, line, 'r-', linewidth=2.5, label=f'Fit: y={slope:.2f}x+{intercept:.2f}')\n\n# Add R² value\nax.text(0.05, 0.95, f'$R^2$ = {r_value**2:.3f}',\n transform=ax.transAxes, fontsize=11,\n verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5))\n\nax.set_xlabel('Study Hours', fontsize=12)\nax.set_ylabel('Test Score', fontsize=12)\nax.set_title('Study Time vs Test Performance with Linear Regression', fontsize=14, fontweight='bold')\nax.legend(fontsize=10)\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('scatter_regression.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Scatter Plot with Color Coding\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nnp.random.seed(42)\nx = np.random.rand(100) * 100\ny = np.random.rand(100) * 100\ncolors = np.random.rand(100) * 100 # Color by third variable\nsizes = np.random.rand(100) * 500 + 50 # Size by fourth variable\n\nfig, ax = plt.subplots(figsize=(8, 6))\n\nscatter = ax.scatter(x, y, c=colors, s=sizes, alpha=0.6,\n cmap='viridis', edgecolors='black', linewidth=0.5)\n\n# Add colorbar\ncbar = plt.colorbar(scatter, ax=ax)\ncbar.set_label('Performance Score', fontsize=11)\n\nax.set_xlabel('Feature A', fontsize=12)\nax.set_ylabel('Feature B', fontsize=12)\nax.set_title('Multi-dimensional Data Visualization', fontsize=14, fontweight='bold')\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('scatter_colored.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Pie and Donut Charts\n\n### Pie Chart\n\n```python\nimport matplotlib.pyplot as plt\n\ncategories = ['Mobile', 'Desktop', 'Tablet', 'Other']\nvalues = [45, 35, 15, 5]\ncolors = ['#ff9999', '#66b3ff', '#99ff99', '#ffcc99']\nexplode = (0.1, 0, 0, 0) # Explode first slice\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\nwedges, texts, autotexts = ax.pie(values, explode=explode, labels=categories,\n colors=colors, autopct='%1.1f%%',\n shadow=True, startangle=90)\n\n# Styling\nfor text in texts:\n text.set_fontsize(12)\n text.set_fontweight('bold')\n\nfor autotext in autotexts:\n autotext.set_color('white')\n autotext.set_fontsize(11)\n autotext.set_fontweight('bold')\n\nax.set_title('Traffic by Device Type', fontsize=14, fontweight='bold')\n\nplt.tight_layout()\nplt.savefig('device_pie.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Donut Chart\n\n```python\nimport matplotlib.pyplot as plt\n\ncategories = ['Development', 'Marketing', 'Operations', 'Research']\nvalues = [40, 25, 20, 15]\ncolors = ['#3498db', '#e74c3c', '#2ecc71', '#f39c12']\n\nfig, ax = plt.subplots(figsize=(7, 5))\n\n# Create donut (pie with center circle)\nwedges, texts, autotexts = ax.pie(values, labels=categories, colors=colors,\n autopct='%1.1f%%', startangle=90,\n pctdistance=0.85)\n\n# Draw center circle\ncentre_circle = plt.Circle((0, 0), 0.70, fc='white')\nax.add_artist(centre_circle)\n\n# Add center text\nax.text(0, 0, 'Budget\\n$1.2M', ha='center', va='center',\n fontsize=14, fontweight='bold')\n\nfor autotext in autotexts:\n autotext.set_color('white')\n autotext.set_fontsize(10)\n autotext.set_fontweight('bold')\n\nax.set_title('Department Budget Allocation', fontsize=14, fontweight='bold')\n\nplt.tight_layout()\nplt.savefig('budget_donut.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Heatmaps\n\nHeatmaps visualize matrix data with colors.\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\n\n# Sample correlation matrix\nnp.random.seed(42)\ndata = np.random.rand(8, 8)\ncorrelation = np.corrcoef(data)\n\nlabels = ['Feature 1', 'Feature 2', 'Feature 3', 'Feature 4',\n 'Feature 5', 'Feature 6', 'Feature 7', 'Feature 8']\n\nfig, ax = plt.subplots(figsize=(9, 7))\n\n# Create heatmap\nim = ax.imshow(correlation, cmap='coolwarm', aspect='auto', vmin=-1, vmax=1)\n\n# Set ticks and labels\nax.set_xticks(np.arange(len(labels)))\nax.set_yticks(np.arange(len(labels)))\nax.set_xticklabels(labels, rotation=45, ha='right')\nax.set_yticklabels(labels)\n\n# Add colorbar\ncbar = plt.colorbar(im, ax=ax)\ncbar.set_label('Correlation Coefficient', fontsize=11)\n\n# Add text annotations\nfor i in range(len(labels)):\n for j in range(len(labels)):\n text = ax.text(j, i, f'{correlation[i, j]:.2f}',\n ha=\"center\", va=\"center\", color=\"black\", fontsize=8)\n\nax.set_title('Feature Correlation Heatmap', fontsize=14, fontweight='bold')\n\nplt.tight_layout()\nplt.savefig('heatmap.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Heatmap with Seaborn\n\n```python\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport numpy as np\nimport pandas as pd\n\n# Create sample data\nnp.random.seed(42)\ndata = np.random.rand(10, 12)\ndf = pd.DataFrame(data,\n columns=[f'M{i}' for i in range(1, 13)],\n index=[f'Product {i}' for i in range(1, 11)])\n\nfig, ax = plt.subplots(figsize=(10, 6))\n\n# Create heatmap with seaborn\nsns.heatmap(df, annot=True, fmt='.2f', cmap='YlOrRd',\n linewidths=0.5, cbar_kws={'label': 'Sales (millions)'},\n ax=ax)\n\nax.set_title('Monthly Sales by Product', fontsize=14, fontweight='bold')\nax.set_xlabel('Month', fontsize=12)\nax.set_ylabel('Product', fontsize=12)\n\nplt.tight_layout()\nplt.savefig('sales_heatmap.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Box Plots and Violin Plots\n\n### Box Plot\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nnp.random.seed(42)\ndata = [np.random.normal(100, 10, 200),\n np.random.normal(110, 15, 200),\n np.random.normal(105, 12, 200),\n np.random.normal(115, 20, 200)]\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\nbp = ax.boxplot(data, labels=['Method A', 'Method B', 'Method C', 'Method D'],\n patch_artist=True, notch=True, showmeans=True)\n\n# Color boxes\ncolors = ['lightblue', 'lightgreen', 'lightyellow', 'lightcoral']\nfor patch, color in zip(bp['boxes'], colors):\n patch.set_facecolor(color)\n\nax.set_ylabel('Performance Score', fontsize=12)\nax.set_title('Performance Comparison Across Methods', fontsize=14, fontweight='bold')\nax.grid(axis='y', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('boxplot.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Violin Plot\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nnp.random.seed(42)\ndata = [np.random.normal(100, 10, 200),\n np.random.normal(110, 15, 200),\n np.random.normal(105, 12, 200),\n np.random.normal(115, 20, 200)]\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\nparts = ax.violinplot(data, showmeans=True, showmedians=True)\n\n# Color violins\ncolors = ['lightblue', 'lightgreen', 'lightyellow', 'lightcoral']\nfor pc, color in zip(parts['bodies'], colors):\n pc.set_facecolor(color)\n pc.set_alpha(0.7)\n\nax.set_xticks([1, 2, 3, 4])\nax.set_xticklabels(['Method A', 'Method B', 'Method C', 'Method D'])\nax.set_ylabel('Performance Score', fontsize=12)\nax.set_title('Performance Distribution Across Methods', fontsize=14, fontweight='bold')\nax.grid(axis='y', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('violinplot.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Histograms\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom scipy import stats\n\nnp.random.seed(42)\ndata = np.random.normal(100, 15, 1000)\n\nfig, ax = plt.subplots(figsize=(8, 5))\n\n# Create histogram\nn, bins, patches = ax.hist(data, bins=30, density=True, alpha=0.7,\n color='steelblue', edgecolor='black')\n\n# Fit normal distribution\nmu, sigma = stats.norm.fit(data)\nx = np.linspace(data.min(), data.max(), 100)\nax.plot(x, stats.norm.pdf(x, mu, sigma), 'r-', linewidth=2.5,\n label=f'Normal fit\\n$\\mu={mu:.1f}$, $\\sigma={sigma:.1f}

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

)\n\nax.set_xlabel('Value', fontsize=12)\nax.set_ylabel('Density', fontsize=12)\nax.set_title('Distribution of Sample Data', fontsize=14, fontweight='bold')\nax.legend(fontsize=10)\nax.grid(axis='y', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('histogram.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Area Charts\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\nmonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']\nproduct_a = [20, 25, 30, 35, 40, 45]\nproduct_b = [15, 18, 22, 25, 28, 32]\nproduct_c = [10, 12, 15, 18, 20, 23]\n\nfig, ax = plt.subplots(figsize=(9, 5))\n\n# Stacked area chart\nax.fill_between(months, 0, product_a, alpha=0.7, label='Product A', color='#3498db')\nax.fill_between(months, product_a, np.array(product_a) + np.array(product_b),\n alpha=0.7, label='Product B', color='#2ecc71')\nax.fill_between(months, np.array(product_a) + np.array(product_b),\n np.array(product_a) + np.array(product_b) + np.array(product_c),\n alpha=0.7, label='Product C', color='#e74c3c')\n\nax.set_xlabel('Month', fontsize=12)\nax.set_ylabel('Sales (thousands)', fontsize=12)\nax.set_title('Product Sales Composition Over Time', fontsize=14, fontweight='bold')\nax.legend(fontsize=10, loc='upper left')\nax.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('area_chart.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Radar/Spider Charts\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy as np\n\ncategories = ['Speed', 'Reliability', 'Ease of Use', 'Features', 'Support', 'Price']\nvalues = [4.5, 4.2, 4.8, 3.9, 4.1, 4.6]\n\n# Number of variables\nN = len(categories)\n\n# Compute angle for each axis\nangles = [n / float(N) * 2 * np.pi for n in range(N)]\nvalues += values[:1] # Complete the circle\nangles += angles[:1]\n\nfig, ax = plt.subplots(figsize=(7, 7), subplot_kw=dict(projection='polar'))\n\n# Plot data\nax.plot(angles, values, 'o-', linewidth=2, color='steelblue')\nax.fill(angles, values, alpha=0.25, color='steelblue')\n\n# Fix axis labels\nax.set_xticks(angles[:-1])\nax.set_xticklabels(categories, fontsize=11)\n\n# Set y-axis limits\nax.set_ylim(0, 5)\nax.set_yticks([1, 2, 3, 4, 5])\nax.set_yticklabels(['1', '2', '3', '4', '5'], fontsize=9)\n\nax.set_title('Product Evaluation Radar Chart', fontsize=14, fontweight='bold', pad=20)\nax.grid(True)\n\nplt.tight_layout()\nplt.savefig('radar_chart.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Using CSV Data with Pandas\n\n### Reading and Plotting CSV\n\n```python\nimport matplotlib.pyplot as plt\nimport pandas as pd\n\n# Read CSV file\ndf = pd.read_csv('sales_data.csv')\n\n# Example CSV structure:\n# Month,Product_A,Product_B,Product_C\n# Jan,23,18,15\n# Feb,25,21,16\n# ...\n\nfig, ax = plt.subplots(figsize=(9, 5))\n\n# Plot each column\nax.plot(df['Month'], df['Product_A'], marker='o', linewidth=2, label='Product A')\nax.plot(df['Month'], df['Product_B'], marker='s', linewidth=2, label='Product B')\nax.plot(df['Month'], df['Product_C'], marker='^', linewidth=2, label='Product C')\n\nax.set_xlabel('Month', fontsize=12)\nax.set_ylabel('Sales (thousands)', fontsize=12)\nax.set_title('Product Sales from CSV Data', fontsize=14, fontweight='bold')\nax.legend(fontsize=10)\nax.grid(True, alpha=0.3)\nplt.xticks(rotation=45)\n\nplt.tight_layout()\nplt.savefig('csv_chart.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n### Grouped Bar Chart from CSV\n\n```python\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport numpy as np\n\ndf = pd.read_csv('comparison.csv')\n\n# Example CSV:\n# Category,Method_A,Method_B\n# Task1,23,28\n# Task2,34,39\n# ...\n\ncategories = df['Category']\nx = np.arange(len(categories))\nwidth = 0.35\n\nfig, ax = plt.subplots(figsize=(9, 5))\n\nbars1 = ax.bar(x - width/2, df['Method_A'], width, label='Method A', color='lightcoral')\nbars2 = ax.bar(x + width/2, df['Method_B'], width, label='Method B', color='steelblue')\n\nax.set_xlabel('Task', fontsize=12)\nax.set_ylabel('Performance', fontsize=12)\nax.set_title('Method Comparison from CSV', fontsize=14, fontweight='bold')\nax.set_xticks(x)\nax.set_xticklabels(categories)\nax.legend(fontsize=10)\nax.grid(axis='y', alpha=0.3)\n\nplt.tight_layout()\nplt.savefig('csv_comparison.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Styling for LaTeX\n\n### Font Configuration\n\n```python\nimport matplotlib.pyplot as plt\nimport matplotlib\n\n# Use LaTeX for text rendering (requires LaTeX installation)\nmatplotlib.rcParams['text.usetex'] = True\nmatplotlib.rcParams['font.family'] = 'serif'\nmatplotlib.rcParams['font.serif'] = ['Computer Modern Roman']\n\n# Or use standard fonts\nmatplotlib.rcParams['font.family'] = 'sans-serif'\nmatplotlib.rcParams['font.size'] = 11\n```\n\n### Figure Sizes for LaTeX\n\n```python\n# Common LaTeX column widths\nSINGLE_COLUMN = 3.5 # inches\nDOUBLE_COLUMN = 7.0 # inches\n\n# Create figure with appropriate size\nfig, ax = plt.subplots(figsize=(SINGLE_COLUMN, SINGLE_COLUMN*0.75))\n```\n\n### DPI Settings\n\n```python\n# High resolution for publication\nplt.savefig('chart.pdf', dpi=300, bbox_inches='tight')\n\n# For screen display\nplt.savefig('chart.png', dpi=150, bbox_inches='tight')\n\n# Extra high resolution for posters\nplt.savefig('chart.pdf', dpi=600, bbox_inches='tight')\n```\n\n### Style Presets\n\n```python\nimport matplotlib.pyplot as plt\n\n# Use built-in styles\nplt.style.use('seaborn-v0_8-paper') # Clean academic style\n# plt.style.use('ggplot') # R ggplot2 style\n# plt.style.use('bmh') # Bayesian Methods for Hackers style\n\n# Or create custom style\nplt.rcParams.update({\n 'font.size': 11,\n 'axes.labelsize': 12,\n 'axes.titlesize': 14,\n 'xtick.labelsize': 10,\n 'ytick.labelsize': 10,\n 'legend.fontsize': 10,\n 'figure.figsize': (7, 5),\n 'axes.grid': True,\n 'grid.alpha': 0.3,\n 'grid.linestyle': '--',\n})\n```\n\n---\n\n## Color Palettes\n\n### Colorblind-Friendly Palettes\n\n```python\nimport matplotlib.pyplot as plt\n\n# IBM colorblind-safe palette\ncolors_ibm = ['#648FFF', '#785EF0', '#DC267F', '#FE6100', '#FFB000']\n\n# Tableau 10 (colorblind-safe)\ncolors_tableau = plt.cm.tab10.colors\n\n# Seaborn colorblind palette\nimport seaborn as sns\ncolors_sns = sns.color_palette('colorblind')\n\n# Use in plot\nfig, ax = plt.subplots()\nfor i, color in enumerate(colors_ibm):\n ax.bar(i, i+1, color=color)\n```\n\n### Custom Color Maps\n\n```python\nfrom matplotlib.colors import LinearSegmentedColormap\n\n# Define custom colormap\ncolors = ['#2E86AB', '#A23B72', '#F18F01']\nn_bins = 100\ncmap = LinearSegmentedColormap.from_list('custom', colors, N=n_bins)\n\n# Use in heatmap\nimport numpy as np\ndata = np.random.rand(10, 10)\nplt.imshow(data, cmap=cmap)\nplt.colorbar()\n```\n\n---\n\n## Saving as PNG vs PDF\n\n### When to Use PNG\n\n- **Raster graphics** with many data points\n- **Web publishing** or presentations\n- **Quick previews** during development\n- **Complex visualizations** (heatmaps with many cells)\n\n```python\nplt.savefig('chart.png', dpi=300, bbox_inches='tight',\n facecolor='white', edgecolor='none')\n```\n\n### When to Use PDF\n\n- **Publication-quality** figures\n- **LaTeX documents** (vector graphics scale perfectly)\n- **Simple plots** (lines, bars, scatter)\n- **When file size matters less**\n\n```python\nplt.savefig('chart.pdf', dpi=300, bbox_inches='tight')\n```\n\n### Best Practices\n\n```python\n# Always use bbox_inches='tight' to avoid clipping\n# Set appropriate DPI (300 for print, 150 for screen)\n# Close figure after saving to free memory\n\nplt.savefig('output.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n```\n\n---\n\n## Integration in LaTeX\n\n### Basic Inclusion\n\n```latex\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{chart.pdf}\n \\caption{Descriptive caption explaining the chart}\n \\label{fig:my-chart}\n\\end{figure}\n```\n\n### Side-by-Side Charts\n\n```latex\n\\usepackage{subcaption}\n\n\\begin{figure}[H]\n \\centering\n \\begin{subfigure}[b]{0.48\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{chart1.pdf}\n \\caption{First chart}\n \\label{fig:chart1}\n \\end{subfigure}\n \\hfill\n \\begin{subfigure}[b]{0.48\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{chart2.pdf}\n \\caption{Second chart}\n \\label{fig:chart2}\n \\end{subfigure}\n \\caption{Comparison of two methods}\n \\label{fig:comparison}\n\\end{figure}\n```\n\n### Wrapping Text Around Figure\n\n```latex\n\\usepackage{wrapfig}\n\n\\begin{wrapfigure}{r}{0.5\\textwidth}\n \\centering\n \\includegraphics[width=0.48\\textwidth]{chart.pdf}\n \\caption{Small chart with text wrap}\n \\label{fig:wrap}\n\\end{wrapfigure}\n\nText flows around the figure...\n```\n\n---\n\n## Comparison: Matplotlib vs pgfplots\n\n| Feature | Matplotlib | pgfplots |\n|---------|-----------|----------|\n| **Data Processing** | Excellent (numpy/pandas) | Limited (reads CSV) |\n| **Syntax** | Python code | LaTeX code |\n| **Learning Curve** | Moderate | Steep |\n| **Customization** | Very flexible | Very flexible |\n| **Quality** | High (raster/vector) | Excellent (native vector) |\n| **File Size** | Can be large | Usually smaller |\n| **Compilation** | Pre-compile (fast LaTeX) | Compile-time (slower) |\n| **Font Matching** | External (config needed) | Native LaTeX fonts |\n| **Complex Data** | Excellent | Poor |\n| **Interactivity** | Yes (Jupyter) | No |\n| **Version Control** | Python scripts | LaTeX code |\n| **Dependencies** | Python + packages | LaTeX + pgfplots |\n| **Best For** | Complex analysis, large data | Simple plots, perfect LaTeX integration |\n\n### Use Matplotlib When:\n\n- Processing complex datasets (CSV, databases, APIs)\n- Using pandas for data manipulation\n- Need statistical analysis (scipy, scikit-learn)\n- Creating many charts programmatically\n- Exploratory data analysis\n- Large datasets (1000+ points)\n- Custom visualizations not easily done in pgfplots\n\n### Use pgfplots When:\n\n- Small datasets (\u003c 100 points)\n- Need perfect LaTeX font matching\n- Want inline data in LaTeX\n- Simpler plots (line, bar, scatter basics)\n- Minimizing external dependencies\n- Vector graphics with minimal file size\n- Native LaTeX compilation\n\n---\n\n## Complete Example Workflow\n\n### 1. Python Script (generate_charts.py)\n\n```python\n#!/usr/bin/env python3\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport numpy as np\n\n# Set style\nplt.style.use('seaborn-v0_8-paper')\nplt.rcParams['font.size'] = 11\n\n# Read data\ndf = pd.read_csv('experiment_data.csv')\n\n# Chart 1: Line plot\nfig, ax = plt.subplots(figsize=(7, 4))\nax.plot(df['time'], df['measurement'], marker='o', linewidth=2)\nax.set_xlabel('Time (s)')\nax.set_ylabel('Measurement (units)')\nax.set_title('Experimental Results Over Time')\nax.grid(True, alpha=0.3)\nplt.tight_layout()\nplt.savefig('figures/time_series.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n\n# Chart 2: Bar plot\nfig, ax = plt.subplots(figsize=(6, 4))\nmethods = ['Method A', 'Method B', 'Method C']\nscores = [85, 92, 78]\nax.bar(methods, scores, color='steelblue', edgecolor='black')\nax.set_ylabel('Performance Score')\nax.set_title('Method Comparison')\nax.grid(axis='y', alpha=0.3)\nplt.tight_layout()\nplt.savefig('figures/method_comparison.pdf', dpi=300, bbox_inches='tight')\nplt.close()\n\nprint(\"Charts generated successfully!\")\n```\n\n### 2. LaTeX Document\n\n```latex\n\\documentclass{article}\n\\usepackage{graphicx}\n\\usepackage{float}\n\\usepackage{subcaption}\n\n\\begin{document}\n\n\\section{Results}\n\nFigure~\\ref{fig:time-series} shows the experimental measurements\ncollected over a 10-hour period. The data exhibits a clear upward\ntrend with some periodic variations.\n\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{figures/time_series.pdf}\n \\caption{Time series of experimental measurements}\n \\label{fig:time-series}\n\\end{figure}\n\nWe compared three different methods (Figure~\\ref{fig:methods}).\nMethod B achieved the highest performance score of 92\\%, followed\nby Method A at 85\\%.\n\n\\begin{figure}[H]\n \\centering\n \\includegraphics[width=0.7\\textwidth]{figures/method_comparison.pdf}\n \\caption{Performance comparison across three methods}\n \\label{fig:methods}\n\\end{figure}\n\n\\end{document}\n```\n\n### 3. Makefile\n\n```makefile\n.PHONY: all charts clean\n\nall: paper.pdf\n\ncharts:\n\tpython3 generate_charts.py\n\npaper.pdf: paper.tex charts\n\tpdflatex paper.tex\n\tpdflatex paper.tex\n\nclean:\n\trm -f *.aux *.log *.out\n\trm -f figures/*.pdf\n```\n\n### 4. Usage\n\n```bash\n# Generate all charts and compile document\nmake\n\n# Regenerate just the charts\nmake charts\n\n# Clean build files\nmake clean\n```\n\n---\n\n## Additional Resources\n\n- **Matplotlib Documentation**: https://matplotlib.org/stable/index.html\n- **Matplotlib Gallery**: https://matplotlib.org/stable/gallery/index.html\n- **Seaborn**: https://seaborn.pydata.org/ (high-level plotting)\n- **Pandas Plotting**: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.html\n- **Color Palettes**: https://colorbrewer2.org/\n- **LaTeX Graphics**: https://en.wikibooks.org/wiki/LaTeX/Importing_Graphics\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":31406,"content_sha256":"24eacdca0b2bac5585412db2f4239df0a4a11a4d7f8d603b0363dc188f4ed230"},{"filename":"references/qa-test-report.md","content":"# QA Test Report: PDF-to-Cheatsheet Pipeline\n\n**Test Date:** 2026-02-16\n**Test Scope:** 8 real academic PDFs across 3 template types\n**Test Objective:** Validate end-to-end pipeline robustness and identify systematic issues\n\n---\n\n## Executive Summary\n\nTested the PDF-to-cheatsheet conversion pipeline with 8 academic papers (9-88 pages) across all 3 template types. All cheatsheets compiled successfully with 0 LaTeX errors. However, **content overflow is a critical systematic issue** - every single cheatsheet initially overflowed by 50-150%. After manual intervention, compression ratios of up to 44:1 were achieved.\n\n**Key Recommendation:** Add explicit character-count content budgets and compile-after-page-1 checkpoints to SKILL.md.\n\n---\n\n## Test Matrix\n\n| Cheatsheet | Source PDF | Pages | Template | Final Pages | Errors | Overfull | Underfull |\n|------------|-----------|-------|----------|-------------|--------|----------|-----------|\n| quantum-exam | Quantum Computing NISQ (Preskill 2018) | 20 | Exam (2-col portrait 6pt) | 2 | 0 | 0 | 0 |\n| deeplearning-exam | Deep Learning in Neural Networks (Schmidhuber 2014) | 88 | Exam (2-col portrait 6pt) | 2 | 0 | 0 | 1 |\n| algorithms-exam | Gated State Spaces (Mehta et al. 2022) | 15 | Exam (2-col portrait 6pt) | 2 | 0 | 0 | 0 |\n| transformers-general | Efficient Transformers Survey (Tay et al. 2022) | 39 | General (3-col landscape 7pt) | 2 | 0 | 1 | 2 |\n| probability-general | Zero-shot Learning with Knowledge Graphs | 34 | General (3-col landscape 7pt) | 2 | 0 | 0 | 1 |\n| mlsurvey-general | Semantic Drift in Text Generation | 16 | General (3-col landscape 7pt) | 2 | 0 | 0 | 0 |\n| chemistry-code | Deep Molecular Dreaming (Shen et al. 2020) | 9 | Code (4-col landscape 7pt) | 2 | 0 | 0 | 6 |\n| linalg-code | Stochastic Gates Feature Selection | 28 | Code (4-col landscape 7pt) | 2 | 0 | 1 | 7 |\n\n**Summary Statistics:**\n- Total sheets tested: 8\n- LaTeX compilation errors: 0\n- Overfull box warnings: 2 (minor)\n- Underfull box warnings: 17 (mostly code template)\n- Success rate (0 errors): 100%\n\n---\n\n## Critical Findings\n\n### 1. CRITICAL: Content Overflow is the #1 Systematic Issue\n\n**Observation:** Every single cheatsheet overflowed on first generation.\n\n**Overflow Magnitude:**\n- **Exam template** (2-col portrait): Generated 5 pages instead of 2 (150% overflow)\n- **General template** (3-col landscape): Generated 3-5 pages instead of 2 (50-150% overflow)\n- **Code template** (4-col landscape): Generated 3 pages instead of 2 (50% overflow)\n\n**Root Cause:** The LLM generates too much content per section. Without explicit constraints, the model prioritizes completeness over density. It does not naturally constrain to a target page count.\n\n**Impact:** Requires manual trimming and recompilation cycles, defeating the purpose of automated generation.\n\n**Recommendation for SKILL.md:**\n\nAdd explicit content budgets based on template type:\n\n```\n## Content Budgets (Target: 2 pages)\n\n- **Exam template** (2-col portrait, 6pt): ~4,500 characters of LaTeX content per page (9,000 total)\n- **General template** (3-col landscape, 7pt): ~8,000 characters per page (16,000 total)\n- **Code template** (4-col landscape, 7pt): ~9,000 characters per page (18,000 total)\n\n**CRITICAL WORKFLOW:**\n1. Write page 1 content only\n2. Compile and check page count with `pdfinfo output.pdf | grep Pages`\n3. If page 1 is exactly 1 page, proceed to page 2\n4. If page 1 exceeds 1 page, trim by 20% and recompile before proceeding\n```\n\n---\n\n### 2. Content Distribution Problem\n\n**Observation:** After fixing overflow, several sheets show uneven column/page distribution:\n- Left/first columns packed tight\n- Rightmost column or bottom 30-50% of page 2 empty\n\n**Root Cause:** The `multicols` environment distributes content evenly across columns, but `\\newpage` forces a hard page break. When page 1 has less than a full page of content, the remaining space on page 1 is wasted.\n\n**Example (Bad):**\n```latex\n\\begin{multicols}{3}\n... page 1 content (not enough to fill all columns) ...\n\\newpage % Forces new page, leaving page 1 partially empty\n... page 2 content ...\n\\end{multicols}\n```\n\n**Recommendation for SKILL.md:**\n\nUse `\\columnbreak` for fine-grained control. For page breaks, end the multicols environment first:\n\n```latex\n\\begin{multicols}{3}\n... page 1 content ...\n\\end{multicols}\n\n\\newpage\n\n\\begin{multicols}{3}\n... page 2 content ...\n\\end{multicols}\n```\n\nFor column breaks within a page:\n```latex\n\\begin{multicols}{3}\n... content in column 1 ...\n\\columnbreak\n... content in column 2 ...\n\\columnbreak\n... content in column 3 ...\n\\end{multicols}\n```\n\n---\n\n### 3. Underfull Box Warnings (Minor Issue)\n\n**Observation:** Code template produces the most underfull warnings (6-7 per sheet).\n\n**Root Cause:** 4-column landscape creates very narrow columns (~60mm wide). Content doesn't always fill the width perfectly, especially with long equations or tight spacing.\n\n**Impact:** Cosmetic only - does not affect functionality or readability.\n\n**Recommendation:** Use `\\sloppy` within narrow-column contexts to reduce warnings:\n\n```latex\n\\begin{multicols}{4}\n\\sloppy % Relax spacing constraints\n... content ...\n\\end{multicols}\n```\n\n---\n\n### 4. Zero LaTeX Compilation Errors\n\n**Observation:** All 8 cheatsheets compiled with 0 LaTeX errors after content fixes.\n\n**Contributing Factors:**\n- Template preambles are robust and comprehensive\n- Key anti-patterns are well-documented in SKILL.md:\n - No blank lines within `\\begin{multicols}...\\end{multicols}`\n - No `\\fbox` naming conflicts\n - No trailing commas in package options\n\n**Conclusion:** The template infrastructure and error-prevention guidance in SKILL.md are working effectively.\n\n---\n\n### 5. Compression Ratios Achieved\n\n| Source Paper | Source Pages | Output Pages | Compression Ratio |\n|--------------|--------------|--------------|-------------------|\n| Deep Learning in Neural Networks (Schmidhuber 2014) | 88 | 2 | **44:1** |\n| Efficient Transformers Survey (Tay et al. 2022) | 39 | 2 | **19.5:1** |\n| Zero-shot Learning with Knowledge Graphs | 34 | 2 | **17:1** |\n| Stochastic Gates Feature Selection | 28 | 2 | **14:1** |\n| Quantum Computing NISQ (Preskill 2018) | 20 | 2 | **10:1** |\n| Semantic Drift in Text Generation | 16 | 2 | **8:1** |\n| Gated State Spaces (Mehta et al. 2022) | 15 | 2 | **7.5:1** |\n| Deep Molecular Dreaming (Shen et al. 2020) | 9 | 2 | **4.5:1** |\n\n**Key Insight:** Successfully achieved up to **44:1 compression** (88 pages → 2 pages) with the exam template. This demonstrates the pipeline can handle very large sources, but requires aggressive prioritization and trimming.\n\n---\n\n### 6. Template Performance Comparison\n\nAll 3 templates compiled successfully. Each has distinct strengths:\n\n#### Exam Template (2-col portrait, 6pt)\n- **Best for:** Math-heavy content, equations, proofs\n- **Strengths:** Formulas render cleanly, good readability for symbols\n- **Weaknesses:** Lower density than landscape templates\n- **Content capacity:** ~9,000 characters for 2 pages\n\n#### General Template (3-col landscape, 7pt)\n- **Best for:** Mixed text/equations, survey papers\n- **Strengths:** Good balance of density and readability\n- **Weaknesses:** Moderate column width can make very long equations wrap awkwardly\n- **Content capacity:** ~16,000 characters for 2 pages\n\n#### Code Template (4-col landscape, 7pt)\n- **Best for:** Algorithm-heavy content, lists, taxonomies\n- **Strengths:** Highest density, excellent for dense information\n- **Weaknesses:** Narrow columns (~60mm) make long formulas challenging\n- **Content capacity:** ~18,000 characters for 2 pages\n- **Note:** Produces most underfull warnings (cosmetic issue only)\n\n---\n\n## Recommendations for SKILL.md Updates\n\n### High Priority\n\n1. **Add explicit character-count content budgets per template type**\n - Exam: 4,500 chars/page (9,000 total)\n - General: 8,000 chars/page (16,000 total)\n - Code: 9,000 chars/page (18,000 total)\n\n2. **Add compile-after-page-1 checkpoint instruction**\n ```\n CRITICAL WORKFLOW:\n 1. Write page 1 content only\n 2. Compile and verify: pdfinfo output.pdf | grep Pages\n 3. If output shows \"Pages: 1\", proceed to page 2\n 4. If output shows \"Pages: 2+\" , trim content by 20% and recompile\n ```\n\n3. **Add `\\columnbreak` usage guidance**\n - Explain difference between `\\columnbreak` (within multicols) and `\\newpage` (between multicols)\n - Show proper technique for page breaks in multicols environments\n\n### Medium Priority\n\n4. **Warn about uneven column distribution after aggressive trimming**\n - Note that overly aggressive trimming can leave rightmost columns empty\n - Recommend visual inspection after compilation\n\n5. **Add `\\sloppy` recommendation for 4-column layouts**\n - Reduces underfull box warnings in narrow columns\n - Cosmetic improvement with no functional impact\n\n6. **Add instruction to verify page count with `pdfinfo` after each compile**\n - Explicit command: `pdfinfo output.pdf | grep Pages`\n - Expected output: `Pages: 2`\n\n### Low Priority\n\n7. **Note that extreme compression ratios (40:1+) are achievable but require aggressive prioritization**\n - Set user expectations for large source documents\n - Emphasize importance of identifying core concepts vs. supporting details\n\n---\n\n## Test Methodology\n\n1. Selected 8 diverse academic papers spanning multiple domains (physics, CS, ML, chemistry)\n2. Tested each template type with multiple papers\n3. Generated cheatsheets using standard pipeline\n4. Compiled with `pdflatex` and captured all warnings/errors\n5. Iteratively trimmed content to achieve 2-page target\n6. Recorded final statistics for errors, warnings, and compression ratios\n\n---\n\n## Conclusion\n\nThe PDF-to-cheatsheet pipeline is fundamentally robust with 100% compilation success rate across 8 diverse test cases. The primary issue is content overflow, which is systematic and predictable. By adding explicit content budgets and compile-checkpoint workflows to SKILL.md, this issue can be mitigated at generation time rather than requiring manual post-processing.\n\n**Overall Assessment:** Production-ready with recommended SKILL.md updates.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":10139,"content_sha256":"b2c28515ea8f0d49391f3a628d5bae15865db0ba96baff73fe0d984ccbdf4aad"},{"filename":"references/resume-ats-guide.md","content":"# ATS-Optimized Resume Guide for LaTeX\n\n## Table of Contents\n- [ATS Overview](#ats-overview)\n- [LaTeX-Specific ATS Rules](#latex-specific-ats-rules)\n- [ATS-Safe Section Headings](#ats-safe-section-headings)\n- [Resume Format Selection Guide](#resume-format-selection-guide)\n- [Keyword Optimization](#keyword-optimization)\n- [Formatting Rules](#formatting-rules)\n- [Common LaTeX ATS Mistakes](#common-latex-ats-mistakes)\n- [Quantified Achievement Patterns](#quantified-achievement-patterns)\n- [Action Verbs by Category](#action-verbs-by-category)\n\n---\n\n## ATS Overview\n\n**Critical Context**: 98% of Fortune 500 companies use Applicant Tracking Systems (ATS). Your resume must pass ATS parsing before human eyes see it.\n\n**Major ATS Systems**:\n- Workday (most common)\n- Greenhouse\n- Lever\n- Taleo (Oracle)\n- iCIMS\n- BambooHR\n- SmartRecruiters\n\n**ATS Parsing Pipeline**:\n1. **Text Extraction**: Converts PDF to plain text (quality varies by system)\n2. **Field Identification**: Attempts to identify name, contact info, sections\n3. **Keyword Matching**: Compares extracted text against job description keywords\n4. **Scoring/Ranking**: Assigns match percentage and ranks candidates\n\n**Failure Points**: Complex layouts, embedded graphics, text in images, unusual fonts, multi-column formats.\n\n---\n\n## LaTeX-Specific ATS Rules\n\n### DO: ATS-Safe LaTeX Practices\n\n1. **Single-Column Layout**: Use standard linear top-to-bottom flow\n ```latex\n \\documentclass{article}\n \\begin{document}\n Name and contact info here\n \\section{Experience}\n \\section{Education}\n \\end{document}\n ```\n\n2. **Standard Document Class**: Use `article` or `report` class\n ```latex\n \\documentclass[11pt,letterpaper]{article}\n ```\n\n3. **Contact Info in Body**: Place directly in document body, not headers\n ```latex\n \\begin{center}\n {\\LARGE\\bfseries John Doe} \\\\[4pt]\n [email protected] $|$ (555) 123-4567 $|$ linkedin.com/in/johndoe\n \\end{center}\n ```\n\n4. **Use \\section for Headings**: Standard LaTeX sections for clear structure\n ```latex\n \\section*{Experience}\n \\section*{Education}\n \\section*{Skills}\n ```\n\n5. **Bullet Points with itemize**: Standard list environment\n ```latex\n \\begin{itemize}\n \\item Reduced API latency by 40%\n \\item Led team of 8 engineers\n \\end{itemize}\n ```\n\n6. **Standard Fonts**: Stick to widely-supported fonts\n - Computer Modern (default LaTeX)\n - Latin Modern: `\\usepackage{lmodern}`\n - Helvetica: `\\usepackage{helvet}` + `\\renewcommand{\\familydefault}{\\sfdefault}`\n\n### DO NOT: ATS-Breaking LaTeX Patterns\n\n1. **NO Multi-Column with minipage**: Creates side-by-side layout ATS can't parse\n ```latex\n % AVOID THIS:\n \\begin{minipage}[t]{0.5\\textwidth}\n Left column content\n \\end{minipage}\n \\begin{minipage}[t]{0.5\\textwidth}\n Right column content\n \\end{minipage}\n ```\n\n2. **NO Tables for Layout**: Tables (tabularx, tabular) confuse field extraction\n ```latex\n % AVOID FOR MAIN LAYOUT:\n \\begin{tabularx}{\\textwidth}{X X}\n Content & Content\n \\end{tabularx}\n ```\n **Exception**: Simple skills list in single row may be acceptable\n\n3. **NO Graphics/TikZ**: Images, logos, profile pictures are ignored or break parsing\n ```latex\n % AVOID:\n \\includegraphics[width=2cm]{photo.jpg}\n \\begin{tikzpicture}...\\end{tikzpicture}\n ```\n\n4. **NO Header/Footer Content**: Info in `\\pagestyle{fancy}` is often missed\n ```latex\n % AVOID:\n \\usepackage{fancyhdr}\n \\fancyhead[L]{John Doe}\n ```\n\n5. **NO Excessive Colored Hyperlinks**: Some ATS strip links; use sparingly\n ```latex\n % USE CAUTIOUSLY:\n \\usepackage[colorlinks=true]{hyperref}\n % BETTER:\n \\usepackage[hidelinks]{hyperref}\n ```\n\n6. **NO Custom Font Packages**: fontspec, custom TTF/OTF fonts may not embed\n ```latex\n % AVOID:\n \\usepackage{fontspec}\n \\setmainfont{CustomFont}\n ```\n\n7. **NO Color Fills/Backgrounds**: `\\rowcolor`, `\\cellcolor`, colored boxes\n ```latex\n % AVOID:\n \\usepackage[table]{xcolor}\n \\rowcolor{gray}\n ```\n\n---\n\n## ATS-Safe Section Headings\n\nATS systems are trained to recognize standard section names. Use these exact headings:\n\n### Recognized Headings (USE THESE):\n\n- **Professional Summary** or **Summary** or **Profile**\n- **Experience** or **Work Experience** or **Professional Experience**\n- **Education** or **Academic Credentials**\n- **Skills** or **Technical Skills** or **Core Competencies**\n- **Certifications** or **Licenses & Certifications**\n- **Projects** or **Key Projects**\n- **Awards** or **Honors & Awards**\n- **Publications**\n- **Volunteer Experience** or **Community Involvement**\n\n### Non-Standard Headings (AVOID):\n\n- \"About Me\" (use \"Summary\")\n- \"Who I Am\" (use \"Summary\")\n- \"My Journey\" (use \"Experience\")\n- \"Career Path\" (use \"Experience\")\n- \"What I Can Do\" (use \"Skills\")\n- \"Academic Background\" (use \"Education\")\n- \"Where I've Worked\" (use \"Experience\")\n\n**Rule**: If you wouldn't find the heading in a 1990s resume book, don't use it.\n\n---\n\n## Resume Format Selection Guide\n\n| Template | Best For | Key Features | ATS Rating | Page Limit |\n|----------|----------|--------------|------------|------------|\n| **resume-classic-ats** | Conservative industries (finance, law, government, healthcare) | Maximum simplicity, zero graphics, chronological | 10/10 | 1-2 pages |\n| **resume-modern-professional** | Tech, corporate, consulting, marketing | Clean design, subtle dividers, balanced visuals | 9/10 | 1-2 pages |\n| **resume-executive** | Senior/C-suite, 15+ years experience | Multi-page, leadership focus, board experience | 8/10 | 2-3 pages |\n| **resume-technical** | Software engineers, data scientists, DevOps | Skills-first hybrid, dedicated projects section | 9/10 | 1-2 pages |\n| **resume-entry-level** | Recent graduates, career changers, \u003c2 years exp | Education-first, relevant coursework, internships | 9/10 | 1 page |\n\n### Decision Tree:\n\n1. **Are you applying to finance/law/government?** → Use `resume-classic-ats`\n2. **Do you have \u003c2 years experience?** → Use `resume-entry-level`\n3. **Are you a senior executive (VP+)?** → Use `resume-executive`\n4. **Are you in technical role (engineering, data)?** → Use `resume-technical`\n5. **Everything else** → Use `resume-modern-professional`\n\n---\n\n## Keyword Optimization\n\n### Strategy 1: Mirror Job Description Language\n\n**Example Job Description**: \"Looking for Senior Software Engineer with expertise in React, Node.js, and AWS cloud infrastructure...\"\n\n**Your Resume Should Include**:\n- Exact phrase \"React\" (not just \"JavaScript frameworks\")\n- Exact phrase \"Node.js\" (not just \"backend development\")\n- Exact phrase \"AWS cloud infrastructure\" (not just \"cloud computing\")\n\n### Strategy 2: Acronyms + Spelled-Out Forms\n\nAlways include both versions:\n\n- \"Search Engine Optimization (SEO)\"\n- \"Application Programming Interface (API)\"\n- \"Continuous Integration/Continuous Deployment (CI/CD)\"\n- \"Customer Relationship Management (CRM)\"\n- \"Key Performance Indicator (KPI)\"\n\n### Strategy 3: Context Keywords in Experience\n\nDon't just list keywords in Skills section. Integrate them into Experience bullets:\n\n**Bad**:\n```\nSkills: Python, Machine Learning, TensorFlow\nExperience:\n- Developed predictive models for customer churn\n```\n\n**Good**:\n```\nSkills: Python, Machine Learning, TensorFlow, Scikit-learn\nExperience:\n- Developed machine learning models in Python using TensorFlow and Scikit-learn, reducing customer churn by 23%\n```\n\n### Strategy 4: Industry-Specific Certifications\n\nInclude certification keywords: \"AWS Certified Solutions Architect\", \"PMP\", \"CPA\", \"Six Sigma Black Belt\"\n\n### What NOT to Do:\n\n- **Keyword Stuffing**: Don't add invisible white text or repeat keywords 50 times\n- **Irrelevant Keywords**: Don't claim skills you don't have just because they're in the JD\n- **Over-Abbreviation**: Don't assume ATS knows \"GCP\" means \"Google Cloud Platform\"\n\n---\n\n## Formatting Rules\n\n### Font Specifications\n\n- **Body Text**: 10-12pt (11pt is optimal)\n- **Name**: 14-18pt (16pt recommended)\n- **Section Headings**: 12-14pt\n- **Font Family**: Computer Modern, Latin Modern, Helvetica, Times New Roman\n\n### Margin Specifications\n\n- **Minimum**: 0.5 inches (0.5in) on all sides\n- **Recommended**: 0.5in-0.75in\n- **Never**: \u003c0.5in (content may be cut off)\n\nLaTeX code:\n```latex\n\\usepackage[margin=0.75in]{geometry}\n% or\n\\usepackage[top=0.75in, bottom=0.75in, left=0.5in, right=0.5in]{geometry}\n```\n\n### File Naming Convention\n\n**Format**: `FirstName_LastName_Resume.pdf`\n\n**Examples**:\n- `John_Doe_Resume.pdf` (correct)\n- `Jane_Smith_Resume.pdf` (correct)\n- `resume.pdf` (BAD)\n- `JD_Resume_2026.pdf` (BAD - don't use initials or dates)\n\n### Page Length Guidelines\n\n| Experience Level | Page Count | Rule |\n|------------------|------------|------|\n| 0-5 years | 1 page | Strict |\n| 5-10 years | 1-2 pages | 2 pages if strong justification |\n| 10-15 years | 2 pages | Standard |\n| 15+ years / Executive | 2-3 pages | Leadership focus |\n\n### Bullet Point Rules\n\n1. **Start with Action Verb**: \"Led\", \"Developed\", \"Increased\" (not \"Responsible for\")\n2. **Include Metrics**: Quantify impact with numbers, percentages, dollar amounts\n3. **Length**: 1-2 lines per bullet (never >2 lines)\n4. **Count**: 3-5 bullets per job (most recent jobs get 5, older jobs get 3)\n\n### Date Formats\n\n**Standard**: `Month Year - Month Year` or `MM/YYYY - MM/YYYY`\n\n**Examples**:\n- `January 2023 - Present`\n- `01/2023 - Present`\n- `Jan 2023 - Dec 2025`\n\n**Avoid**:\n- `2023-2025` (too vague)\n- `1/23 - 12/25` (ambiguous)\n\n---\n\n## Common LaTeX ATS Mistakes\n\n### Mistake #1: Two-Column Header with minipage\n\n**Problem**:\n```latex\n\\begin{minipage}[t]{0.5\\textwidth}\nJohn Doe \\\\\nSenior Engineer\n\\end{minipage}%\n\\begin{minipage}[t]{0.5\\textwidth}\n\\raggedleft\[email protected] \\\\\n(555) 123-4567\n\\end{minipage}\n```\n\n**Solution**: Linear layout\n```latex\n\\begin{center}\n{\\LARGE\\bfseries John Doe} \\\\[4pt]\nSenior Software Engineer \\\\[4pt]\[email protected] $|$ (555) 123-4567 $|$ linkedin.com/in/johndoe\n\\end{center}\n```\n\n### Mistake #2: Skills Grid with tabularx\n\n**Problem**:\n```latex\n\\begin{tabularx}{\\textwidth}{X X X}\nPython & React & AWS \\\\\nDocker & PostgreSQL & Git\n\\end{tabularx}\n```\n\n**Solution**: Comma-separated or bulleted list\n```latex\n\\textbf{Languages:} Python, JavaScript, Java, SQL \\\\\n\\textbf{Frameworks:} React, Node.js, Django, Flask \\\\\n\\textbf{Cloud:} AWS (EC2, S3, Lambda), Azure, GCP\n```\n\n### Mistake #3: Profile Photo with includegraphics\n\n**Problem**:\n```latex\n\\includegraphics[width=3cm]{profile.jpg}\n```\n\n**Solution**: Remove entirely. Photos are not ATS-friendly and can introduce bias.\n\n### Mistake #4: Contact Info in fancyhdr\n\n**Problem**:\n```latex\n\\usepackage{fancyhdr}\n\\pagestyle{fancy}\n\\fancyhead[L]{John Doe}\n\\fancyhead[R]{[email protected]}\n```\n\n**Solution**: Put contact info in document body (see Mistake #1 solution)\n\n### Mistake #5: Colored Section Dividers\n\n**Problem**:\n```latex\n\\usepackage{xcolor}\n\\section*{{\\color{blue}Experience}}\n\\textcolor{gray}{\\hrulefill}\n```\n\n**Solution**: Keep it simple\n```latex\n\\section*{Experience}\n```\n\n### Mistake #6: Custom Fonts\n\n**Problem**:\n```latex\n\\usepackage{fontspec}\n\\setmainfont{Montserrat}\n```\n\n**Solution**: Use standard fonts\n```latex\n\\usepackage{lmodern}\n```\n\n### Mistake #7: Unescaped Special Characters\n\n**Problem**: Using `&`, `%`, ` latex-document-skill — Skillopedia , `#` without escaping\n\n**Solution**: Escape them: `\\&`, `\\%`, `\\ latex-document-skill — Skillopedia , `\\#`\n\n---\n\n## Quantified Achievement Patterns\n\n### Formula: Verb + Action + Metric\n\n**Template**: `[Action Verb] + [what you did] + [quantified result/impact]`\n\n### Examples by Category:\n\n#### Leadership\n- \"Led team of 8 engineers to deliver $2M project 3 weeks ahead of schedule\"\n- \"Managed cross-functional team of 12 across 3 time zones, improving delivery velocity by 35%\"\n- \"Mentored 5 junior developers, resulting in 100% promotion rate within 18 months\"\n\n#### Technical Achievement\n- \"Reduced API latency by 40% by implementing Redis caching layer\"\n- \"Optimized database queries, improving page load time from 3.2s to 0.8s (75% reduction)\"\n- \"Architected microservices infrastructure serving 10M+ daily active users\"\n\n#### Business Impact\n- \"Increased revenue by $1.2M annually through conversion rate optimization (15% improvement)\"\n- \"Reduced customer churn by 23% via predictive machine learning model\"\n- \"Cut infrastructure costs by $150K/year by migrating to containerized architecture\"\n\n#### Process Improvement\n- \"Automated deployment pipeline, reducing release time from 4 hours to 15 minutes\"\n- \"Established CI/CD best practices, increasing deployment frequency from weekly to daily\"\n- \"Implemented code review standards, reducing production bugs by 62%\"\n\n#### Scale/Volume\n- \"Built data pipeline processing 5TB daily across 200+ data sources\"\n- \"Designed RESTful API handling 50K requests/second with 99.99% uptime\"\n- \"Migrated 2.5M user accounts to new authentication system with zero downtime\"\n\n### Metrics Checklist\n\nWhen writing bullets, include at least ONE of these:\n- **Percentage**: \"increased by X%\", \"reduced by Y%\"\n- **Dollar Amount**: \"$X revenue\", \"$Y cost savings\"\n- **Time Savings**: \"reduced from X hours to Y minutes\"\n- **Scale**: \"X million users\", \"Y terabytes\"\n- **Team Size**: \"led team of X\"\n- **Frequency**: \"from X per week to Y per day\"\n\n---\n\n## Action Verbs by Category\n\n### Leadership & Management\nChaired, Coordinated, Delegated, Directed, Drove, Executed, Guided, Headed, Led, Managed, Mentored, Orchestrated, Oversaw, Piloted, Spearheaded, Supervised\n\n### Technical & Engineering\nArchitected, Automated, Built, Coded, Compiled, Debugged, Deployed, Designed, Developed, Engineered, Implemented, Integrated, Migrated, Optimized, Programmed, Refactored, Resolved, Scaled\n\n### Analysis & Strategy\nAnalyzed, Assessed, Audited, Calculated, Evaluated, Examined, Forecasted, Identified, Investigated, Measured, Modeled, Projected, Quantified, Researched, Tested, Validated\n\n### Achievement & Results\nAchieved, Accelerated, Exceeded, Generated, Improved, Increased, Maximized, Outperformed, Reduced, Saved, Surpassed, Transformed\n\n### Communication & Collaboration\nCollaborated, Communicated, Coordinated, Presented, Documented, Facilitated, Interfaced, Liaised, Negotiated, Partnered\n\n### Creation & Innovation\nAuthored, Created, Designed, Established, Formulated, Founded, Initiated, Innovated, Introduced, Invented, Launched, Pioneered\n\n### Organization & Process\nConsolidated, Organized, Planned, Prioritized, Restructured, Standardized, Streamlined, Systematized\n\n---\n\n## ATS Testing Checklist\n\nBefore submitting your resume, verify:\n\n- [ ] Single-column layout (no side-by-side sections)\n- [ ] Contact info in document body (not header/footer)\n- [ ] Standard section headings from approved list\n- [ ] No tables used for layout\n- [ ] No images, graphics, or photos\n- [ ] Standard fonts only (Computer Modern, Latin Modern, Helvetica)\n- [ ] Font size 10-12pt for body text\n- [ ] Margins ≥0.5in on all sides\n- [ ] Keywords from job description present\n- [ ] Acronyms spelled out on first use\n- [ ] Every bullet starts with action verb\n- [ ] At least 80% of bullets include metrics\n- [ ] File named `FirstName_LastName_Resume.pdf`\n- [ ] Page count appropriate for experience level\n\n---\n\n**Last Updated**: February 2026\n**Recommended Review**: Before each resume generation or major template update\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":15296,"content_sha256":"91e94e940203a440d867da490fa6609e5b61ded13aa98afd05c55007a3839b81"},{"filename":"references/script-tools.md","content":"# Script & Tool Reference\n\nComplete reference for all automation scripts in the latex-document skill. Load when you need to use PDF utilities, quality checks, or conversion tools.\n\n## PDF Tools\n\n### PDF-to-Images Script\n\n```bash\n# Split PDF and resize for API compatibility\nbash \u003cskill_path>/scripts/pdf_to_images.sh input.pdf ./tmp/pages\n\n# Custom DPI and max dimension\nbash \u003cskill_path>/scripts/pdf_to_images.sh input.pdf ./tmp/pages --dpi 200 --max-dim 2000\n```\n\nAuto-installs `poppler-utils` and `imagemagick`, renders pages as PNG, resizes to fit within API image dimension limits (2000px max).\n\n### PDF Encryption\n\n**IMPORTANT: ALWAYS use the AskUserQuestion tool to ask the user what password they want BEFORE encrypting any PDF. NEVER use a default or auto-generated password. The user must explicitly choose their password.**\n\n```bash\n# Encrypt a PDF with AES-256\nbash \u003cskill_path>/scripts/pdf_encrypt.sh document.pdf --user-password \"\u003cUSER_PASSWORD>\"\n\n# With separate owner password and restrictions\nbash \u003cskill_path>/scripts/pdf_encrypt.sh document.pdf --user-password \"\u003cUSER_PASSWORD>\" --owner-password \"\u003cOWNER_PASSWORD>\" --restrict-print --restrict-modify\n\n# Custom output path\nbash \u003cskill_path>/scripts/pdf_encrypt.sh document.pdf --user-password \"\u003cUSER_PASSWORD>\" --output secure.pdf\n```\n\nWhen the user asks to encrypt, protect, or password-protect a PDF, use this workflow:\n1. Use **AskUserQuestion** to ask: \"What password would you like to use to protect this PDF?\"\n2. Wait for the user's response\n3. Run `pdf_encrypt.sh` with the password they provided\n4. Report success and remind the user to remember their password\n\n### PDF Merge\n\n```bash\n# Merge multiple PDFs into one\nbash \u003cskill_path>/scripts/pdf_merge.sh file1.pdf file2.pdf file3.pdf -o merged.pdf\n```\n\n### PDF Optimize\n\n```bash\n# Compress and linearize a PDF for web delivery or email\nbash \u003cskill_path>/scripts/pdf_optimize.sh document.pdf optimized.pdf\n```\n\n### PDF Page Extraction\n\n```bash\n# Extract pages 1-10 from a PDF\nbash \u003cskill_path>/scripts/pdf_extract_pages.sh input.pdf --pages 1-10\n\n# Extract specific pages with custom output\nbash \u003cskill_path>/scripts/pdf_extract_pages.sh input.pdf --pages 1,3,5-8 --output selected.pdf\n\n# Extract odd or even pages only\nbash \u003cskill_path>/scripts/pdf_extract_pages.sh input.pdf --pages odd --output odd_pages.pdf\n\n# Extract the last 3 pages\nbash \u003cskill_path>/scripts/pdf_extract_pages.sh input.pdf --pages last:3\n```\n\n### PDF Form Operations\n\n```bash\n# Check if PDF has fillable form fields\npython3 \u003cskill_path>/scripts/pdf_check_form.py input.pdf\n\n# Extract form field info to JSON (field IDs, types, pages, rects)\npython3 \u003cskill_path>/scripts/pdf_extract_fields.py input.pdf field_info.json\n\n# Fill fillable form fields (validates field IDs/pages/values before writing)\npython3 \u003cskill_path>/scripts/pdf_fill_form.py input.pdf field_values.json output.pdf\n\n# Fill non-fillable forms with text annotations at bounding box positions\npython3 \u003cskill_path>/scripts/pdf_fill_annotations.py input.pdf fields.json output.pdf\n\n# Validate bounding boxes (check intersections and entry height vs font size)\npython3 \u003cskill_path>/scripts/pdf_validate_boxes.py fields.json\n\n# Create validation image showing bounding boxes overlaid on page image\npython3 \u003cskill_path>/scripts/pdf_validate_boxes.py fields.json \\\n --image page-001.png --output validation.png --page 1\n```\n\n**Workflow for fillable PDFs:** `pdf_check_form.py` -> `pdf_extract_fields.py` -> create `field_values.json` -> `pdf_fill_form.py`\n\n**Workflow for non-fillable PDFs:** `pdf_check_form.py` -> `pdf_to_images.sh` -> create `fields.json` with bounding boxes -> `pdf_validate_boxes.py` (validate + create validation images) -> `pdf_fill_annotations.py`\n\nSee `references/pdf-operations.md` for detailed field format documentation and advanced PDF operations.\n\n## LaTeX Quality Tools\n\n### Lint (Pre-Compilation Check)\n\n```bash\n# Run chktex linter with formatted output\nbash \u003cskill_path>/scripts/latex_lint.sh document.tex\n```\n\n### Word Count\n\n```bash\n# Count words (strips LaTeX commands)\nbash \u003cskill_path>/scripts/latex_wordcount.sh document.tex\n```\n\n### Document Analysis\n\n```bash\n# Get statistics: word count, figures, tables, equations, citations, sections\nbash \u003cskill_path>/scripts/latex_analyze.sh document.tex\n```\n\n### Package Availability Check\n\n```bash\n# Pre-flight check: verify all \\usepackage packages are installed\nbash \u003cskill_path>/scripts/latex_package_check.sh document.tex\n\n# With auto-install of missing packages\nbash \u003cskill_path>/scripts/latex_package_check.sh document.tex --install\n\n# Verbose output showing each package check\nbash \u003cskill_path>/scripts/latex_package_check.sh document.tex --verbose\n```\n\n### Citation Analysis\n\n```bash\n# Extract all \\cite{} keys from a .tex file\nbash \u003cskill_path>/scripts/latex_citation_extract.sh document.tex\n\n# Cross-reference citations against a .bib file (auto-detects from \\bibliography{})\nbash \u003cskill_path>/scripts/latex_citation_extract.sh document.tex --check\n\n# Specify .bib file explicitly, output as JSON\nbash \u003cskill_path>/scripts/latex_citation_extract.sh document.tex --bib refs.bib --format json\n```\n\n## Compilation Tools\n\n### Auto-Fix Mode\n\n```bash\n# Compile with automatic fixes for common issues\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --auto-fix\n\n# Auto-fix + preview\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --auto-fix --preview --preview-dir ./outputs\n```\n\n`--auto-fix` creates a temporary copy and applies:\n- **Stage 1:** Adds `[htbp]` placement to naked `\\begin{figure}` and `\\begin{table}` (the #1 LaTeX complaint)\n- **Stage 2:** If overfull hbox warnings are detected, injects `\\usepackage{microtype}` and recompiles\n\nThe script also parses the `.log` file and translates cryptic LaTeX errors into actionable suggestions (missing ` latex-document-skill — Skillopedia , undefined commands, missing packages, unbalanced braces, undefined citations).\n\n## Bibliography Tools\n\n### Fetch BibTeX\n\n```bash\n# Auto-download BibTeX from a DOI\nbash \u003cskill_path>/scripts/fetch_bibtex.sh 10.1145/359576.359579\n\n# Append to an existing .bib file\nbash \u003cskill_path>/scripts/fetch_bibtex.sh 10.1145/359576.359579 >> references.bib\n```\n\n## Diagram Tools\n\n### Diagram Conversion Scripts\n\n```bash\n# Convert Graphviz .dot to PDF\nbash \u003cskill_path>/scripts/graphviz_to_pdf.sh diagram.dot output.pdf\n\n# Convert PlantUML .puml to PDF\nbash \u003cskill_path>/scripts/plantuml_to_pdf.sh diagram.puml output.pdf\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":6436,"content_sha256":"1cee405c162f961ae861e69aea1fcce56b9c48906bdb694de25ff68256a3b444"},{"filename":"references/tables-and-images.md","content":"# Tables and Images in LaTeX\n\n## Table of Contents\n- [Tables](#tables)\n - [Basic Table](#basic-table)\n - [Full-Width Table with tabularx](#full-width-table-with-tabularx)\n - [Colored Rows](#colored-rows)\n - [Multi-row and Multi-column](#multi-row-and-multi-column)\n - [Borderless Modern Table](#borderless-modern-table)\n - [Long Tables](#long-tables)\n- [Advanced Tables](#advanced-tables)\n - [Alternating Row Colors](#alternating-row-colors)\n - [Complex Multi-row/Multi-column](#complex-multi-rowmulti-column)\n - [Conditional Cell Formatting](#conditional-cell-formatting)\n - [Tables from CSV Data](#tables-from-csv-data)\n - [Rotated Column Headers](#rotated-column-headers)\n - [Adjustbox for Table Sizing](#adjustbox-for-table-sizing)\n - [nicematrix (Modern Alternative)](#nicematrix-modern-alternative)\n - [Long Table with Continuation Headers](#long-table-with-continuation-headers)\n - [Landscape Tables](#landscape-tables)\n- [Images](#images)\n - [Including External Images](#including-external-images)\n - [TikZ Drawings](#tikz-drawings)\n - [Circular Clipped Photo](#circular-clipped-photo)\n - [Side-by-Side Images](#side-by-side-images)\n - [Text Wrapping Around Images](#text-wrapping-around-images)\n- [Advanced Images](#advanced-images)\n - [Subfigures (Multiple Images with Sub-captions)](#subfigures-multiple-images-with-sub-captions)\n - [Image Grid (3x2, 2x2, etc.)](#image-grid-3x2-2x2-etc)\n - [Full-Page Images](#full-page-images)\n - [Image Borders and Shadows](#image-borders-and-shadows)\n - [Overlaying Text on Images](#overlaying-text-on-images)\n- [Troubleshooting Tables & Images](#troubleshooting-tables--images)\n - [Common Table Errors](#common-table-errors)\n - [Common Image Errors](#common-image-errors)\n\n---\n\n## Tables\n\nRequired packages:\n```latex\n\\usepackage{tabularx} % Auto-width columns\n\\usepackage{array} % Column customization\n\\usepackage{colortbl} % Row/cell colors\n\\usepackage{multirow} % Span multiple rows\n\\usepackage{booktabs} % Professional rules (\\toprule, \\midrule, \\bottomrule)\n\\usepackage{longtable} % Tables spanning pages\n```\n\n### Basic Table\n\n```latex\n\\begin{tabular}{|l|c|r|}\n\\hline\n\\textbf{Left} & \\textbf{Center} & \\textbf{Right} \\\\\n\\hline\nA & B & C \\\\\n\\hline\n\\end{tabular}\n```\n\nColumn types: `l` left, `c` center, `r` right, `p{3cm}` fixed-width paragraph.\n\n### Full-Width Table with tabularx\n\n```latex\n\\begin{tabularx}{\\textwidth}{|>{\\bfseries}l|X|c|}\n\\hline\n\\textbf{Category} & \\textbf{Description} & \\textbf{Level} \\\\\n\\hline\nLanguages & Python, Java, Go, SQL & Expert \\\\\n\\hline\nFrontend & React, Next.js, Vue.js & Advanced \\\\\n\\hline\n\\end{tabularx}\n```\n\n`X` columns auto-expand to fill remaining width. Use `>{\\bfseries}l` to auto-bold a column.\n\n### Colored Rows\n\nRequires `\\usepackage{colortbl}` and `\\usepackage{xcolor}`.\n\n```latex\n\\definecolor{headerblue}{RGB}{200, 220, 255}\n\\definecolor{lightgray}{RGB}{240, 240, 240}\n\n\\begin{tabularx}{\\textwidth}{|l|X|c|}\n\\hline\n\\rowcolor{headerblue}\n\\textbf{Metric} & \\textbf{Value} & \\textbf{Change} \\\\\n\\hline\n\\rowcolor{lightgray}\nRevenue & \\$1.2M & \\textcolor{green}{\\textbf{+15\\%}} \\\\\n\\hline\nCosts & \\$800K & \\textcolor{red}{\\textbf{+5\\%}} \\\\\n\\hline\n\\end{tabularx}\n```\n\n### Multi-row and Multi-column\n\nRequires `\\usepackage{multirow}`.\n\n```latex\n\\begin{tabular}{|l|c|c|c|}\n\\hline\n\\multirow{2}{*}{\\textbf{Name}} & \\multicolumn{3}{c|}{\\textbf{Scores}} \\\\\n\\cline{2-4}\n & Math & Science & English \\\\\n\\hline\nAlice & 95 & 88 & 92 \\\\\n\\hline\n\\end{tabular}\n```\n\n### Borderless Modern Table\n\nUsing `booktabs` for professional look:\n\n```latex\n\\begin{tabular}{lrr}\n\\toprule\n\\textbf{Project} & \\textbf{Users} & \\textbf{Uptime} \\\\\n\\midrule\nPlatform A & 2M+ & 99.9\\% \\\\\nPlatform B & 50K & 99.5\\% \\\\\nPlatform C & 5K & 99.8\\% \\\\\n\\bottomrule\n\\end{tabular}\n```\n\n### Long Tables\n\nFor tables that span pages, use `longtable`:\n\n```latex\n\\usepackage{longtable}\n% ...\n\\begin{longtable}{|l|p{8cm}|r|}\n\\hline\n\\textbf{ID} & \\textbf{Description} & \\textbf{Amount} \\\\\n\\hline\n\\endfirsthead\n\\hline\n\\textbf{ID} & \\textbf{Description} & \\textbf{Amount} \\\\\n\\hline\n\\endhead\n\\hline\n\\endfoot\n001 & First item & \\$100 \\\\\n\\hline\n% ... many rows ...\n\\end{longtable}\n```\n\n---\n\n## Images\n\nRequired packages:\n```latex\n\\usepackage{graphicx} % \\includegraphics\n\\usepackage{tikz} % Programmatic drawings\n\\usepackage{wrapfig} % Text wrapping around images\n\\usepackage{subcaption} % Subfigures\n```\n\n### Including External Images\n\n```latex\n% Basic inclusion\n\\includegraphics[width=0.5\\textwidth]{photo.png}\n\n% With figure environment (adds caption + label)\n\\begin{figure}[htbp]\n \\centering\n \\includegraphics[width=0.8\\textwidth]{chart.png}\n \\caption{Sales data for Q1 2025}\n \\label{fig:sales}\n\\end{figure}\n\n% Fixed dimensions\n\\includegraphics[width=5cm, height=3cm, keepaspectratio]{logo.png}\n```\n\nSupported formats: PNG, JPG, PDF (vector). Use `keepaspectratio` to prevent distortion.\n\n### TikZ Drawings\n\nPlaceholder shapes when no image file is available:\n\n```latex\n% Simple person icon (for profile photo placeholder)\n\\begin{tikzpicture}\n \\draw[fill=gray!20] (0,0) circle (1.2cm);\n \\draw[fill=white] (0,-0.2) circle (0.4cm);\n \\draw[fill=white] (0,0.5) circle (0.5cm);\n\\end{tikzpicture}\n\n% Bar chart\n\\begin{tikzpicture}\n \\fill[blue!60] (0,0) rectangle (1,3);\n \\fill[blue!40] (1.5,0) rectangle (2.5,2);\n \\fill[blue!20] (3,0) rectangle (4,4);\n \\node at (0.5,-0.3) {Q1};\n \\node at (2,-0.3) {Q2};\n \\node at (3.5,-0.3) {Q3};\n\\end{tikzpicture}\n\n% Star rating\n\\begin{tikzpicture}\n \\foreach \\i in {1,...,5} {\n \\fill[yellow!80!orange] (\\i*0.5,0) -- ++(0.18,0.35) -- ++(0.35,0)\n -- ++(-0.25,0.22) -- ++(0.1,0.38) -- ++(-0.28,-0.25)\n -- ++(-0.28,0.25) -- ++(0.1,-0.38) -- ++(-0.25,-0.22)\n -- ++(0.35,0) -- cycle;\n }\n\\end{tikzpicture}\n```\n\n### Circular Clipped Photo\n\n```latex\n\\usepackage{tikz}\n% ...\n\\begin{tikzpicture}\n \\clip (0,0) circle (1.5cm);\n \\node at (0,0) {\\includegraphics[width=3cm]{photo.jpg}};\n\\end{tikzpicture}\n```\n\n### Side-by-Side Images\n\n```latex\n\\begin{figure}[htbp]\n \\centering\n \\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{image1.png}\n \\caption{First image}\n \\end{minipage}\n \\hfill\n \\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{image2.png}\n \\caption{Second image}\n \\end{minipage}\n\\end{figure}\n```\n\n### Text Wrapping Around Images\n\n```latex\n\\usepackage{wrapfig}\n% ...\n\\begin{wrapfigure}{r}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=0.28\\textwidth]{photo.png}\n \\caption{Profile}\n\\end{wrapfigure}\nThe text here flows around the image on the right side.\n```\n\nPosition options: `r` right, `l` left, `R`/`L` for float versions.\n\n---\n\n## Advanced Tables\n\n### Alternating Row Colors\n\nAutomatically color alternating rows for improved readability:\n\n```latex\n\\usepackage[table]{xcolor}\n\n% Set alternating row colors (starting from row 2)\n\\rowcolors{2}{gray!10}{white}\n\n\\begin{tabular}{lcc}\n\\toprule\n\\textbf{Product} & \\textbf{Sales} & \\textbf{Growth} \\\\\n\\midrule\nWidget A & \\$50K & +12\\% \\\\\nWidget B & \\$35K & -3\\% \\\\\nWidget C & \\$72K & +25\\% \\\\\nWidget D & \\$41K & +8\\% \\\\\n\\bottomrule\n\\end{tabular}\n```\n\nThe `\\rowcolors{starting_row}{odd_color}{even_color}` command applies colors automatically. Use `\\hiderowcolors` and `\\showrowcolors` to temporarily disable/enable.\n\n### Complex Multi-row/Multi-column\n\nA realistic example combining both `\\multirow` and `\\multicolumn` with nested spanning:\n\n```latex\n\\usepackage{multirow}\n\\usepackage{booktabs}\n\n\\begin{tabular}{|l|c|c|c|c|}\n\\hline\n\\multirow{2}{*}{\\textbf{Region}} & \\multicolumn{2}{c|}{\\textbf{Q1}} & \\multicolumn{2}{c|}{\\textbf{Q2}} \\\\\n\\cline{2-5}\n & Revenue & Units & Revenue & Units \\\\\n\\hline\n\\multirow{2}{*}{North} & \\$120K & 1,200 & \\$135K & 1,350 \\\\\n & \\multicolumn{4}{c|}{(5\\% growth in units)} \\\\\n\\hline\n\\multirow{2}{*}{South} & \\$95K & 950 & \\$110K & 1,100 \\\\\n & \\multicolumn{4}{c|}{(15\\% growth in units)} \\\\\n\\hline\n\\textbf{Total} & \\multicolumn{2}{c|}{\\$215K} & \\multicolumn{2}{c|}{\\$245K} \\\\\n\\hline\n\\end{tabular}\n```\n\nTips:\n- Use `\\cline{2-5}` for partial horizontal lines\n- Combine `\\multirow` with `\\multicolumn` by nesting them carefully\n- Leave empty cells in subsequent rows when using `\\multirow`\n\n### Conditional Cell Formatting\n\nColor individual cells based on their values:\n\n```latex\n\\usepackage[table]{xcolor}\n\n\\begin{tabular}{|l|c|c|}\n\\hline\n\\textbf{Metric} & \\textbf{Target} & \\textbf{Actual} \\\\\n\\hline\nRevenue & \\$100K & \\cellcolor{green!30}\\$115K \\\\\n\\hline\nCosts & \\$80K & \\cellcolor{red!30}\\$95K \\\\\n\\hline\nMargin & 20\\% & \\cellcolor{yellow!30}17\\% \\\\\n\\hline\n\\end{tabular}\n```\n\nAdvanced: Define custom commands for threshold-based coloring:\n\n```latex\n\\newcommand{\\goodcell}[1]{\\cellcolor{green!30}#1}\n\\newcommand{\\badcell}[1]{\\cellcolor{red!30}#1}\n\\newcommand{\\warncell}[1]{\\cellcolor{yellow!30}#1}\n\n\\begin{tabular}{lc}\n\\toprule\nTest & Status \\\\\n\\midrule\nUnit Tests & \\goodcell{Passed} \\\\\nIntegration & \\badcell{Failed} \\\\\nPerformance & \\warncell{Slow} \\\\\n\\bottomrule\n\\end{tabular}\n```\n\n### Tables from CSV Data\n\nAutomatically generate tables from CSV files:\n\n```latex\n\\usepackage{csvsimple}\n\n% Simple auto-table\n\\csvautotabular{data.csv}\n\n% Custom formatting\n\\begin{table}[htbp]\n\\centering\n\\begin{tabular}{lrr}\n\\toprule\n\\bfseries Name & \\bfseries Age & \\bfseries Score \\\\\n\\midrule\n\\csvreader[head to column names]{data.csv}{}\n{\\name & \\age & \\score \\\\}\n\\bottomrule\n\\end{tabular}\n\\caption{Data imported from CSV}\n\\end{table}\n```\n\nExample `data.csv`:\n```\nname,age,score\nAlice,28,95\nBob,32,87\nCarol,25,92\n```\n\nFiltering rows:\n```latex\n\\csvreader[filter expr={\\value{score}>90}]{data.csv}{name=\\name,score=\\score}\n{\\name & \\score \\\\}\n```\n\n### Rotated Column Headers\n\nUseful for tables with many narrow columns:\n\n```latex\n\\usepackage{rotating}\n\\usepackage{booktabs}\n\\usepackage{array}\n\n\\begin{tabular}{l*{5}{c}}\n\\toprule\n\\textbf{Team} & \\rotatebox{90}{Velocity} & \\rotatebox{90}{Quality} & \\rotatebox{90}{Coverage} & \\rotatebox{90}{Bugs} & \\rotatebox{90}{Uptime} \\\\\n\\midrule\nAlpha & 85 & 92 & 88 & 3 & 99.9\\% \\\\\nBeta & 78 & 87 & 91 & 5 & 99.7\\% \\\\\nGamma & 92 & 95 & 94 & 1 & 99.99\\% \\\\\n\\bottomrule\n\\end{tabular}\n```\n\nAlternative with `\\rothead` custom command:\n```latex\n\\newcommand{\\rothead}[1]{\\rotatebox{90}{\\textbf{#1}}}\n\n\\begin{tabular}{l*{5}{c}}\n\\toprule\n\\textbf{Team} & \\rothead{Velocity} & \\rothead{Quality} & \\rothead{Coverage} & \\rothead{Bugs} & \\rothead{Uptime} \\\\\n\\midrule\n% ... data rows ...\n\\bottomrule\n\\end{tabular}\n```\n\n### Adjustbox for Table Sizing\n\nAutomatically scale tables to fit page width while maintaining aspect ratio:\n\n```latex\n\\usepackage{adjustbox}\n\n% Scale to fit text width\n\\begin{adjustbox}{max width=\\textwidth}\n\\begin{tabular}{lccccccccc}\n\\toprule\n\\textbf{ID} & \\textbf{Col1} & \\textbf{Col2} & \\textbf{Col3} & \\textbf{Col4} & \\textbf{Col5} & \\textbf{Col6} & \\textbf{Col7} & \\textbf{Col8} & \\textbf{Col9} \\\\\n\\midrule\n001 & A & B & C & D & E & F & G & H & I \\\\\n002 & J & K & L & M & N & O & P & Q & R \\\\\n\\bottomrule\n\\end{tabular}\n\\end{adjustbox}\n\n% Scale to specific width\n\\begin{adjustbox}{width=0.9\\textwidth}\n\\begin{tabular}{...}\n% ...\n\\end{tabular}\n\\end{adjustbox}\n\n% Center and scale\n\\begin{adjustbox}{center, max width=\\textwidth}\n\\begin{tabular}{...}\n% ...\n\\end{tabular}\n\\end{adjustbox}\n```\n\nAdvantages over `\\resizebox`:\n- Maintains better font scaling\n- More flexible options (max width, max height, etc.)\n- Can center automatically\n\n### nicematrix (Modern Alternative)\n\nA modern package offering enhanced table features:\n\n```latex\n\\usepackage{nicematrix}\n\n% Basic usage with automatic rules\n\\begin{NiceTabular}{lcc}[hvlines, rules/color=gray]\n\\RowStyle{\\bfseries}\nHeader 1 & Header 2 & Header 3 \\\\\nA & B & C \\\\\nD & E & F \\\\\n\\end{NiceTabular}\n\n% With custom styling\n\\begin{NiceTabular}{lcc}[\n hvlines,\n cell-space-limits=3pt,\n code-before = \\rowcolor{blue!15}{1}\n]\n\\textbf{Product} & \\textbf{Price} & \\textbf{Stock} \\\\\nWidget & \\$29.99 & 150 \\\\\nGadget & \\$49.99 & 87 \\\\\nTool & \\$19.99 & 200 \\\\\n\\end{NiceTabular}\n```\n\nAdvanced features:\n```latex\n% Diagonal lines in cells\n\\begin{NiceTabular}{cc}[hvlines]\n\\diagbox{Row}{Col} & Column 1 \\\\\nRow 1 & Data \\\\\n\\end{NiceTabular}\n\n% Custom block styling\n\\begin{NiceTabular}{cccc}[hvlines]\n\\Block{1-4}{\\textbf{Quarterly Report}} \\\\\nQ1 & Q2 & Q3 & Q4 \\\\\n\\$100K & \\$120K & \\$115K & \\$140K \\\\\n\\end{NiceTabular}\n```\n\n### Long Table with Continuation Headers\n\nComplete example with headers and footers that repeat across pages:\n\n```latex\n\\usepackage{longtable}\n\\usepackage{booktabs}\n\n\\begin{longtable}{llrr}\n% Header for first page\n\\toprule\n\\textbf{ID} & \\textbf{Description} & \\textbf{Quantity} & \\textbf{Price} \\\\\n\\midrule\n\\endfirsthead\n\n% Header for continuation pages\n\\multicolumn{4}{c}{\\tablename\\ \\thetable\\ -- \\textit{Continued from previous page}} \\\\\n\\toprule\n\\textbf{ID} & \\textbf{Description} & \\textbf{Quantity} & \\textbf{Price} \\\\\n\\midrule\n\\endhead\n\n% Footer for all pages except last\n\\midrule\n\\multicolumn{4}{r}{\\textit{Continued on next page}} \\\\\n\\endfoot\n\n% Footer for last page\n\\bottomrule\n\\multicolumn{3}{r}{\\textbf{Total:}} & \\textbf{\\$15,750.00} \\\\\n\\endlastfoot\n\n% Data rows\n001 & Premium Widget Set & 50 & \\$1,250.00 \\\\\n002 & Standard Gadget & 100 & \\$2,500.00 \\\\\n003 & Deluxe Tool Kit & 25 & \\$1,875.00 \\\\\n004 & Basic Component & 200 & \\$1,000.00 \\\\\n005 & Advanced Module & 30 & \\$2,400.00 \\\\\n% ... many more rows ...\n050 & Final Item & 75 & \\$1,875.00 \\\\\n\\end{longtable}\n```\n\nKey commands:\n- `\\endfirsthead` - Header for first page only\n- `\\endhead` - Header for subsequent pages\n- `\\endfoot` - Footer for all pages except last\n- `\\endlastfoot` - Footer for final page only\n\n### Landscape Tables\n\nFor very wide tables, use landscape orientation:\n\n```latex\n\\usepackage{pdflscape}\n\\usepackage{longtable}\n\n\\begin{landscape}\n\\begin{table}[htbp]\n\\centering\n\\begin{tabular}{lcccccccccc}\n\\toprule\n\\textbf{Project} & \\textbf{Jan} & \\textbf{Feb} & \\textbf{Mar} & \\textbf{Apr} & \\textbf{May} & \\textbf{Jun} & \\textbf{Jul} & \\textbf{Aug} & \\textbf{Sep} & \\textbf{Oct} \\\\\n\\midrule\nAlpha & 85\\% & 87\\% & 92\\% & 94\\% & 95\\% & 97\\% & 98\\% & 98\\% & 99\\% & 99\\% \\\\\nBeta & 72\\% & 75\\% & 78\\% & 82\\% & 85\\% & 88\\% & 91\\% & 93\\% & 95\\% & 96\\% \\\\\nGamma & 91\\% & 92\\% & 93\\% & 94\\% & 95\\% & 96\\% & 97\\% & 98\\% & 99\\% & 99\\% \\\\\n\\bottomrule\n\\end{tabular}\n\\caption{Monthly project completion rates}\n\\end{table}\n\\end{landscape}\n\n% For multi-page landscape tables, combine with longtable:\n\\begin{landscape}\n\\begin{longtable}{lcccccccccc}\n% ... longtable structure ...\n\\end{longtable}\n\\end{landscape}\n```\n\nAlternative using `rotating` package:\n```latex\n\\usepackage{rotating}\n\n\\begin{sidewaystable}\n\\centering\n\\begin{tabular}{...}\n% ... table content ...\n\\end{tabular}\n\\caption{Wide table in landscape}\n\\end{sidewaystable}\n```\n\n---\n\n## Advanced Images\n\n### Subfigures (Multiple Images with Sub-captions)\n\nDisplay multiple related images with individual sub-captions and an overall caption:\n\n```latex\n\\usepackage{subcaption}\n\\usepackage{graphicx}\n\n\\begin{figure}[htbp]\n\\centering\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{chart1.png}\n \\caption{Revenue trends}\n \\label{fig:revenue}\n\\end{subfigure}\n\\hfill\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{chart2.png}\n \\caption{Cost breakdown}\n \\label{fig:costs}\n\\end{subfigure}\n\\caption{Q1 2025 Financial Analysis}\n\\label{fig:financial}\n\\end{figure}\n\n% Reference with: Figure \\ref{fig:financial} shows...,\n% specifically \\ref{fig:revenue} indicates...\n```\n\nVertical layout:\n```latex\n\\begin{figure}[htbp]\n\\centering\n\\begin{subfigure}{\\textwidth}\n \\centering\n \\includegraphics[width=0.6\\textwidth]{top.png}\n \\caption{Overview}\n\\end{subfigure}\n\n\\vspace{1em}\n\n\\begin{subfigure}{\\textwidth}\n \\centering\n \\includegraphics[width=0.6\\textwidth]{bottom.png}\n \\caption{Detailed view}\n\\end{subfigure}\n\\caption{System architecture}\n\\end{figure}\n```\n\nGrid of four subfigures:\n```latex\n\\begin{figure}[htbp]\n\\centering\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img1.png}\n \\caption{First}\n\\end{subfigure}\n\\hfill\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img2.png}\n \\caption{Second}\n\\end{subfigure}\n\n\\vspace{1em}\n\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img3.png}\n \\caption{Third}\n\\end{subfigure}\n\\hfill\n\\begin{subfigure}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img4.png}\n \\caption{Fourth}\n\\end{subfigure}\n\\caption{Comparison of four approaches}\n\\end{figure}\n```\n\n### Image Grid (3x2, 2x2, etc.)\n\nCreate aligned grids of images using minipage:\n\n```latex\n% 2x2 grid without individual captions\n\\begin{figure}[htbp]\n\\centering\n\\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img1.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img2.png}\n\\end{minipage}\n\n\\vspace{0.5cm}\n\n\\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img3.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.45\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{img4.png}\n\\end{minipage}\n\\caption{Image grid 2x2}\n\\end{figure}\n\n% 3x2 grid\n\\begin{figure}[htbp]\n\\centering\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{a1.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{a2.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{a3.png}\n\\end{minipage}\n\n\\vspace{0.5cm}\n\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{b1.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{b2.png}\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{b3.png}\n\\end{minipage}\n\\caption{Image grid 3x2}\n\\end{figure}\n```\n\nWith labels under each image:\n```latex\n\\begin{figure}[htbp]\n\\centering\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{phase1.png}\n \\small Phase 1: Planning\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{phase2.png}\n \\small Phase 2: Development\n\\end{minipage}\n\\hfill\n\\begin{minipage}{0.3\\textwidth}\n \\centering\n \\includegraphics[width=\\textwidth]{phase3.png}\n \\small Phase 3: Deployment\n\\end{minipage}\n\\caption{Project phases}\n\\end{figure}\n```\n\n### Full-Page Images\n\nDedicate an entire page to a large figure:\n\n```latex\n% Dedicated page for figure\n\\begin{figure}[p] % p = dedicated page\n\\centering\n\\includegraphics[width=\\textwidth,height=0.9\\textheight,keepaspectratio]{architecture.pdf}\n\\caption{Complete system architecture diagram}\n\\label{fig:fullpage}\n\\end{figure}\n\n% Full page without margins\n\\begin{figure}[p]\n\\centering\n\\includegraphics[width=\\paperwidth,height=\\paperheight,keepaspectratio]{poster.png}\n\\end{figure}\n\n% Landscape full page\n\\usepackage{pdflscape}\n\\begin{landscape}\n\\begin{figure}[p]\n\\centering\n\\includegraphics[width=\\textwidth,height=\\textheight,keepaspectratio]{wide_chart.pdf}\n\\caption{Full landscape figure}\n\\end{figure}\n\\end{landscape}\n```\n\nFor true full-bleed images (no margins):\n```latex\n\\usepackage{eso-pic}\n\n\\AddToShipoutPictureBG*{%\n \\AtPageLowerLeft{%\n \\includegraphics[width=\\paperwidth,height=\\paperheight]{background.jpg}%\n }%\n}\n```\n\n### Image Borders and Shadows\n\nUse `tcolorbox` for professional framing:\n\n```latex\n\\usepackage{tcolorbox}\n\\usepackage{graphicx}\n\n% Simple border\n\\begin{tcolorbox}[colback=white,colframe=black,boxrule=1pt]\n\\includegraphics[width=\\textwidth]{photo.png}\n\\end{tcolorbox}\n\n% With shadow\n\\begin{tcolorbox}[\n enhanced,\n drop shadow,\n colback=white,\n colframe=gray!50,\n boxrule=0.5pt\n]\n\\includegraphics[width=\\textwidth]{screenshot.png}\n\\end{tcolorbox}\n\n% Rounded corners with caption\n\\begin{tcolorbox}[\n enhanced,\n drop shadow,\n colback=white,\n colframe=blue!50,\n arc=3mm,\n boxrule=1pt,\n title=Figure: Application Interface\n]\n\\centering\n\\includegraphics[width=0.9\\textwidth]{ui.png}\n\\end{tcolorbox}\n```\n\nUsing `fancybox`:\n```latex\n\\usepackage{fancybox}\n\n\\begin{figure}[htbp]\n\\centering\n\\shadowbox{\\includegraphics[width=0.7\\textwidth]{image.png}}\n\\caption{Image with shadow}\n\\end{figure}\n\n\\begin{figure}[htbp]\n\\centering\n\\doublebox{\\includegraphics[width=0.7\\textwidth]{image.png}}\n\\caption{Image with double border}\n\\end{figure}\n\n\\begin{figure}[htbp]\n\\centering\n\\ovalbox{\\includegraphics[width=0.7\\textwidth]{image.png}}\n\\caption{Image with rounded border}\n\\end{figure}\n```\n\n### Overlaying Text on Images\n\nUse TikZ to place text over images:\n\n```latex\n\\usepackage{tikz}\n\n% Basic text overlay\n\\begin{figure}[htbp]\n\\centering\n\\begin{tikzpicture}\n\\node[anchor=south west,inner sep=0] (image) at (0,0) {\n \\includegraphics[width=0.8\\textwidth]{background.png}\n};\n\\node[white,font=\\Large\\bfseries] at (image.center) {Overlay Text};\n\\end{tikzpicture}\n\\caption{Image with centered text}\n\\end{figure}\n\n% Multiple text elements with positioning\n\\begin{tikzpicture}\n\\node[anchor=south west,inner sep=0] (image) at (0,0) {\n \\includegraphics[width=\\textwidth]{dashboard.png}\n};\n\\node[white,font=\\huge\\bfseries,drop shadow] at (4,3) {Dashboard 2025};\n\\node[yellow,font=\\Large] at (8,1) {Revenue: \\$2.5M};\n\\node[green,font=\\small] at (2,5) {+15\\% Growth};\n\\end{tikzpicture}\n\n% Text box with background\n\\begin{tikzpicture}\n\\node[anchor=south west,inner sep=0] at (0,0) {\n \\includegraphics[width=\\textwidth]{photo.jpg}\n};\n\\node[\n fill=black,\n fill opacity=0.7,\n text=white,\n text opacity=1,\n font=\\Large\\bfseries,\n rounded corners,\n inner sep=10pt\n] at (5,2) {Important Notice};\n\\end{tikzpicture}\n```\n\nAdvanced positioning:\n```latex\n\\begin{tikzpicture}\n\\node[anchor=south west,inner sep=0] (img) at (0,0) {\n \\includegraphics[width=\\textwidth]{chart.png}\n};\n% Top-left corner\n\\node[anchor=north west,fill=white,opacity=0.9,inner sep=5pt]\n at (img.north west) {\\textbf{Q1 Results}};\n% Bottom-right corner\n\\node[anchor=south east,fill=blue!20,inner sep=5pt]\n at (img.south east) {\\small Source: Internal Data};\n\\end{tikzpicture}\n```\n\n---\n\n## Troubleshooting Tables & Images\n\n### Common Table Errors\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| \"Extra alignment tab has been changed to \\\\cr\" | Too many `&` in a row | Count columns in preamble vs. `&` in rows |\n| \"Missing \\\\endgroup inserted\" | Unmatched braces in cell | Check `{` and `}` balance in cells |\n| Table overflows right margin | Too many/wide columns | Use `tabularx`, `adjustbox`, or reduce column widths |\n| \"Misplaced \\\\noalign\" | `\\hline` placement error | Ensure `\\\\` before `\\hline`: `\\\\\\\\hline` |\n| \"Illegal pream-token\" | Invalid column specifier | Check for typos in `\\begin{tabular}{...}` |\n| \"Extra }, or forgotten \\\\endgroup\" | Mismatched braces | Verify nested `\\multirow` or `\\multicolumn` braces |\n| Vertical alignment issues | Cell content too tall | Use `\\arraystretch` or `p{}` columns |\n| \"Undefined control sequence \\\\toprule\" | Missing booktabs | Add `\\usepackage{booktabs}` |\n| Colored rows not working | Missing xcolor package | Add `\\usepackage[table]{xcolor}` |\n| `\\multirow` spanning incorrect rows | Wrong row count | Check the `{n}` parameter in `\\multirow{n}{*}{...}` |\n\nCommon fixes:\n```latex\n% Increase row height globally\n\\renewcommand{\\arraystretch}{1.5}\n\n% Fix column width overflow\n\\usepackage{tabularx}\n\\begin{tabularx}{\\textwidth}{lXc} % X expands to fill\n\n% Center table horizontally\n\\begin{center}\n\\begin{tabular}{...}\n...\n\\end{tabular}\n\\end{center}\n\n% Or use table environment\n\\begin{table}[htbp]\n\\centering\n\\begin{tabular}{...}\n...\n\\end{tabular}\n\\end{table}\n```\n\n### Common Image Errors\n\n| Error | Cause | Fix |\n|-------|-------|-----|\n| \"File `image.png' not found\" | Wrong path or missing file | Use path relative to `.tex` file location |\n| \"Cannot determine size of graphic\" | Unsupported format or no BoundingBox | Convert to PNG/JPG/PDF; use `pdflatex` not `latex` |\n| \"Dimension too large\" | Image resolution too high | Scale with `width=` or `scale=` option |\n| Image appears in wrong location | Float placement | Use `[H]` (requires `\\usepackage{float}`) or `[!htbp]` |\n| \"Unknown graphics extension\" | Missing graphicx package | Add `\\usepackage{graphicx}` |\n| Image quality is poor | Scaled bitmap too much | Use vector format (PDF/SVG) or higher resolution |\n| \"Undefined control sequence \\\\includegraphics\" | Missing graphicx | Add `\\usepackage{graphicx}` |\n| Image overlaps text | No spacing | Add `\\vspace{1em}` before/after or use `figure` environment |\n| Caption not appearing | Outside figure environment | Wrap in `\\begin{figure}...\\end{figure}` |\n| \"Option clash for package graphicx\" | Loaded multiple times with different options | Load once in preamble with all options |\n\nCommon fixes:\n```latex\n% Force image at exact location\n\\usepackage{float}\n\\begin{figure}[H] % H = \"Here, definitely\"\n\\centering\n\\includegraphics[width=0.8\\textwidth]{image.png}\n\\end{figure}\n\n% Constrain image dimensions\n\\includegraphics[width=0.8\\textwidth,height=0.5\\textheight,keepaspectratio]{large.jpg}\n\n% Specify image directory\n\\graphicspath{{./images/}{./figures/}}\n\\includegraphics{photo.png} % searches in specified directories\n\n% Fix path issues in subdirectories\n% If .tex is in project/docs/ and image in project/images/\n\\includegraphics{../images/photo.png}\n\n% Supported formats check\n% PDF/JPG/PNG work with pdflatex\n% EPS works with latex (not pdflatex)\n% Convert EPS to PDF: epstopdf image.eps\n```\n\nDebugging image paths:\n```latex\n% Show image search paths\n\\typeout{\\the\\graphicspath}\n\n% Verify file existence with draft mode\n\\usepackage[draft]{graphicx} % Shows boxes instead of images\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":25912,"content_sha256":"0055de4f1528af36e7901fcf26225a0da2e21944ead816f25a00decbbc7eb253"},{"filename":"references/visual-packages.md","content":"# Advanced Visual & Diagram Packages Reference\n\nThis guide covers 24 specialized TikZ and visualization packages that are **already installed** and ready to use in the TeX Live distribution. No additional installation required—just `\\usepackage{...}` and start creating.\n\n## Table of Contents\n- [Mathematics & Computer Science](#mathematics--computer-science)\n- [Physics & Engineering](#physics--engineering)\n- [Chemistry](#chemistry)\n- [Data Visualization](#data-visualization)\n- [Network & Graph Theory](#network--graph-theory)\n- [Business & General](#business--general)\n- [Music & Games](#music--games)\n- [Scientific Computing](#scientific-computing)\n- [Quick Reference Table](#quick-reference-table)\n\n---\n\n## Mathematics & Computer Science\n\n### tikz-cd (Commutative Diagrams)\n\n**Use for:** Category theory, abstract algebra, topology, homological algebra, type theory, functional programming diagrams\n\n**Package:** `\\usepackage{tikz-cd}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{tikz-cd}\n\\begin{document}\n\n\\begin{tikzcd}\nA \\arrow{r}{f} \\arrow{d}{\\alpha} & B \\arrow{d}{\\beta} \\\\\nC \\arrow{r}{g} & D\n\\end{tikzcd}\n\n\\end{document}\n```\n\n**Notes:** Specialized syntax for arrows (`\\arrow{r}` for right, `\\arrow{d}` for down). Much cleaner than raw TikZ for commutative diagrams. Supports curved arrows with `\\arrow[bend left]` and diagonal arrows.\n\n---\n\n### forest (Tree Structures)\n\n**Use for:** Syntax trees (linguistics), parse trees (compilers), decision trees, organizational charts, file system hierarchies, game trees, proof trees\n\n**Package:** `\\usepackage{forest}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{forest}\n\\begin{document}\n\n\\begin{forest}\n[S\n [NP [Det [The]] [N [cat]]]\n [VP [V [sat]] [PP [P [on]] [NP [Det [the]] [N [mat]]]]]\n]\n\\end{forest}\n\n\\end{document}\n```\n\n**Notes:** Simple bracket notation for tree structure. Automatically handles node placement and spacing. Supports custom node styles, edge labels, and triangular subtrees for linguistic diagrams.\n\n---\n\n### tikz-3dplot (3D Coordinate Systems)\n\n**Use for:** 3D geometry, linear algebra (vectors, planes), physics (coordinate transformations), crystallography, 3D projections\n\n**Package:**\n```latex\n\\usepackage{tikz}\n\\usepackage{tikz-3dplot}\n```\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{tikz,tikz-3dplot}\n\\begin{document}\n\n\\tdplotsetmaincoords{60}{120}\n\\begin{tikzpicture}[tdplot_main_coords]\n\\draw[thick,->] (0,0,0) -- (3,0,0) node[anchor=north east]{$x$};\n\\draw[thick,->] (0,0,0) -- (0,3,0) node[anchor=north west]{$y$};\n\\draw[thick,->] (0,0,0) -- (0,0,3) node[anchor=south]{$z$};\n\\draw[blue,thick] (0,0,0) -- (2,2,2);\n\\end{tikzpicture}\n\n\\end{document}\n```\n\n**Notes:** `\\tdplotsetmaincoords{theta}{phi}` sets viewing angle. Use `tdplot_main_coords` coordinate system. Good for 3D vectors and simple surfaces, but pgfplots is better for 3D data plots.\n\n---\n\n### nicematrix (Enhanced Matrices & Tables)\n\n**Use for:** Colored matrices, bordered matrices, matrices with named cells, block matrices, augmented matrices, linear algebra, quantum computing state vectors, system of equations in matrix form\n\n**Package:** `\\usepackage{nicematrix}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{nicematrix}\n\\usepackage{xcolor}\n\\begin{document}\n\n% Colored augmented matrix\n$\\begin{pNiceArray}{ccc|c}[first-row,last-col]\nx & y & z & \\\\\n1 & 2 & 3 & 6 & L_1 \\\\\n0 & 1 & -1 & -2 & L_2 \\\\\n0 & 0 & 1 & 3 & L_3\n\\CodeAfter\n\\rowcolor{blue!10}{2}\n\\end{pNiceArray}$\n\n% Matrix with colored blocks\n$\\begin{bNiceMatrix}[margin]\n\\Block[fill=red!15]{2-2}{A} & & 0 \\\\\n& & 0 \\\\\n0 & 0 & \\Block[fill=blue!15]{1-1}{d}\n\\end{bNiceMatrix}$\n\n\\end{document}\n```\n\n**Notes:** Modern replacement for `array` and `amsmath` matrix environments. Key features: `\\Block` for merged cells with fill colors, `\\CodeAfter` for post-rendering decorations (lines, colors), automatic named cell nodes for TikZ overlay, dotted lines (`\\Cdots`, `\\Vdots`, `\\Ddots`). Works with pdflatex, xelatex, and lualatex. Particularly useful for linear algebra textbooks and lecture notes.\n\n---\n\n## Physics & Engineering\n\n### tikz-feynman (Feynman Diagrams)\n\n**Use for:** Particle physics, quantum field theory, high-energy physics papers\n\n**Package:** `\\usepackage[compat=1.1.0]{tikz-feynman}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage[compat=1.1.0]{tikz-feynman}\n\\begin{document}\n\n\\feynmandiagram[horizontal=a to b]{\n i1 -- [fermion] a -- [fermion] i2,\n a -- [photon] b,\n f1 -- [fermion] b -- [fermion] f2,\n};\n\n\\end{document}\n```\n\n**Notes:** **REQUIRES LuaLaTeX** (compile with `lualatex` instead of `pdflatex`). Automatic graph layout using Lua. Supports fermion lines, photon wavy lines, gluon springs, scalar dashed lines.\n\n---\n\n### circuitikz (Electronic Circuits)\n\n**Use for:** Electrical engineering, analog/digital circuits, schematics, signal flow diagrams\n\n**Package:** `\\usepackage{circuitikz}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{circuitikz}\n\\begin{document}\n\n\\begin{circuitikz}\n\\draw (0,0) to[battery1, l=$V$] (0,3)\n to[R, l=$R_1$] (3,3)\n to[L, l=$L$] (3,0)\n to[short] (0,0);\n\\draw (3,3) to[C, l=$C$] (3,0);\n\\end{circuitikz}\n\n\\end{document}\n```\n\n**Notes:** Rich component library (resistors, capacitors, inductors, op-amps, transistors, logic gates). Use `l=` for labels, `v=` for voltage labels. Supports European and American circuit symbols.\n\n---\n\n### tikz-timing (Timing Diagrams)\n\n**Use for:** Digital logic, hardware verification, signal processing, embedded systems, FPGA design\n\n**Package:** `\\usepackage{tikz-timing}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{tikz-timing}\n\\begin{document}\n\n\\begin{tikztimingtable}\nCLK & 10{C} \\\\\nDATA & 2L 3H 2L 3H \\\\\n\\end{tikztimingtable}\n\n\\end{document}\n```\n\n**Notes:** `C` = clock pulse, `H` = high, `L` = low, `Z` = high-impedance, `X` = unknown/transition. Number prefix repeats pattern (e.g., `10{C}` = 10 clock cycles).\n\n---\n\n## Chemistry\n\n### chemfig (Chemical Structures)\n\n**Use for:** Organic chemistry, molecular diagrams, structural formulas, reaction mechanisms\n\n**Package:** `\\usepackage{chemfig}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{chemfig}\n\\begin{document}\n\n\\chemfig{H-C(-[2]H)(-[6]H)-C(=[1]O)-O-H}\n\n\\chemfig{*6(-=-(-)=-=)}\n\n\\end{document}\n```\n\n**Notes:** Linear syntax for bonds: `-` (single), `=` (double), `~` (triple). Angles: `[0]` = right, `[1]` = 45°, `[2]` = up, etc. `*6(...)` creates hexagon (benzene ring). Supports stereochemistry wedges and ring structures.\n\n---\n\n### mhchem (Chemical Equations)\n\n**Use for:** Chemical equations, reaction stoichiometry, molecular formulas, isotope notation\n\n**Package:** `\\usepackage{mhchem}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{mhchem}\n\\begin{document}\n\n\\ce{2H2 + O2 -> 2H2O}\n\n\\ce{H2SO4 \u003c=> H+ + HSO4-}\n\n\\ce{^{14}_6C}\n\n\\end{document}\n```\n\n**Notes:** Use `\\ce{...}` for chemical notation. Subscripts/superscripts automatic. `->` for reactions, `\u003c=>` for equilibrium. Supports phase notation `(s)`, `(l)`, `(g)`, `(aq)`.\n\n---\n\n## Data Visualization\n\n### pgf-pie (Pie Charts)\n\n**Use for:** Market share, budget breakdowns, survey results, categorical proportions\n\n**Package:** `\\usepackage{pgf-pie}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{pgf-pie}\n\\begin{document}\n\n\\begin{tikzpicture}\n\\pie[radius=2]{\n 35/Product A,\n 25/Product B,\n 20/Product C,\n 15/Product D,\n 5/Other\n}\n\\end{tikzpicture}\n\n\\end{document}\n```\n\n**Notes:** Syntax: `percentage/label`. Options: `radius=`, `color=`, `explode=` (separate slice), `text=legend` (legend instead of labels). Auto-colored slices.\n\n---\n\n### pgfplots (fillbetween library)\n\n**Use for:** Area between curves, confidence intervals, statistical ranges, integration visualizations\n\n**Package:**\n```latex\n\\usepackage{pgfplots}\n\\usepgfplotslibrary{fillbetween}\n\\pgfplotsset{compat=1.18}\n```\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{pgfplots}\n\\usepgfplotslibrary{fillbetween}\n\\pgfplotsset{compat=1.18}\n\\begin{document}\n\n\\begin{tikzpicture}\n\\begin{axis}\n\\addplot[name path=A, blue] {x^2};\n\\addplot[name path=B, red] {2*x};\n\\addplot[fill=green, opacity=0.3] fill between[of=A and B];\n\\end{axis}\n\\end{tikzpicture}\n\n\\end{document}\n```\n\n**Notes:** Use `name path=` to name curves, then `fill between[of=A and B]`. Supports `soft clip` for restricting fill region.\n\n---\n\n### pgfplots (3D Surface Plots)\n\n**Use for:** Multivariable calculus, heat maps, terrain visualization, response surfaces, optimization landscapes\n\n**Package:**\n```latex\n\\usepackage{pgfplots}\n\\pgfplotsset{compat=1.18}\n```\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{pgfplots}\n\\pgfplotsset{compat=1.18}\n\\begin{document}\n\n\\begin{tikzpicture}\n\\begin{axis}[view={60}{30}]\n\\addplot3[surf, domain=-2:2, samples=20] {x^2 - y^2};\n\\end{axis}\n\\end{tikzpicture}\n\n\\end{document}\n```\n\n**Notes:** `surf` = surface plot, `mesh` = wireframe, `scatter` = 3D scatter. `view={azimuth}{elevation}` controls viewing angle. Can plot from data files with `\\addplot3 table {data.txt};`.\n\n---\n\n## Network & Graph Theory\n\n### tikz-network (Network Graphs)\n\n**Use for:** Social networks, computer networks, neural networks, graph visualization, network topology\n\n**Package:** `\\usepackage{tikz-network}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{tikz-network}\n\\begin{document}\n\n\\begin{tikzpicture}\n\\Vertex[x=0, y=0, label=A]{a}\n\\Vertex[x=2, y=1, label=B]{b}\n\\Vertex[x=2, y=-1, label=C]{c}\n\\Edge[label=5](a)(b)\n\\Edge[label=3](a)(c)\n\\Edge[label=2, bend=20](b)(c)\n\\end{tikzpicture}\n\n\\end{document}\n```\n\n**Notes:** `\\Vertex` creates nodes with position and label. `\\Edge` creates connections with optional labels and bend. Supports directed edges with `Direct` option, and styled vertices/edges.\n\n---\n\n### tikz-dependency (Dependency Parsing)\n\n**Use for:** Natural language processing, dependency grammar, syntactic parsing, computational linguistics\n\n**Package:** `\\usepackage{tikz-dependency}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{tikz-dependency}\n\\begin{document}\n\n\\begin{dependency}\n\\begin{deptext}\nThe \\& cat \\& sat \\& on \\& the \\& mat \\\\\n\\end{deptext}\n\\deproot{3}{ROOT}\n\\depedge{2}{1}{det}\n\\depedge{3}{2}{nsubj}\n\\depedge{3}{4}{prep}\n\\depedge{6}{5}{det}\n\\depedge{4}{6}{pobj}\n\\end{dependency}\n\n\\end{document}\n```\n\n**Notes:** `\\deptext` defines word sequence. `\\depedge{from}{to}{label}` creates dependency arcs. `\\deproot{word}{label}` marks root. Automatically manages arc positioning to avoid overlaps.\n\n---\n\n## Business & General\n\n### smartdiagram (Preset Diagram Types)\n\n**Use for:** Presentations, business diagrams, process flows, cyclic diagrams, organizational structures\n\n**Package:** `\\usepackage{smartdiagram}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{smartdiagram}\n\\begin{document}\n\n\\smartdiagram[circular diagram]{\n Planning, Design, Development, Testing, Deployment\n}\n\n\\smartdiagram[priority descriptive diagram]{\n Goal 1/Primary objective,\n Goal 2/Secondary objective,\n Goal 3/Tertiary objective\n}\n\n\\end{document}\n```\n\n**Notes:** Multiple preset types: `circular diagram`, `flow diagram`, `bubble diagram`, `priority descriptive diagram`, `sequence diagram`. Minimal syntax—just list items. Good for quick professional diagrams.\n\n---\n\n### pgfgantt (Gantt Charts)\n\n**Use for:** Project management, timeline planning, task scheduling, resource allocation\n\n**Package:** `\\usepackage{pgfgantt}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{pgfgantt}\n\\begin{document}\n\n\\begin{ganttchart}[hgrid, vgrid]{1}{12}\n\\gantttitle{2026 Project Timeline}{12} \\\\\n\\gantttitlelist{1,...,12}{1} \\\\\n\\ganttbar{Task 1}{1}{3} \\\\\n\\ganttbar{Task 2}{4}{7} \\\\\n\\ganttbar{Task 3}{8}{12}\n\\end{ganttchart}\n\n\\end{document}\n```\n\n**Notes:** `\\ganttbar{label}{start}{end}` creates task bars. `\\ganttlink{elem1}{elem2}` adds dependencies. Supports milestones with `\\ganttmilestone`, grouped tasks with `\\ganttgroup`.\n\n---\n\n### genealogytree (Family Trees)\n\n**Use for:** Genealogy, pedigree charts, family history, inheritance diagrams\n\n**Package:** `\\usepackage{genealogytree}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{genealogytree}\n\\begin{document}\n\n\\begin{genealogypicture}\nparent{\n g[male]{John Smith}\n p[female]{Jane Doe}\n c[male]{Bob Smith}\n c[female]{Alice Smith}\n}\n\\end{genealogypicture}\n\n\\end{document}\n```\n\n**Notes:** `g` = grandparent, `p` = parent, `c` = child. Gender specified with `[male]` or `[female]`. Supports multiple generations, marriage links, and custom node styles.\n\n---\n\n### chronosys (Timelines)\n\n**Use for:** Historical timelines, project milestones, biographical chronologies, event sequences\n\n**Package:** `\\usepackage{chronosys}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{chronosys}\n\\begin{document}\n\n\\startchronology[startyear=2020, stopyear=2026]\n\\chronoevent{2020}{Project Start}\n\\chronoevent{2022}{Milestone 1}\n\\chronoevent{2024}{Milestone 2}\n\\chronoevent{2026}{Completion}\n\\stopchronology\n\n\\end{document}\n```\n\n**Notes:** Define year range with `startyear`/`stopyear`. Use `\\chronoevent{year}{label}` for events. Supports horizontal and vertical timelines, custom styling, and period spans.\n\n---\n\n## Music & Games\n\n### xskak / chessboard (Chess Positions)\n\n**Use for:** Chess puzzles, game notation, chess analysis, chess instruction\n\n**Package:**\n```latex\n\\usepackage{xskak}\n\\usepackage{chessboard}\n```\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{xskak}\n\\usepackage{chessboard}\n\\begin{document}\n\n\\chessboard[setfen=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR]\n\n\\newchessgame\n\\mainline{1. e4 e5 2. Nf3 Nc6}\n\\chessboard\n\n\\end{document}\n```\n\n**Notes:** `\\chessboard[setfen=...]` displays position from FEN notation. `\\mainline{...}` parses algebraic notation and updates position. Supports move highlighting, arrows, and custom piece styles.\n\n---\n\n### guitarchordschemes (Guitar Chords)\n\n**Use for:** Guitar instruction, chord charts, music theory, songbooks\n\n**Package:** `\\usepackage{guitarchordschemes}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{guitarchordschemes}\n\\begin{document}\n\n\\chordscheme[name=C Major]{x,3,2,0,1,0}\n\n\\chordscheme[name=G Major]{3,2,0,0,0,3}\n\n\\chordscheme[name=D Minor, barre=1/1-5]{x,x,0,2,3,1}\n\n\\end{document}\n```\n\n**Notes:** Syntax: 6 strings from low E to high E. `x` = muted, `0` = open string, numbers = fret positions. `barre=fret/string-string` for barre chords. Displays standard chord diagram grid.\n\n---\n\n## Scientific Computing\n\n### siunitx (SI Units & Scientific Notation)\n\n**Use for:** Physics, engineering, scientific papers, data tables with units, measurement reporting\n\n**Package:** `\\usepackage{siunitx}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{siunitx}\n\\begin{document}\n\n\\SI{3.0e8}{\\meter\\per\\second}\n\n\\SI{9.81}{\\meter\\per\\second\\squared}\n\n\\num{1.234e-5}\n\n\\SI{25}{\\celsius}\n\n\\end{document}\n```\n\n**Notes:** `\\SI{value}{unit}` for quantities with units. `\\num{value}` for pure numbers with proper formatting. Automatic spacing, exponent formatting, and unit notation. Use `\\per` for division, `\\squared` for powers.\n\n---\n\n### animate (PDF Animations)\n\n**Use for:** Animated algorithms, step-by-step proofs, dynamic visualizations, presentation builds\n\n**Package:** `\\usepackage{animate}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{animate}\n\\usepackage{tikz}\n\\begin{document}\n\n\\begin{animateinline}[loop, controls]{2}\n\\multiframe{10}{i=0+1}{\n \\begin{tikzpicture}\n \\draw (0,0) circle (\\i mm);\n \\end{tikzpicture}\n}\n\\end{animateinline}\n\n\\end{document}\n```\n\n**Notes:** **Animations only work in Adobe Reader**. `\\begin{animateinline}{fps}` creates inline animation. `\\multiframe{n}{counter=start+step}{...}` generates frames. Use `loop` for continuous play, `controls` for play/pause buttons.\n\n---\n\n### standalone (Compile Individual Graphics)\n\n**Use for:** Extracting single diagrams, creating reusable graphics, figure generation pipelines, cropped PDFs\n\n**Package:** `\\documentclass{standalone}` (document class, not package)\n\n**Minimal Example:**\n```latex\n\\documentclass{standalone}\n\\usepackage{tikz}\n\\begin{document}\n\\begin{tikzpicture}\n\\draw (0,0) rectangle (3,2);\n\\node at (1.5,1) {Diagram};\n\\end{tikzpicture}\n\\end{document}\n```\n\n**Notes:** Compiles to tightly-cropped PDF containing only the diagram. Use `\\standaloneconfig{border=5pt}` to add padding. Perfect for generating figures separately and including via `\\includegraphics`.\n\n---\n\n### algorithm2e (Algorithm Typesetting)\n\n**Use for:** Computer science papers, algorithm pseudocode, complexity analysis, technical documentation\n\n**Package:** `\\usepackage{algorithm2e}`\n\n**Minimal Example:**\n```latex\n\\documentclass{article}\n\\usepackage{algorithm2e}\n\\begin{document}\n\n\\begin{algorithm}\n\\KwData{Array $A$ of size $n$}\n\\KwResult{Sorted array $A$}\n\\For{$i \\gets 1$ \\KwTo $n-1$}{\n \\For{$j \\gets i+1$ \\KwTo $n$}{\n \\If{$A[i] > A[j]$}{\n Swap $A[i]$ and $A[j]$\\;\n }\n }\n}\n\\caption{Bubble Sort}\n\\end{algorithm}\n\n\\end{document}\n```\n\n**Notes:** `\\KwData` and `\\KwResult` for input/output specification. Control structures: `\\For`, `\\While`, `\\If`, `\\ElseIf`, `\\Else`. Line terminator `\\;` is optional. Use `\\caption{}` for algorithm title.\n\n---\n\n### listings / minted (Code Listings with Syntax Highlighting)\n\n**Use for:** Technical documentation, code examples, programming tutorials, software papers\n\n**Package (listings):** `\\usepackage{listings}`\n\n**Minimal Example (listings):**\n```latex\n\\documentclass{article}\n\\usepackage{listings}\n\\usepackage{xcolor}\n\\lstset{\n basicstyle=\\ttfamily,\n keywordstyle=\\color{blue},\n commentstyle=\\color{green!60!black},\n stringstyle=\\color{red},\n numbers=left\n}\n\\begin{document}\n\n\\begin{lstlisting}[language=Python]\ndef factorial(n):\n if n \u003c= 1:\n return 1\n return n * factorial(n-1)\n\\end{lstlisting}\n\n\\end{document}\n```\n\n**Package (minted):** `\\usepackage{minted}`\n\n**Minimal Example (minted):**\n```latex\n\\documentclass{article}\n\\usepackage{minted}\n\\begin{document}\n\n\\begin{minted}{python}\ndef factorial(n):\n if n \u003c= 1:\n return 1\n return n * factorial(n-1)\n\\end{minted}\n\n\\end{document}\n```\n\n**Notes:** `listings` is pure LaTeX, works everywhere. `minted` uses Pygments for better syntax highlighting but **requires `-shell-escape` flag** and Python with Pygments installed. Compile with: `pdflatex -shell-escape document.tex`\n\n---\n\n## Quick Reference Table\n\n| Package | Use Case | Special Requirements | Minimal \\usepackage |\n|---------|----------|---------------------|---------------------|\n| tikz-cd | Commutative diagrams (category theory) | None | `\\usepackage{tikz-cd}` |\n| forest | Tree structures (syntax trees, parse trees) | None | `\\usepackage{forest}` |\n| tikz-3dplot | 3D coordinate systems and vectors | Requires `\\usepackage{tikz}` | `\\usepackage{tikz-3dplot}` |\n| nicematrix | Enhanced matrices with colors and blocks | None | `\\usepackage{nicematrix}` |\n| circuitikz | Electronic circuit diagrams | None | `\\usepackage{circuitikz}` |\n| pgf-pie | Pie charts | None | `\\usepackage{pgf-pie}` |\n| tikz-feynman | Feynman diagrams (particle physics) | **Requires LuaLaTeX** | `\\usepackage[compat=1.1.0]{tikz-feynman}` |\n| tikz-timing | Timing diagrams (digital logic) | None | `\\usepackage{tikz-timing}` |\n| tikz-network | Network and graph visualization | None | `\\usepackage{tikz-network}` |\n| tikz-dependency | Dependency parsing (NLP) | None | `\\usepackage{tikz-dependency}` |\n| smartdiagram | Preset diagram types (circular, flow, bubble) | None | `\\usepackage{smartdiagram}` |\n| pgfplots fillbetween | Area between curves | Requires pgfplots | `\\usepgfplotslibrary{fillbetween}` |\n| chemfig | Chemical structure diagrams | None | `\\usepackage{chemfig}` |\n| mhchem | Chemical equations and formulas | None | `\\usepackage{mhchem}` |\n| pgfplots 3D | 3D surface plots | Requires pgfplots | `\\usepackage{pgfplots}` |\n| xskak/chessboard | Chess positions and notation | None | `\\usepackage{xskak,chessboard}` |\n| guitarchordschemes | Guitar chord diagrams | None | `\\usepackage{guitarchordschemes}` |\n| pgfgantt | Gantt charts (project management) | None | `\\usepackage{pgfgantt}` |\n| genealogytree | Family trees and pedigrees | None | `\\usepackage{genealogytree}` |\n| chronosys | Historical timelines | None | `\\usepackage{chronosys}` |\n| siunitx | SI units and scientific notation | None | `\\usepackage{siunitx}` |\n| animate | PDF animations (frame-based) | Adobe Reader only | `\\usepackage{animate}` |\n| standalone | Compile individual graphics (cropped PDF) | Document class | `\\documentclass{standalone}` |\n| algorithm2e | Algorithm pseudocode | None | `\\usepackage{algorithm2e}` |\n| listings | Code syntax highlighting (pure LaTeX) | None | `\\usepackage{listings}` |\n| minted | Code syntax highlighting (Pygments) | **Requires `-shell-escape` and Python/Pygments** | `\\usepackage{minted}` |\n\n---\n\n## Tips\n\n1. **Test compilation:** Most packages work with standard `pdflatex`, but tikz-feynman requires `lualatex` and minted requires `pdflatex -shell-escape`.\n\n2. **Combine packages:** Many packages work together. Use tikz-cd for category theory diagrams in a beamer presentation, or circuitikz with siunitx for labeled circuit values.\n\n3. **Documentation:** All packages have extensive documentation. Run `texdoc \u003cpackagename>` (e.g., `texdoc forest`) to view the full manual.\n\n4. **Performance:** Complex TikZ diagrams can slow compilation. Use `standalone` class to compile diagrams separately, then include the resulting PDF.\n\n5. **Color schemes:** Most packages respect TikZ/pgfplots color settings. Define custom colors with `\\definecolor` for consistent styling.\n\n6. **External data:** pgfplots can read CSV/TSV files. Use `\\addplot table {data.csv};` for data-driven plots.\n\n7. **Minimal examples compile:** Every example in this guide is complete and compilable. Copy-paste to test, then customize for your needs.\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":22024,"content_sha256":"1a3ee86c769febd3702190ecc5ee6804b02ba2d1d601ade35245914d3348f372"},{"filename":"scripts/compile_latex.sh","content":"#!/usr/bin/env bash\n# compile_latex.sh - Compile .tex to .pdf and optionally generate PNG previews\n#\n# Usage:\n# compile_latex.sh \u003cinput.tex> [OPTIONS]\n#\n# Options:\n# --preview Generate PNG previews of each page\n# --preview-dir Directory for PNG output (default: same as input)\n# --scale Max dimension for PNG preview in pixels (default: 1200)\n# --engine LaTeX engine: pdflatex (default), xelatex, or lualatex\n# --auto-fix Apply automatic fixes (naked floats, microtype) to temp copy before compiling\n# --use-latexmk Use latexmk for compilation (automatic multi-pass, dependency tracking)\n# --verbose Show full compilation output (default: summary only)\n# --quiet Suppress all output except errors and final paths\n# --clean Remove auxiliary files without recompiling\n# --pdfa Produce PDF/A-compliant output (for thesis/archival submissions)\n#\n# Features:\n# - Auto-installs texlive if missing\n# - Auto-detects engine from document content (fontspec/xeCJK → xelatex)\n# - Detects .bib files and runs bibtex/biber automatically\n# - Detects \\makeindex and runs makeindex automatically\n# - Detects \\makeglossaries and runs makeglossaries automatically\n# - Runs multiple passes for cross-references\n# - Optional latexmk backend for automatic dependency resolution\n# - Optional texfot log filtering for cleaner output\n# - Generates PNG previews with pdftoppm\n# - Cleans auxiliary files after compilation\n# - Smart error recovery with --auto-fix:\n# * Automatically adds [htbp] to naked floats\n# * Auto-injects microtype for overfull hbox warnings\n# - Intelligent error parsing and helpful suggestions\n#\n# Examples:\n# compile_latex.sh resume.tex\n# compile_latex.sh report.tex --preview\n# compile_latex.sh report.tex --preview --preview-dir ./outputs --scale 1600\n# compile_latex.sh cjk-doc.tex --engine xelatex\n# compile_latex.sh document.tex --engine lualatex --preview\n# compile_latex.sh paper.tex --auto-fix\n# compile_latex.sh thesis.tex --use-latexmk --verbose\n# compile_latex.sh thesis.tex --pdfa\n# compile_latex.sh document.tex --clean\n\nset -euo pipefail\n\n# --- Usage function ---\nusage() {\n cat \u003c\u003c'EOF'\ncompile_latex.sh - Compile .tex to .pdf and optionally generate PNG previews\n\nUsage:\n compile_latex.sh \u003cinput.tex> [OPTIONS]\n\nOptions:\n --preview Generate PNG previews of each page\n --preview-dir Directory for PNG output (default: same as input)\n --scale Max dimension for PNG preview in pixels (default: 1200)\n --engine LaTeX engine: pdflatex (default), xelatex, or lualatex\n --auto-fix Apply automatic fixes (naked floats, microtype) to temp copy before compiling\n --use-latexmk Use latexmk for compilation (automatic multi-pass, dependency tracking)\n --verbose Show full compilation output\n --quiet Suppress all output except errors and final paths\n --clean Remove auxiliary files without recompiling\n --pdfa Produce PDF/A-compliant output (for thesis/archival submissions)\n\nFeatures:\n - Auto-installs texlive if missing\n - Auto-detects engine from document content (fontspec/xeCJK → xelatex)\n - Detects .bib files and runs bibtex/biber automatically\n - Detects \\makeindex and runs makeindex automatically\n - Detects \\makeglossaries and runs makeglossaries automatically\n - Runs multiple passes for cross-references\n - Optional latexmk backend (--use-latexmk) for automatic dependency resolution\n - Optional texfot log filtering for cleaner output (used automatically when available)\n - Generates PNG previews with pdftoppm\n - Cleans auxiliary files after compilation\n - Smart error recovery with --auto-fix:\n * Automatically adds [htbp] to naked floats\n * Auto-injects microtype for overfull hbox warnings\n - Intelligent error parsing and helpful suggestions\n - PDF/A output for archival submissions (--pdfa)\n\nExamples:\n compile_latex.sh resume.tex\n compile_latex.sh report.tex --preview\n compile_latex.sh report.tex --preview --preview-dir ./outputs --scale 1600\n compile_latex.sh cjk-doc.tex --engine xelatex\n compile_latex.sh document.tex --engine lualatex --preview\n compile_latex.sh paper.tex --auto-fix\n compile_latex.sh thesis.tex --use-latexmk --verbose\n compile_latex.sh thesis.tex --pdfa\n compile_latex.sh document.tex --clean\nEOF\n}\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# --- Parse arguments ---\nINPUT_TEX=\"\"\nPREVIEW=false\nPREVIEW_DIR=\"\"\nSCALE=1200\nENGINE=\"\"\nAUTO_FIX=false\nUSE_LATEXMK=false\nVERBOSE=false\nQUIET=false\nCLEAN_ONLY=false\nPDFA=false\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) usage; exit 0 ;;\n --preview) PREVIEW=true; shift ;;\n --preview-dir) PREVIEW_DIR=\"$2\"; shift 2 ;;\n --scale) SCALE=\"$2\"; shift 2 ;;\n --engine) ENGINE=\"$2\"; shift 2 ;;\n --auto-fix) AUTO_FIX=true; shift ;;\n --use-latexmk) USE_LATEXMK=true; shift ;;\n --verbose) VERBOSE=true; shift ;;\n --quiet) QUIET=true; shift ;;\n --clean) CLEAN_ONLY=true; shift ;;\n --pdfa) PDFA=true; shift ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *) INPUT_TEX=\"$1\"; shift ;;\n esac\ndone\n\nif [[ -z \"$INPUT_TEX\" ]]; then\n echo \"Error: No input .tex file specified\" >&2\n echo \"Usage: compile_latex.sh \u003cinput.tex> [--preview] [--preview-dir \u003cdir>] [--scale \u003cpixels>] [--engine \u003cengine>]\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_TEX\" ]]; then\n echo \"Error: File not found: $INPUT_TEX\" >&2\n exit 1\nfi\n\n# Resolve absolute paths\nINPUT_TEX=\"$(realpath \"$INPUT_TEX\")\"\nINPUT_DIR=\"$(dirname \"$INPUT_TEX\")\"\nINPUT_BASE=\"$(basename \"$INPUT_TEX\" .tex)\"\nPDF_FILE=\"${INPUT_DIR}/${INPUT_BASE}.pdf\"\n\nif [[ -z \"$PREVIEW_DIR\" ]]; then\n PREVIEW_DIR=\"$INPUT_DIR\"\nfi\n\n# --- Logging helpers (respect --verbose / --quiet) ---\nlog_info() {\n [[ \"$QUIET\" == true ]] && return\n echo \":: $*\" >&2\n}\n\nlog_detail() {\n [[ \"$VERBOSE\" != true ]] && return\n echo \" $*\" >&2\n}\n\n# --- Handle --clean mode (remove aux files and exit) ---\nif [[ \"$CLEAN_ONLY\" == true ]]; then\n log_info \"Cleaning auxiliary files for ${INPUT_BASE}...\"\n cd \"$INPUT_DIR\"\n rm -f \"${INPUT_BASE}.aux\" \"${INPUT_BASE}.log\" \"${INPUT_BASE}.out\" \\\n \"${INPUT_BASE}.toc\" \"${INPUT_BASE}.lof\" \"${INPUT_BASE}.lot\" \\\n \"${INPUT_BASE}.nav\" \"${INPUT_BASE}.snm\" \"${INPUT_BASE}.vrb\" \\\n \"${INPUT_BASE}.bbl\" \"${INPUT_BASE}.blg\" \\\n \"${INPUT_BASE}.idx\" \"${INPUT_BASE}.ilg\" \"${INPUT_BASE}.ind\" \\\n \"${INPUT_BASE}.bcf\" \"${INPUT_BASE}.run.xml\" \\\n \"${INPUT_BASE}.glo\" \"${INPUT_BASE}.gls\" \"${INPUT_BASE}.glg\" \\\n \"${INPUT_BASE}.ist\" \"${INPUT_BASE}.acn\" \"${INPUT_BASE}.acr\" \\\n \"${INPUT_BASE}.alg\" \"${INPUT_BASE}.fls\" \"${INPUT_BASE}.fdb_latexmk\" \\\n \"${INPUT_BASE}.synctex.gz\" \"${INPUT_BASE}.xdv\" \\\n \"${INPUT_BASE}.pytxcode\" 2>/dev/null || true\n log_info \"Auxiliary files cleaned.\"\n exit 0\nfi\n\n# --- Ensure TeX Live is installed ---\nensure_texlive() {\n if command -v pdflatex &>/dev/null; then\n return 0\n fi\n echo \":: pdflatex not found. Installing TeX Live (this may take several minutes)...\" >&2\n install_packages \"texlive\" || {\n echo \"Error: Failed to install TeX Live.\" >&2\n print_install_help \"texlive\"\n exit 1\n }\n _brew_post_texlive\n if ! command -v pdflatex &>/dev/null; then\n echo \"Error: pdflatex still not available after install\" >&2\n print_install_help \"texlive\"\n exit 1\n fi\n echo \":: TeX Live installed successfully\" >&2\n}\n\n# --- Ensure poppler-utils for PDF-to-PNG ---\nensure_poppler() {\n if command -v pdftoppm &>/dev/null; then\n return 0\n fi\n echo \":: pdftoppm not found. Installing poppler...\" >&2\n install_packages \"poppler\" || {\n echo \"Error: Failed to install poppler.\" >&2\n print_install_help \"poppler\"\n exit 1\n }\n}\n\n# --- Auto-detect engine from document content ---\ndetect_engine() {\n # If user specified engine, use that\n if [[ -n \"$ENGINE\" ]]; then\n echo \"$ENGINE\"\n return\n fi\n # Check for packages that require XeLaTeX/LuaLaTeX\n # Filter out commented lines (starting with %) before checking\n local uncommented\n uncommented=$(sed 's/%.*//;/^[[:space:]]*$/d' \"$INPUT_TEX\" 2>/dev/null)\n if echo \"$uncommented\" | grep -qE '\\\\usepackage\\{fontspec\\}|\\\\usepackage\\{xeCJK\\}|\\\\usepackage\\{polyglossia\\}'; then\n echo \"xelatex\"\n elif echo \"$uncommented\" | grep -qE '\\\\usepackage\\{luacode\\}|\\\\usepackage\\{luatextra\\}|\\\\directlua'; then\n echo \"lualatex\"\n else\n echo \"pdflatex\"\n fi\n}\n\n# --- Detect bibliography usage ---\ndetect_bibliography() {\n # Filter out comments (both full-line and inline) before checking\n local uncommented\n uncommented=$(sed 's/%.*//;/^[[:space:]]*$/d' \"$INPUT_TEX\" 2>/dev/null)\n if echo \"$uncommented\" | grep -qE '\\\\bibliography\\{'; then\n echo \"bibtex\"\n elif echo \"$uncommented\" | grep -qE '\\\\addbibresource\\{'; then\n echo \"biber\"\n else\n echo \"none\"\n fi\n}\n\n# --- Detect makeindex usage ---\ndetect_makeindex() {\n local uncommented\n uncommented=$(sed 's/%.*//;/^[[:space:]]*$/d' \"$INPUT_TEX\" 2>/dev/null)\n echo \"$uncommented\" | grep -qE '\\\\makeindex|\\\\printindex'\n}\n\n# --- Detect glossary usage ---\ndetect_glossary() {\n local uncommented\n uncommented=$(sed 's/%.*//;/^[[:space:]]*$/d' \"$INPUT_TEX\" 2>/dev/null)\n echo \"$uncommented\" | grep -qE '\\\\makeglossaries|\\\\printglossary|\\\\printglossaries|\\\\newacronym'\n}\n\n# --- Parse and translate common LaTeX errors ---\nparse_errors() {\n local log_file=\"$1\"\n if [[ ! -f \"$log_file\" ]]; then\n return\n fi\n\n echo \"\" >&2\n echo \"=== LaTeX Error Analysis ===\" >&2\n\n # Check for missing packages\n if grep -q \"File \\`.*\\.sty' not found\" \"$log_file\"; then\n echo \"\" >&2\n grep \"File \\`.*\\.sty' not found\" \"$log_file\" | sed -E 's/.*File `(.*)\\.sty.*/Missing package: \\1/' | while read -r line; do\n package=$(echo \"$line\" | sed 's/Missing package: //')\n echo \" ! $line\" >&2\n echo \" → Install with: sudo apt-get install texlive-latex-extra\" >&2\n echo \" → Or try: tlmgr install $package\" >&2\n done\n fi\n\n # Check for math mode errors\n if grep -q \"Missing \\$ inserted\" \"$log_file\"; then\n echo \"\" >&2\n echo \" ! Math mode error: You used a math symbol outside of \\$ delimiters\" >&2\n grep -n \"Missing \\$ inserted\" \"$log_file\" | head -5 | sed 's/^/ Line /' >&2\n echo \" → Wrap math symbols with \\$...\\$ or use \\\\(...\\\\) for inline math\" >&2\n fi\n\n # Check for undefined control sequences\n if grep -q \"Undefined control sequence\" \"$log_file\"; then\n echo \"\" >&2\n echo \" ! Undefined control sequence(s) detected\" >&2\n grep -A1 \"Undefined control sequence\" \"$log_file\" | grep \"^l\\.[0-9]\" | head -5 | while read -r line; do\n linenum=$(echo \"$line\" | sed -E 's/^l\\.([0-9]+).*/\\1/')\n cmd=$(echo \"$line\" | sed -E 's/.*\\\\([a-zA-Z]+).*/\\\\\\1/')\n echo \" Line $linenum: Unknown command '$cmd'\" >&2\n done\n echo \" → Check spelling or add the required \\\\usepackage\" >&2\n fi\n\n # Check for missing \\begin{document}\n if grep -q \"Missing .begin.document.\" \"$log_file\"; then\n echo \"\" >&2\n echo \" ! Your document is missing \\\\begin{document}\" >&2\n echo \" → Add \\\\begin{document} after the preamble (after all \\\\usepackage lines)\" >&2\n fi\n\n # Check for unbalanced braces\n if grep -q \"Too many }'s\" \"$log_file\"; then\n echo \"\" >&2\n echo \" ! Unbalanced braces detected\" >&2\n grep -n \"Too many }'s\" \"$log_file\" | head -3 | sed 's/^/ /' >&2\n echo \" → Check for missing { or extra }\" >&2\n fi\n\n # Check for undefined environments\n if grep -q \"LaTeX Error: Environment .* undefined\" \"$log_file\"; then\n echo \"\" >&2\n grep \"LaTeX Error: Environment .* undefined\" \"$log_file\" | sed -E 's/.*Environment (.*) undefined.*/ ! Environment \"\\1\" not defined/' | head -3 >&2\n echo \" → Add the required \\\\usepackage for this environment\" >&2\n fi\n\n # Check for overfull hbox (margin overflow)\n local overfull_count=0\n if [[ -f \"$log_file\" ]]; then\n overfull_count=$(grep -c \"Overfull .hbox\" \"$log_file\" 2>/dev/null || true)\n overfull_count=${overfull_count:-0}\n fi\n if [[ \"$overfull_count\" -gt 0 ]]; then\n echo \"\" >&2\n echo \" ! Found $overfull_count overfull hbox warning(s) - text overflows margins\" >&2\n if [[ \"$AUTO_FIX\" == true ]]; then\n echo \" → Auto-fix will attempt to apply microtype package\" >&2\n else\n echo \" → Consider adding \\\\usepackage{microtype} to preamble\" >&2\n echo \" → Or use --auto-fix flag to apply automatically\" >&2\n fi\n fi\n\n # Check for undefined citations\n if grep -q \"Citation .* undefined\" \"$log_file\"; then\n echo \"\" >&2\n echo \" ! Undefined citation(s) detected\" >&2\n grep \"Citation .* undefined\" \"$log_file\" | sed -E \"s/.*Citation \\`(.*)' .*/ '\\1'/\" | sort -u | head -5 >&2\n echo \" → Check spelling or ensure your .bib file is correct\" >&2\n echo \" → Make sure bibliography engine ran (bibtex/biber)\" >&2\n fi\n\n echo \"\" >&2\n}\n\n# --- Auto-fix floats (adds [htbp] to naked floats) ---\nauto_fix_floats() {\n local input_file=\"$1\"\n local output_file=\"$2\"\n\n # Copy input to output\n cp \"$input_file\" \"$output_file\"\n\n # Fix naked floats - add [htbp] to figure and table environments without placement specifiers\n # Two passes: (1) end-of-line case, (2) mid-line case where next char is not [\n # Pass 1: \\begin{figure} at end of line (nothing or whitespace follows)\n sed -i.bak -E 's/\\\\begin\\{(figure|table)\\}[[:space:]]*$/\\\\begin{\\1}[htbp]/g' \"$output_file\"\n rm -f \"${output_file}.bak\"\n # Pass 2: \\begin{figure} followed by non-[ character (mid-line)\n sed -i.bak -E 's/\\\\begin\\{(figure|table)\\}([^[[])/\\\\begin{\\1}[htbp]\\2/g' \"$output_file\"\n rm -f \"${output_file}.bak\"\n\n # Count how many fixes were made\n local fixed_count=$(grep -o '\\\\begin{figure}\\[htbp\\]\\|\\\\begin{table}\\[htbp\\]' \"$output_file\" 2>/dev/null | wc -l)\n if [[ $fixed_count -gt 0 ]]; then\n echo \" → Fixed $fixed_count naked float(s) by adding [htbp] placement\" >&2\n fi\n}\n\n# --- Auto-inject microtype if needed ---\nauto_inject_microtype() {\n local input_file=\"$1\"\n local output_file=\"$2\"\n\n # Check if microtype is already present\n if grep -q '\\\\usepackage.*{microtype}' \"$input_file\"; then\n echo \" → microtype already present, skipping injection\" >&2\n cp \"$input_file\" \"$output_file\"\n return\n fi\n\n # Find the last \\usepackage line and inject microtype after it\n # If no \\usepackage found, inject after \\documentclass\n if grep -q '\\\\usepackage' \"$input_file\"; then\n # Find line number of last \\usepackage\n local last_pkg_line=$(grep -n '\\\\usepackage' \"$input_file\" | tail -1 | cut -d: -f1)\n # Insert after that line\n awk -v line=\"$last_pkg_line\" 'NR==line {print; print \"\\\\usepackage{microtype} % Auto-injected for better spacing\"; next} {print}' \"$input_file\" > \"$output_file\"\n echo \" → Injected \\\\usepackage{microtype} after line $last_pkg_line\" >&2\n elif grep -q '\\\\documentclass' \"$input_file\"; then\n local docclass_line=$(grep -n '\\\\documentclass' \"$input_file\" | head -1 | cut -d: -f1)\n awk -v line=\"$docclass_line\" 'NR==line {print; print \"\\\\usepackage{microtype} % Auto-injected for better spacing\"; next} {print}' \"$input_file\" > \"$output_file\"\n echo \" → Injected \\\\usepackage{microtype} after \\\\documentclass\" >&2\n else\n # Fallback: just copy\n cp \"$input_file\" \"$output_file\"\n fi\n}\n\n# --- Run engine command with optional texfot filtering ---\n# Uses texfot when available and not in verbose mode, to show only relevant warnings/errors.\nrun_engine() {\n local engine=\"$1\"\n shift\n local texfile=\"$1\"\n shift\n\n if [[ \"$VERBOSE\" == true ]]; then\n # Verbose: show full output\n \"$engine\" -interaction=nonstopmode \"$@\" \"$texfile\" >&2\n elif [[ \"$QUIET\" == true ]]; then\n # Quiet: suppress everything\n \"$engine\" -interaction=nonstopmode \"$@\" \"$texfile\" >/dev/null 2>&1\n elif command -v texfot &>/dev/null; then\n # Default with texfot: filtered output\n texfot \"$engine\" -interaction=nonstopmode \"$@\" \"$texfile\" >&2 2>/dev/null\n else\n # Default without texfot: suppress output\n \"$engine\" -interaction=nonstopmode \"$@\" \"$texfile\" >/dev/null 2>&1\n fi\n}\n\n# --- PDF/A injection: add pdfx package to preamble ---\npdfa_inject() {\n local input_file=\"$1\"\n local output_file=\"$2\"\n\n # Check if pdfx or pdfmanagement is already present\n if grep -qE '\\\\usepackage(\\[.*\\])?\\{pdfx\\}|\\\\usepackage(\\[.*\\])?\\{pdfmanagement-testphase\\}' \"$input_file\"; then\n log_detail \"PDF/A package already present, skipping injection\"\n cp \"$input_file\" \"$output_file\"\n return\n fi\n\n # Find the \\documentclass line and inject \\usepackage{pdfx} right after it\n # pdfx must be loaded very early (before hyperref, before most other packages)\n if grep -q '\\\\documentclass' \"$input_file\"; then\n local docclass_line\n docclass_line=$(grep -n '\\\\documentclass' \"$input_file\" | head -1 | cut -d: -f1)\n awk -v line=\"$docclass_line\" 'NR==line {print; print \"\\\\usepackage[a-2b]{pdfx} % Auto-injected for PDF/A compliance\"; next} {print}' \"$input_file\" > \"$output_file\"\n log_info \"Injected \\\\usepackage[a-2b]{pdfx} for PDF/A output\"\n else\n cp \"$input_file\" \"$output_file\"\n fi\n}\n\n# --- latexmk compilation backend ---\ncompile_with_latexmk() {\n local engine=\"$1\"\n local texfile=\"$2\"\n\n # Determine latexmk engine flag\n local lmk_flag\n case \"$engine\" in\n pdflatex) lmk_flag=\"-pdf\" ;;\n xelatex) lmk_flag=\"-xelatex\" ;;\n lualatex) lmk_flag=\"-lualatex\" ;;\n *) lmk_flag=\"-pdf\" ;;\n esac\n\n log_info \"Using latexmk (${engine}) for automatic multi-pass compilation...\"\n\n local latexmk_exit=0\n if [[ \"$VERBOSE\" == true ]]; then\n latexmk \"$lmk_flag\" -interaction=nonstopmode \"$texfile\" >&2 || latexmk_exit=$?\n elif [[ \"$QUIET\" == true ]]; then\n latexmk \"$lmk_flag\" -interaction=nonstopmode -quiet \"$texfile\" >/dev/null 2>&1 || latexmk_exit=$?\n elif command -v texfot &>/dev/null; then\n texfot latexmk \"$lmk_flag\" -interaction=nonstopmode \"$texfile\" >&2 2>/dev/null || latexmk_exit=$?\n else\n latexmk \"$lmk_flag\" -interaction=nonstopmode -quiet \"$texfile\" >/dev/null 2>&1 || latexmk_exit=$?\n fi\n\n return $latexmk_exit\n}\n\n# --- Compile ---\nensure_texlive\n\nLATEX_ENGINE=$(detect_engine)\nlog_info \"Compiling ${INPUT_TEX} with ${LATEX_ENGINE}...\"\ncd \"$INPUT_DIR\"\n\n# --- Auto-fix / PDF/A workflow: create temp copy if needed ---\nWORKING_TEX=\"$INPUT_TEX\"\nTEMP_TEX=\"\"\nTEMP_DIR=\"\"\nif [[ \"$AUTO_FIX\" == true || \"$PDFA\" == true ]]; then\n if [[ \"$AUTO_FIX\" == true ]]; then\n log_info \"Auto-fix enabled - creating temporary working copy...\"\n fi\n if [[ \"$PDFA\" == true ]]; then\n log_info \"PDF/A mode enabled\"\n fi\n TEMP_DIR=$(mktemp -d)\n TEMP_TEX=\"${TEMP_DIR}/${INPUT_BASE}.tex\"\n\n # Copy all files from input directory to temp dir (for .bib, images, etc.)\n cp -a \"${INPUT_DIR}/\"* \"$TEMP_DIR/\" 2>/dev/null || true\n\n if [[ \"$AUTO_FIX\" == true ]]; then\n # Stage 1: Fix naked floats\n log_info \"Stage 1: Checking for naked floats...\"\n auto_fix_floats \"$INPUT_TEX\" \"$TEMP_TEX\"\n else\n cp \"$INPUT_TEX\" \"$TEMP_TEX\"\n fi\n\n # Inject PDF/A package if requested\n if [[ \"$PDFA\" == true ]]; then\n local_pdfa_tmp=\"${TEMP_DIR}/${INPUT_BASE}_pdfa.tex\"\n pdfa_inject \"$TEMP_TEX\" \"$local_pdfa_tmp\"\n mv \"$local_pdfa_tmp\" \"$TEMP_TEX\"\n fi\n\n WORKING_TEX=\"$TEMP_TEX\"\n # Change to temp dir for compilation\n cd \"$TEMP_DIR\"\nfi\n\nBIB_ENGINE=$(detect_bibliography)\nNEEDS_INDEX=false\nNEEDS_GLOSSARY=false\nif detect_makeindex; then\n NEEDS_INDEX=true\nfi\nif detect_glossary; then\n NEEDS_GLOSSARY=true\nfi\n\nif [[ \"$LATEX_ENGINE\" != \"pdflatex\" ]]; then\n log_info \"Using engine: $LATEX_ENGINE\"\nfi\nif [[ \"$BIB_ENGINE\" != \"none\" ]]; then\n log_info \"Detected bibliography ($BIB_ENGINE) -- will run bibliography pass\"\nfi\nif [[ \"$NEEDS_INDEX\" == true ]]; then\n log_info \"Detected index -- will run makeindex\"\nfi\nif [[ \"$NEEDS_GLOSSARY\" == true ]]; then\n log_info \"Detected glossary -- will run makeglossaries\"\nfi\nif command -v texfot &>/dev/null && [[ \"$VERBOSE\" != true && \"$QUIET\" != true ]]; then\n log_detail \"texfot available -- using filtered log output\"\nfi\n\n# Determine log file location (depends on auto-fix/pdfa mode)\nif [[ -n \"$TEMP_DIR\" ]]; then\n LOG_FILE=\"${TEMP_DIR}/${INPUT_BASE}.log\"\nelse\n LOG_FILE=\"${INPUT_DIR}/${INPUT_BASE}.log\"\nfi\n\n# Check for PDF in correct location (temp dir for auto-fix/pdfa, input dir otherwise)\nACTUAL_PDF=\"$PDF_FILE\"\nif [[ -n \"$TEMP_DIR\" ]]; then\n ACTUAL_PDF=\"${TEMP_DIR}/${INPUT_BASE}.pdf\"\nfi\n\n# =================================================================\n# COMPILATION: latexmk branch vs manual multi-pass branch\n# =================================================================\nif [[ \"$USE_LATEXMK\" == true ]]; then\n # --- latexmk backend ---\n if ! command -v latexmk &>/dev/null; then\n echo \"Error: latexmk not found. Install with: sudo apt-get install latexmk\" >&2\n echo \"Or remove --use-latexmk to use the built-in multi-pass engine.\" >&2\n [[ -n \"$TEMP_DIR\" ]] && rm -rf \"$TEMP_DIR\"\n exit 1\n fi\n\n LATEXMK_EXIT=0\n compile_with_latexmk \"$LATEX_ENGINE\" \"$WORKING_TEX\" || LATEXMK_EXIT=$?\n\n if [[ $LATEXMK_EXIT -ne 0 && ! -f \"$ACTUAL_PDF\" ]]; then\n echo \"Error: latexmk compilation failed - no PDF produced\" >&2\n parse_errors \"$LOG_FILE\"\n [[ -n \"$TEMP_DIR\" ]] && rm -rf \"$TEMP_DIR\"\n exit 1\n fi\n if [[ $LATEXMK_EXIT -ne 0 && -f \"$ACTUAL_PDF\" ]]; then\n log_info \"latexmk had warnings (PDF still produced)\"\n fi\n\nelse\n # --- Manual multi-pass backend (original logic) ---\n\n # First pass\n FIRST_PASS_EXIT=0\n run_engine \"$LATEX_ENGINE\" \"$WORKING_TEX\" || FIRST_PASS_EXIT=$?\n\n if [[ $FIRST_PASS_EXIT -ne 0 && ! -f \"$ACTUAL_PDF\" ]]; then\n log_info \"First pass failed. Running diagnostic pass...\"\n \"$LATEX_ENGINE\" -interaction=nonstopmode \"$WORKING_TEX\" 2>&1 | tail -50 >&2\n if [[ ! -f \"$ACTUAL_PDF\" ]]; then\n echo \"Error: Compilation failed - no PDF produced\" >&2\n parse_errors \"$LOG_FILE\"\n [[ -n \"$TEMP_DIR\" ]] && rm -rf \"$TEMP_DIR\"\n exit 1\n fi\n fi\n if [[ $FIRST_PASS_EXIT -ne 0 && -f \"$ACTUAL_PDF\" ]]; then\n log_info \"First pass had warnings (PDF still produced)\"\n fi\n\n # Auto-fix Stage 2: Check for overfull hbox and inject microtype if needed\n if [[ \"$AUTO_FIX\" == true && -f \"$LOG_FILE\" ]]; then\n OVERFULL_COUNT=$(grep -c \"Overfull \\\\\\\\hbox\" \"$LOG_FILE\" 2>/dev/null || true)\n OVERFULL_COUNT=${OVERFULL_COUNT:-0}\n if [[ \"$OVERFULL_COUNT\" -gt 0 ]]; then\n log_info \"Stage 2: Detected $OVERFULL_COUNT overfull hbox warnings\"\n TEMP_TEX2=\"${TEMP_DIR}/${INPUT_BASE}_microtype.tex\"\n auto_inject_microtype \"$TEMP_TEX\" \"$TEMP_TEX2\"\n WORKING_TEX=\"$TEMP_TEX2\"\n\n log_info \"Recompiling with microtype...\"\n run_engine \"$LATEX_ENGINE\" \"$WORKING_TEX\" || true\n fi\n fi\n\n # Run bibliography engine if needed\n if [[ \"$BIB_ENGINE\" == \"bibtex\" ]]; then\n log_info \"Running bibtex...\"\n bibtex \"$INPUT_BASE\" >/dev/null 2>&1 || {\n log_info \"bibtex had warnings (this is often normal for first run)\"\n }\n elif [[ \"$BIB_ENGINE\" == \"biber\" ]]; then\n log_info \"Running biber...\"\n biber \"$INPUT_BASE\" >/dev/null 2>&1 || {\n log_info \"biber had warnings\"\n }\n fi\n\n # Run makeindex if needed\n if [[ \"$NEEDS_INDEX\" == true ]]; then\n log_info \"Running makeindex...\"\n makeindex \"$INPUT_BASE\" >/dev/null 2>&1 || {\n log_info \"makeindex had warnings\"\n }\n fi\n\n # Run makeglossaries if needed\n if [[ \"$NEEDS_GLOSSARY\" == true ]]; then\n log_info \"Running makeglossaries...\"\n makeglossaries \"$INPUT_BASE\" >/dev/null 2>&1 || {\n log_info \"makeglossaries had warnings (ensure glossaries package is installed)\"\n }\n fi\n\n # Second pass (resolves references after bibtex/biber/makeindex/glossaries)\n run_engine \"$LATEX_ENGINE\" \"$WORKING_TEX\" || true\n\n # Third pass if bibliography, index, or glossary was used (final cross-ref resolution)\n if [[ \"$BIB_ENGINE\" != \"none\" || \"$NEEDS_INDEX\" == true || \"$NEEDS_GLOSSARY\" == true ]]; then\n log_info \"Running final pass for cross-references...\"\n run_engine \"$LATEX_ENGINE\" \"$WORKING_TEX\" || true\n fi\n\nfi\n\n# Handle PDF location based on temp dir mode (auto-fix or pdfa)\nif [[ -n \"$TEMP_DIR\" ]]; then\n TEMP_PDF=\"${TEMP_DIR}/${INPUT_BASE}.pdf\"\n if [[ ! -f \"$TEMP_PDF\" ]]; then\n echo \"Error: PDF not produced\" >&2\n parse_errors \"$LOG_FILE\"\n rm -rf \"$TEMP_DIR\"\n exit 1\n fi\n # Copy PDF back to original location\n cp \"$TEMP_PDF\" \"$PDF_FILE\"\n log_info \"PDF created: ${PDF_FILE}\"\n if [[ \"$AUTO_FIX\" == true ]]; then\n log_detail \"(compiled from auto-fixed temporary copy)\"\n fi\n if [[ \"$PDFA\" == true ]]; then\n log_detail \"(PDF/A-2b compliant)\"\n fi\nelse\n if [[ ! -f \"$PDF_FILE\" ]]; then\n echo \"Error: PDF not produced\" >&2\n parse_errors \"$LOG_FILE\"\n exit 1\n fi\n log_info \"PDF created: ${PDF_FILE}\"\nfi\n\n# Run error analysis on successful compilation (for warnings/suggestions)\nif [[ -f \"$LOG_FILE\" && \"$QUIET\" != true ]]; then\n parse_errors \"$LOG_FILE\"\nfi\n\n# --- Generate PNG previews ---\nif [[ \"$PREVIEW\" == true ]]; then\n ensure_poppler\n mkdir -p \"$PREVIEW_DIR\"\n\n PREVIEW_BASE=\"${PREVIEW_DIR}/${INPUT_BASE}\"\n pdftoppm \"$PDF_FILE\" \"$PREVIEW_BASE\" -png -scale-to \"$SCALE\"\n\n # List generated PNGs\n PNG_COUNT=$(ls \"${PREVIEW_BASE}\"*.png 2>/dev/null | wc -l)\n log_info \"Generated ${PNG_COUNT} PNG preview(s) in ${PREVIEW_DIR}/\"\n if [[ \"$QUIET\" != true ]]; then\n ls \"${PREVIEW_BASE}\"*.png 2>/dev/null\n fi\nfi\n\n# --- Clean auxiliary files ---\ncd \"$INPUT_DIR\"\nrm -f \"${INPUT_BASE}.aux\" \"${INPUT_BASE}.log\" \"${INPUT_BASE}.out\" \\\n \"${INPUT_BASE}.toc\" \"${INPUT_BASE}.lof\" \"${INPUT_BASE}.lot\" \\\n \"${INPUT_BASE}.nav\" \"${INPUT_BASE}.snm\" \"${INPUT_BASE}.vrb\" \\\n \"${INPUT_BASE}.bbl\" \"${INPUT_BASE}.blg\" \\\n \"${INPUT_BASE}.idx\" \"${INPUT_BASE}.ilg\" \"${INPUT_BASE}.ind\" \\\n \"${INPUT_BASE}.bcf\" \"${INPUT_BASE}.run.xml\" \\\n \"${INPUT_BASE}.glo\" \"${INPUT_BASE}.gls\" \"${INPUT_BASE}.glg\" \\\n \"${INPUT_BASE}.ist\" \"${INPUT_BASE}.acn\" \"${INPUT_BASE}.acr\" \\\n \"${INPUT_BASE}.alg\" \"${INPUT_BASE}.fls\" \"${INPUT_BASE}.fdb_latexmk\" \\\n \"${INPUT_BASE}.synctex.gz\" 2>/dev/null || true\n\n# Clean up temp directory if auto-fix was used\nif [[ -n \"$TEMP_DIR\" && -d \"$TEMP_DIR\" ]]; then\n rm -rf \"$TEMP_DIR\"\nfi\n\nlog_info \"Done.\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":26298,"content_sha256":"12852172497d50ecfcfc9e94d1a01b58c9bbcc57f893deb6ffe07af1d9402942"},{"filename":"scripts/convert_document.sh","content":"#!/usr/bin/env bash\n\n# convert_document.sh - Document format conversion wrapper for Pandoc\n#\n# DESCRIPTION:\n# Converts between various document formats using Pandoc.\n# Auto-detects conversion direction from file extensions.\n#\n# SUPPORTED CONVERSIONS:\n# .md → .tex, .docx, .html, .pdf\n# .tex → .md, .docx, .html, .pdf\n# .docx → .tex, .md, .html, .pdf\n# .html → .tex, .md, .docx, .pdf\n#\n# USAGE:\n# convert_document.sh INPUT OUTPUT [OPTIONS]\n#\n# EXAMPLES:\n# # Markdown to LaTeX\n# convert_document.sh report.md report.tex --standalone --toc\n#\n# # LaTeX to PDF with bibliography\n# convert_document.sh paper.tex paper.pdf --bibliography refs.bib --csl ieee.csl\n#\n# # DOCX to LaTeX with custom template\n# convert_document.sh manuscript.docx manuscript.tex --template custom.latex\n#\n# # LaTeX to Markdown (for editing)\n# convert_document.sh document.tex document.md\n#\n# # HTML to LaTeX\n# convert_document.sh webpage.html output.tex --standalone\n#\n# OPTIONS:\n# --template PATH Custom Pandoc template file\n# --bibliography PATH BibTeX (.bib) file for citations\n# --csl PATH Citation Style Language file\n# --toc Include table of contents\n# --standalone Produce standalone document (default for most)\n# --no-standalone Disable standalone mode\n# --help Show this help message\n\nset -euo pipefail\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Colors for output\nRED='\\033[0;31m'\nGREEN='\\033[0;32m'\nYELLOW='\\033[1;33m'\nBLUE='\\033[0;34m'\nNC='\\033[0m' # No Color\n\n# Function to print colored messages\ninfo() {\n echo -e \"${BLUE}[INFO]${NC} $1\"\n}\n\nsuccess() {\n echo -e \"${GREEN}[SUCCESS]${NC} $1\"\n}\n\nwarn() {\n echo -e \"${YELLOW}[WARN]${NC} $1\"\n}\n\nerror() {\n echo -e \"${RED}[ERROR]${NC} $1\" >&2\n}\n\n# Function to show help\nshow_help() {\n sed -n '/^# convert_document.sh/,/^$/p' \"$0\" | sed 's/^# \\?//'\n exit 0\n}\n\n# Function to check if pandoc is installed\ncheck_pandoc() {\n if command -v pandoc >/dev/null 2>&1; then\n local version=$(pandoc --version | head -n1)\n info \"Pandoc found: $version\"\n return 0\n else\n warn \"Pandoc not found. Attempting to install...\"\n install_packages \"pandoc\" || {\n error \"Unable to auto-install pandoc. Please install manually:\"\n error \" Ubuntu/Debian: sudo apt-get install pandoc\"\n error \" macOS: brew install pandoc\"\n error \" Fedora/RHEL: sudo dnf install pandoc\"\n error \" Alpine: sudo apk add pandoc\"\n error \" Arch: sudo pacman -S pandoc\"\n error \" Or download from: https://pandoc.org/installing.html\"\n exit 1\n }\n\n if command -v pandoc >/dev/null 2>&1; then\n success \"Pandoc installed successfully\"\n else\n error \"Pandoc installation failed\"\n print_install_help \"pandoc\"\n exit 1\n fi\n fi\n}\n\n# Function to get file extension\nget_extension() {\n echo \"${1##*.}\" | tr '[:upper:]' '[:lower:]'\n}\n\n# Function to get base filename without extension\nget_basename() {\n local filename=$(basename \"$1\")\n echo \"${filename%.*}\"\n}\n\n# Parse arguments\nif [[ $# -lt 2 ]]; then\n error \"Insufficient arguments\"\n echo \"\"\n show_help\nfi\n\nINPUT_FILE=\"$1\"\nOUTPUT_FILE=\"$2\"\nshift 2\n\n# Check if input file exists\nif [[ ! -f \"$INPUT_FILE\" ]]; then\n error \"Input file not found: $INPUT_FILE\"\n exit 1\nfi\n\n# Parse options\nTEMPLATE=\"\"\nBIBLIOGRAPHY=\"\"\nCSL=\"\"\nTOC=false\nSTANDALONE=\"auto\"\nEXTRA_ARGS=()\n\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --template)\n TEMPLATE=\"$2\"\n if [[ ! -f \"$TEMPLATE\" ]]; then\n error \"Template file not found: $TEMPLATE\"\n exit 1\n fi\n shift 2\n ;;\n --bibliography)\n BIBLIOGRAPHY=\"$2\"\n if [[ ! -f \"$BIBLIOGRAPHY\" ]]; then\n error \"Bibliography file not found: $BIBLIOGRAPHY\"\n exit 1\n fi\n shift 2\n ;;\n --csl)\n CSL=\"$2\"\n if [[ ! -f \"$CSL\" ]]; then\n error \"CSL file not found: $CSL\"\n exit 1\n fi\n shift 2\n ;;\n --toc)\n TOC=true\n shift\n ;;\n --standalone)\n STANDALONE=\"yes\"\n shift\n ;;\n --no-standalone)\n STANDALONE=\"no\"\n shift\n ;;\n --help)\n show_help\n ;;\n *)\n EXTRA_ARGS+=(\"$1\")\n shift\n ;;\n esac\ndone\n\n# Check pandoc installation\ncheck_pandoc\n\n# Get file extensions\nINPUT_EXT=$(get_extension \"$INPUT_FILE\")\nOUTPUT_EXT=$(get_extension \"$OUTPUT_FILE\")\n\ninfo \"Converting: $INPUT_FILE ($INPUT_EXT) → $OUTPUT_FILE ($OUTPUT_EXT)\"\n\n# Build pandoc command\nPANDOC_CMD=(pandoc \"$INPUT_FILE\" -o \"$OUTPUT_FILE\")\n\n# Determine if standalone should be used\nif [[ \"$STANDALONE\" == \"auto\" ]]; then\n # Default to standalone for most conversions, except when creating fragments\n if [[ \"$OUTPUT_EXT\" == \"tex\" || \"$OUTPUT_EXT\" == \"html\" || \"$OUTPUT_EXT\" == \"docx\" || \"$OUTPUT_EXT\" == \"pdf\" ]]; then\n PANDOC_CMD+=(--standalone)\n fi\nelif [[ \"$STANDALONE\" == \"yes\" ]]; then\n PANDOC_CMD+=(--standalone)\nfi\n\n# Add table of contents\nif [[ \"$TOC\" == true ]]; then\n PANDOC_CMD+=(--toc)\n info \"Including table of contents\"\nfi\n\n# Add template\nif [[ -n \"$TEMPLATE\" ]]; then\n PANDOC_CMD+=(--template=\"$TEMPLATE\")\n info \"Using template: $TEMPLATE\"\nfi\n\n# Add bibliography\nif [[ -n \"$BIBLIOGRAPHY\" ]]; then\n PANDOC_CMD+=(--bibliography=\"$BIBLIOGRAPHY\")\n info \"Using bibliography: $BIBLIOGRAPHY\"\nfi\n\n# Add CSL\nif [[ -n \"$CSL\" ]]; then\n PANDOC_CMD+=(--csl=\"$CSL\")\n info \"Using citation style: $CSL\"\nfi\n\n# Add format-specific options\ncase \"$INPUT_EXT\" in\n tex)\n PANDOC_CMD+=(--from=latex)\n ;;\n md|markdown)\n PANDOC_CMD+=(--from=markdown)\n ;;\n docx)\n PANDOC_CMD+=(--from=docx)\n ;;\n html|htm)\n PANDOC_CMD+=(--from=html)\n ;;\nesac\n\ncase \"$OUTPUT_EXT\" in\n tex)\n PANDOC_CMD+=(--to=latex)\n ;;\n md|markdown)\n PANDOC_CMD+=(--to=markdown)\n ;;\n docx)\n PANDOC_CMD+=(--to=docx)\n ;;\n html|htm)\n PANDOC_CMD+=(--to=html)\n # Add MathJax for math rendering in HTML\n PANDOC_CMD+=(--mathjax)\n ;;\n pdf)\n PANDOC_CMD+=(--to=pdf)\n # Use lualatex if available for better Unicode support\n if command -v lualatex >/dev/null 2>&1; then\n PANDOC_CMD+=(--pdf-engine=lualatex)\n elif command -v pdflatex >/dev/null 2>&1; then\n PANDOC_CMD+=(--pdf-engine=pdflatex)\n fi\n ;;\n *)\n warn \"Unknown output format: $OUTPUT_EXT\"\n warn \"Pandoc will attempt auto-detection\"\n ;;\nesac\n\n# Add any extra arguments\nif [[ ${#EXTRA_ARGS[@]} -gt 0 ]]; then\n PANDOC_CMD+=(\"${EXTRA_ARGS[@]}\")\nfi\n\n# Print command for debugging\ninfo \"Running: ${PANDOC_CMD[*]}\"\n\n# Execute conversion\nif \"${PANDOC_CMD[@]}\"; then\n success \"Conversion completed successfully\"\n\n # Get absolute path of output file\n OUTPUT_ABS=$(realpath \"$OUTPUT_FILE\")\n\n # Print file info\n if [[ -f \"$OUTPUT_FILE\" ]]; then\n FILE_SIZE=$(du -h \"$OUTPUT_FILE\" | cut -f1)\n success \"Output file: $OUTPUT_ABS\"\n info \"File size: $FILE_SIZE\"\n fi\n\n exit 0\nelse\n error \"Conversion failed\"\n echo \"\"\n error \"Troubleshooting tips:\"\n error \" 1. Check that input file is valid ${INPUT_EXT} format\"\n error \" 2. For PDF output, ensure LaTeX is installed (texlive-full)\"\n error \" 3. For bibliography, ensure .bib file syntax is correct\"\n error \" 4. Try adding --verbose flag for more details\"\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":7979,"content_sha256":"725d049dc2c50072283ac129b1447af91845fe4bee63cd58705be22f2f20d789"},{"filename":"scripts/csv_to_latex.py","content":"#!/usr/bin/env python3\n\"\"\"\ncsv_to_latex.py\nConverts CSV files to formatted LaTeX tabular code.\n\nExamples:\n # Basic booktabs table with caption\n ./csv_to_latex.py data.csv --caption \"Sales Data\" --label \"tab:sales\"\n\n # Simple grid table with alternating row colors\n ./csv_to_latex.py data.csv --style grid --alternating-rows\n\n # Save to file with custom alignment\n ./csv_to_latex.py data.csv --align \"lccr\" --output table.tex\n\n # Truncate large tables\n ./csv_to_latex.py large_data.csv --max-rows 20 --caption \"Truncated Results\"\n\"\"\"\n\nimport argparse\nimport subprocess\nimport sys\nfrom pathlib import Path\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n # PEP 668: retry with --break-system-packages for externally-managed envs\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"pandas\")\n\nimport pandas as pd\n\ndef escape_latex(text):\n \"\"\"Escape special LaTeX characters in text.\"\"\"\n if pd.isna(text):\n return \"\"\n\n text = str(text)\n\n # Escape special characters\n replacements = {\n '\\\\': r'\\textbackslash{}',\n '&': r'\\&',\n '%': r'\\%',\n '

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

: r'\\

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

,\n '#': r'\\#',\n '_': r'\\_',\n '{': r'\\{',\n '}': r'\\}',\n '~': r'\\textasciitilde{}',\n '^': r'\\textasciicircum{}',\n }\n\n for char, replacement in replacements.items():\n text = text.replace(char, replacement)\n\n return text\n\ndef detect_alignment(df):\n \"\"\"Auto-detect column alignment based on data types.\"\"\"\n alignment = \"\"\n for col in df.columns:\n dtype = df[col].dtype\n if pd.api.types.is_numeric_dtype(dtype):\n alignment += \"r\" # Right-align numbers\n else:\n alignment += \"l\" # Left-align text\n return alignment\n\ndef generate_booktabs_table(df, caption, label, align, highlight_header, alternating_rows):\n \"\"\"Generate a table using booktabs package (professional style).\"\"\"\n lines = []\n\n # Table environment\n lines.append(r\"\\begin{table}[htbp]\")\n lines.append(r\" \\centering\")\n\n if caption:\n lines.append(f\" \\\\caption{{{escape_latex(caption)}}}\")\n if label:\n lines.append(f\" \\\\label{{{label}}}\")\n\n # Tabular environment\n lines.append(f\" \\\\begin{{tabular}}{{{align}}}\")\n lines.append(r\" \\toprule\")\n\n # Header row\n headers = [escape_latex(col) for col in df.columns]\n if highlight_header:\n headers = [f\"\\\\textbf{{{h}}}\" for h in headers]\n lines.append(\" \" + \" & \".join(headers) + r\" \\\\\")\n lines.append(r\" \\midrule\")\n\n # Data rows\n for idx, row in df.iterrows():\n escaped_row = [escape_latex(val) for val in row]\n row_str = \" & \".join(escaped_row) + r\" \\\\\"\n\n if alternating_rows and idx % 2 == 1:\n lines.append(f\" \\\\rowcolor{{gray!10}} {row_str}\")\n else:\n lines.append(f\" {row_str}\")\n\n lines.append(r\" \\bottomrule\")\n lines.append(r\" \\end{tabular}\")\n lines.append(r\"\\end{table}\")\n\n return \"\\n\".join(lines)\n\ndef generate_grid_table(df, caption, label, align, highlight_header, alternating_rows):\n \"\"\"Generate a table with full grid lines.\"\"\"\n lines = []\n\n # Table environment\n lines.append(r\"\\begin{table}[htbp]\")\n lines.append(r\" \\centering\")\n\n if caption:\n lines.append(f\" \\\\caption{{{escape_latex(caption)}}}\")\n if label:\n lines.append(f\" \\\\label{{{label}}}\")\n\n # Tabular environment with vertical lines\n align_with_lines = \"|\" + \"|\".join(list(align)) + \"|\"\n lines.append(f\" \\\\begin{{tabular}}{{{align_with_lines}}}\")\n lines.append(r\" \\hline\")\n\n # Header row\n headers = [escape_latex(col) for col in df.columns]\n if highlight_header:\n headers = [f\"\\\\textbf{{{h}}}\" for h in headers]\n lines.append(\" \" + \" & \".join(headers) + r\" \\\\\")\n lines.append(r\" \\hline\")\n\n # Data rows\n for idx, row in df.iterrows():\n escaped_row = [escape_latex(val) for val in row]\n row_str = \" & \".join(escaped_row) + r\" \\\\\"\n\n if alternating_rows and idx % 2 == 1:\n lines.append(f\" \\\\rowcolor{{gray!10}} {row_str}\")\n else:\n lines.append(f\" {row_str}\")\n lines.append(r\" \\hline\")\n\n lines.append(r\" \\end{tabular}\")\n lines.append(r\"\\end{table}\")\n\n return \"\\n\".join(lines)\n\ndef generate_simple_table(df, caption, label, align, highlight_header, alternating_rows):\n \"\"\"Generate a simple table with minimal lines.\"\"\"\n lines = []\n\n # Table environment\n lines.append(r\"\\begin{table}[htbp]\")\n lines.append(r\" \\centering\")\n\n if caption:\n lines.append(f\" \\\\caption{{{escape_latex(caption)}}}\")\n if label:\n lines.append(f\" \\\\label{{{label}}}\")\n\n # Tabular environment\n lines.append(f\" \\\\begin{{tabular}}{{{align}}}\")\n lines.append(r\" \\hline\")\n\n # Header row\n headers = [escape_latex(col) for col in df.columns]\n if highlight_header:\n headers = [f\"\\\\textbf{{{h}}}\" for h in headers]\n lines.append(\" \" + \" & \".join(headers) + r\" \\\\\")\n lines.append(r\" \\hline\")\n\n # Data rows\n for idx, row in df.iterrows():\n escaped_row = [escape_latex(val) for val in row]\n row_str = \" & \".join(escaped_row) + r\" \\\\\"\n\n if alternating_rows and idx % 2 == 1:\n lines.append(f\" \\\\rowcolor{{gray!10}} {row_str}\")\n else:\n lines.append(f\" {row_str}\")\n\n lines.append(r\" \\hline\")\n lines.append(r\" \\end{tabular}\")\n lines.append(r\"\\end{table}\")\n\n return \"\\n\".join(lines)\n\ndef generate_plain_table(df, caption, label, align, highlight_header, alternating_rows):\n \"\"\"Generate a plain table with no lines.\"\"\"\n lines = []\n\n # Table environment\n lines.append(r\"\\begin{table}[htbp]\")\n lines.append(r\" \\centering\")\n\n if caption:\n lines.append(f\" \\\\caption{{{escape_latex(caption)}}}\")\n if label:\n lines.append(f\" \\\\label{{{label}}}\")\n\n # Tabular environment\n lines.append(f\" \\\\begin{{tabular}}{{{align}}}\")\n\n # Header row\n headers = [escape_latex(col) for col in df.columns]\n if highlight_header:\n headers = [f\"\\\\textbf{{{h}}}\" for h in headers]\n lines.append(\" \" + \" & \".join(headers) + r\" \\\\[0.5ex]\")\n\n # Data rows\n for idx, row in df.iterrows():\n escaped_row = [escape_latex(val) for val in row]\n row_str = \" & \".join(escaped_row) + r\" \\\\\"\n\n if alternating_rows and idx % 2 == 1:\n lines.append(f\" \\\\rowcolor{{gray!10}} {row_str}\")\n else:\n lines.append(f\" {row_str}\")\n\n lines.append(r\" \\end{tabular}\")\n lines.append(r\"\\end{table}\")\n\n return \"\\n\".join(lines)\n\nSTYLE_GENERATORS = {\n 'booktabs': generate_booktabs_table,\n 'grid': generate_grid_table,\n 'simple': generate_simple_table,\n 'plain': generate_plain_table,\n}\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description='Convert CSV files to formatted LaTeX tabular code',\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=__doc__\n )\n\n parser.add_argument('csv_file', type=str,\n help='Path to CSV file')\n parser.add_argument('--style', type=str, default='booktabs',\n choices=STYLE_GENERATORS.keys(),\n help='Table style (default: booktabs)')\n parser.add_argument('--caption', type=str, default='',\n help='Table caption text')\n parser.add_argument('--label', type=str, default='',\n help='Table label for cross-referencing (e.g., tab:results)')\n parser.add_argument('--align', type=str, default=None,\n help='Column alignment string (e.g., \"lcr\") or auto-detect')\n parser.add_argument('--no-highlight-header', dest='highlight_header',\n action='store_false',\n help='Disable bold headers (enabled by default)')\n parser.set_defaults(highlight_header=True)\n parser.add_argument('--alternating-rows', action='store_true',\n help='Use alternating row colors (requires xcolor package)')\n parser.add_argument('--max-rows', type=int, default=None,\n help='Maximum number of rows (truncate with \"...\" row)')\n parser.add_argument('--output', type=str, default=None,\n help='Output file path (default: stdout)')\n\n return parser.parse_args()\n\ndef main():\n args = parse_args()\n\n # Read CSV file\n try:\n csv_path = Path(args.csv_file)\n if not csv_path.exists():\n print(f\"Error: CSV file not found: {args.csv_file}\", file=sys.stderr)\n sys.exit(1)\n\n df = pd.read_csv(args.csv_file)\n\n if df.empty:\n print(\"Error: CSV file is empty\", file=sys.stderr)\n sys.exit(1)\n\n except Exception as e:\n print(f\"Error: Failed to read CSV file: {e}\", file=sys.stderr)\n sys.exit(1)\n\n # Truncate if max_rows specified\n if args.max_rows and len(df) > args.max_rows:\n df = df.head(args.max_rows)\n # Add truncation row\n truncation_row = pd.DataFrame([[\"...\" for _ in df.columns]], columns=df.columns)\n df = pd.concat([df, truncation_row], ignore_index=True)\n\n # Determine column alignment\n if args.align:\n if len(args.align) != len(df.columns):\n print(f\"Error: Alignment string length ({len(args.align)}) must match number of columns ({len(df.columns)})\", file=sys.stderr)\n sys.exit(1)\n align = args.align\n else:\n align = detect_alignment(df)\n\n # Generate table\n try:\n generator = STYLE_GENERATORS[args.style]\n latex_code = generator(\n df,\n args.caption,\n args.label,\n align,\n args.highlight_header,\n args.alternating_rows\n )\n except Exception as e:\n print(f\"Error: Failed to generate LaTeX table: {e}\", file=sys.stderr)\n sys.exit(1)\n\n # Add package requirements comment\n preamble = []\n preamble.append(\"% Required LaTeX packages:\")\n if args.style == 'booktabs':\n preamble.append(\"% \\\\usepackage{booktabs}\")\n if args.alternating_rows:\n preamble.append(\"% \\\\usepackage[table]{xcolor}\")\n preamble.append(\"\")\n\n output = \"\\n\".join(preamble) + latex_code\n\n # Write output\n if args.output:\n try:\n output_path = Path(args.output)\n output_path.parent.mkdir(parents=True, exist_ok=True)\n output_path.write_text(output)\n print(f\"Successfully created: {args.output}\", file=sys.stderr)\n except Exception as e:\n print(f\"Error: Failed to write output file: {e}\", file=sys.stderr)\n sys.exit(1)\n else:\n print(output)\n\nif __name__ == '__main__':\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":11935,"content_sha256":"4b7f90f6c3a00c34edcbd95155c2a0b6fcf1c3b77f30db9eead70bf322ef392e"},{"filename":"scripts/fetch_bibtex.sh","content":"#!/usr/bin/env bash\n\n# fetch_bibtex.sh\n# Auto-download BibTeX entries from DOIs or arXiv IDs\n#\n# Examples:\n# ./fetch_bibtex.sh 10.1038/nature12373\n# ./fetch_bibtex.sh 2301.07041 --output references.bib\n# ./fetch_bibtex.sh 10.1145/3290605.3300608 1906.08237 --append --output refs.bib\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n\n# Default values\nOUTPUT_FILE=\"\"\nAPPEND_MODE=false\nIDENTIFIERS=()\n\n# ANSI color codes\nGREEN='\\033[0;32m'\nYELLOW='\\033[1;33m'\nRED='\\033[0;31m'\nNC='\\033[0m' # No Color\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cDOI_or_arXiv_ID> [\u003cDOI_or_arXiv_ID> ...] [OPTIONS]\n\nAuto-download BibTeX entries from DOIs or arXiv IDs.\n\nArguments:\n DOI_or_arXiv_ID One or more DOIs (e.g., 10.1038/nature12373) or\n arXiv IDs (e.g., 2301.07041 or arXiv:2301.07041)\n\nOptions:\n --output \u003cfile> Output .bib file (default: stdout)\n --append Append to existing .bib file instead of overwriting\n -h, --help Show this help message\n\nExamples:\n $0 10.1038/nature12373\n $0 2301.07041 --output references.bib\n $0 10.1145/3290605.3300608 1906.08237 --append --output refs.bib\n\nRequires: curl (usually pre-installed)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n --append)\n APPEND_MODE=true\n shift\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n IDENTIFIERS+=(\"$1\")\n shift\n ;;\n esac\ndone\n\n# Validate we have at least one identifier\nif [[ ${#IDENTIFIERS[@]} -eq 0 ]]; then\n echo \"Error: No DOI or arXiv ID specified\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\n# Check for curl\nif ! command -v curl &>/dev/null; then\n echo \"Error: curl not found. Please install curl:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install curl\" >&2\n echo \" macOS: brew install curl\" >&2\n echo \" Fedora/RHEL: sudo dnf install curl\" >&2\n echo \" Alpine: sudo apk add curl\" >&2\n echo \" Arch: sudo pacman -S curl\" >&2\n exit 1\nfi\n\n# Function to detect if identifier is DOI or arXiv\ndetect_type() {\n local id=\"$1\"\n\n # Strip 'arXiv:' prefix if present\n id=\"${id#arXiv:}\"\n id=\"${id#arxiv:}\"\n\n # arXiv pattern: 4 digits, optional dot, 4-5 digits, optional version\n # Examples: 2301.07041, 2301.07041v1, 1906.08237\n if [[ \"$id\" =~ ^[0-9]{4}\\.[0-9]{4,5}(v[0-9]+)?$ ]]; then\n echo \"arxiv\"\n # DOI pattern: starts with 10.\n elif [[ \"$id\" =~ ^10\\. ]]; then\n echo \"doi\"\n else\n echo \"unknown\"\n fi\n}\n\n# Function to fetch BibTeX from DOI\nfetch_doi() {\n local doi=\"$1\"\n\n echo \"Fetching DOI: $doi...\" >&2\n\n local bibtex\n bibtex=$(curl -sL -H \"Accept: application/x-bibtex\" \"https://doi.org/$doi\" 2>&1)\n\n if [[ $? -ne 0 ]] || [[ -z \"$bibtex\" ]]; then\n echo -e \"${RED}Error: Failed to fetch BibTeX for DOI: $doi${NC}\" >&2\n return 1\n fi\n\n # Basic validation: check if it looks like BibTeX\n if ! echo \"$bibtex\" | grep -q '@'; then\n echo -e \"${RED}Error: Invalid BibTeX response for DOI: $doi${NC}\" >&2\n echo \"Response: $bibtex\" >&2\n return 1\n fi\n\n echo \"$bibtex\"\n return 0\n}\n\n# Function to fetch BibTeX from arXiv\nfetch_arxiv() {\n local arxiv_id=\"$1\"\n\n # Strip 'arXiv:' prefix if present\n arxiv_id=\"${arxiv_id#arXiv:}\"\n arxiv_id=\"${arxiv_id#arxiv:}\"\n\n echo \"Fetching arXiv: $arxiv_id...\" >&2\n\n # Use arXiv's native BibTeX endpoint (more reliable than parsing Atom XML)\n local bibtex\n bibtex=$(curl -sL \"https://arxiv.org/bibtex/${arxiv_id}\" 2>&1)\n\n if [[ $? -ne 0 ]] || [[ -z \"$bibtex\" ]]; then\n echo -e \"${RED}Error: Failed to fetch BibTeX for arXiv: $arxiv_id${NC}\" >&2\n return 1\n fi\n\n # Validate: check if response looks like BibTeX\n if ! echo \"$bibtex\" | grep -q '@'; then\n echo -e \"${RED}Error: Invalid BibTeX response for arXiv: $arxiv_id${NC}\" >&2\n echo \"Response: $bibtex\" >&2\n return 1\n fi\n\n echo \"$bibtex\"\n return 0\n}\n\n# Main processing\nALL_BIBTEX=\"\"\nSUCCESS_COUNT=0\nFAILED_COUNT=0\n\nfor identifier in \"${IDENTIFIERS[@]}\"; do\n TYPE=$(detect_type \"$identifier\")\n\n case \"$TYPE\" in\n doi)\n if bibtex_entry=$(fetch_doi \"$identifier\"); then\n ALL_BIBTEX=\"${ALL_BIBTEX}${bibtex_entry}\\n\\n\"\n SUCCESS_COUNT=$((SUCCESS_COUNT + 1))\n else\n FAILED_COUNT=$((FAILED_COUNT + 1))\n fi\n ;;\n arxiv)\n if bibtex_entry=$(fetch_arxiv \"$identifier\"); then\n ALL_BIBTEX=\"${ALL_BIBTEX}${bibtex_entry}\\n\\n\"\n SUCCESS_COUNT=$((SUCCESS_COUNT + 1))\n else\n FAILED_COUNT=$((FAILED_COUNT + 1))\n fi\n ;;\n *)\n echo -e \"${RED}Error: Could not detect type for identifier: $identifier${NC}\" >&2\n echo \"Supported formats: DOI (10.xxxx/...) or arXiv (YYMM.NNNNN)\" >&2\n FAILED_COUNT=$((FAILED_COUNT + 1))\n ;;\n esac\ndone\n\n# Output results\nif [[ $SUCCESS_COUNT -eq 0 ]]; then\n echo -e \"${RED}Error: Failed to fetch any BibTeX entries${NC}\" >&2\n exit 1\nfi\n\nif [[ -z \"$OUTPUT_FILE\" ]]; then\n # Output to stdout\n echo -e \"$ALL_BIBTEX\"\nelse\n # Output to file\n if [[ \"$APPEND_MODE\" == true ]] && [[ -f \"$OUTPUT_FILE\" ]]; then\n echo -e \"\\n$ALL_BIBTEX\" >> \"$OUTPUT_FILE\"\n echo -e \"${GREEN}✓ Appended $SUCCESS_COUNT BibTeX entry(ies) to: $OUTPUT_FILE${NC}\" >&2\n else\n echo -e \"$ALL_BIBTEX\" > \"$OUTPUT_FILE\"\n echo -e \"${GREEN}✓ Wrote $SUCCESS_COUNT BibTeX entry(ies) to: $OUTPUT_FILE${NC}\" >&2\n fi\nfi\n\nif [[ $FAILED_COUNT -gt 0 ]]; then\n echo -e \"${YELLOW}⚠ Failed to fetch $FAILED_COUNT entry(ies)${NC}\" >&2\n exit 1\nfi\n\nexit 0\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":6111,"content_sha256":"a6f103705393bb13aa6207c19e1835f83152fd5a57e6b37eb5f2795739689b61"},{"filename":"scripts/generate_chart.py","content":"#!/usr/bin/env python3\n\"\"\"\ngenerate_chart.py\nGenerates publication-quality charts as PNG/PDF for LaTeX inclusion using matplotlib.\n\nExamples:\n # Bar chart from JSON data\n ./generate_chart.py bar --data '{\"x\":[\"A\",\"B\",\"C\"],\"y\":[10,20,15]}' --output bar.png --title \"Sales by Region\"\n\n # Line chart from CSV file\n ./generate_chart.py line --csv data.csv --output line.pdf --xlabel \"Time\" --ylabel \"Value\" --dpi 300\n\n # Scatter plot with custom styling\n ./generate_chart.py scatter --data '{\"x\":[1,2,3,4],\"y\":[2,4,1,3]}' --style seaborn-v0_8-darkgrid --figsize 10x6\n\n # Pie chart with custom colors\n ./generate_chart.py pie --data '{\"labels\":[\"A\",\"B\",\"C\"],\"values\":[30,40,30]}' --colors \"#FF6B6B,#4ECDC4,#45B7D1\"\n\"\"\"\n\nimport argparse\nimport json\nimport subprocess\nimport sys\nfrom pathlib import Path\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n # PEP 668: retry with --break-system-packages for externally-managed envs\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"numpy\")\n_ensure_package(\"pandas\")\n_ensure_package(\"matplotlib\")\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib\nmatplotlib.use('Agg') # Use non-interactive backend\nimport matplotlib.pyplot as plt\n\n# Chart type implementations\ndef plot_bar(data, ax, **kwargs):\n \"\"\"Create a bar chart.\"\"\"\n if 'x' in data and 'y' in data:\n x = data['x']\n y = data['y']\n legend_labels = kwargs.get('legend_labels', None)\n colors = kwargs.get('colors', None)\n\n # Check if y is multi-series (list of lists)\n is_multi_series = isinstance(y[0], (list, tuple)) if len(y) > 0 else False\n\n if is_multi_series:\n # Multi-series grouped bar chart\n n_series = len(y)\n n_groups = len(x)\n\n # Get colors for each series\n if colors is None:\n colors = get_colorblind_palette(n_series)\n\n # Calculate bar positions and width\n bar_width = 0.8 / n_series\n x_positions = np.arange(n_groups)\n\n for i, series in enumerate(y):\n offset = (i - n_series/2 + 0.5) * bar_width\n label = legend_labels[i] if legend_labels and i \u003c len(legend_labels) else f\"Series {i+1}\"\n ax.bar(x_positions + offset, series, bar_width,\n label=label, color=colors[i % len(colors)])\n\n ax.set_xticks(x_positions)\n ax.set_xticklabels(x)\n else:\n # Single-series bar chart (backward compatible)\n ax.bar(x, y, color=colors[0] if colors else None)\n else:\n raise ValueError(\"Bar chart requires 'x' and 'y' keys in data\")\n\ndef plot_line(data, ax, **kwargs):\n \"\"\"Create a line chart.\"\"\"\n if 'x' in data and 'y' in data:\n x = data['x']\n y = data['y']\n legend_labels = kwargs.get('legend_labels', None)\n colors = kwargs.get('colors', None)\n show_grid = kwargs.get('show_grid', False)\n\n # Check if y is multi-series (list of lists)\n is_multi_series = isinstance(y[0], (list, tuple)) if len(y) > 0 else False\n\n if is_multi_series:\n # Multi-series line chart\n n_series = len(y)\n markers = ['o', 's', '^', 'D', 'v', '\u003c', '>', 'p', '*', 'h']\n\n # Get colors for each series\n if colors is None:\n colors = get_colorblind_palette(n_series)\n\n for i, series in enumerate(y):\n label = legend_labels[i] if legend_labels and i \u003c len(legend_labels) else f\"Series {i+1}\"\n marker = markers[i % len(markers)]\n ax.plot(x, series, marker=marker, linewidth=2,\n label=label, color=colors[i % len(colors)])\n else:\n # Single-series line chart (backward compatible)\n ax.plot(x, y, marker='o', linewidth=2, color=colors[0] if colors else None)\n\n if show_grid:\n ax.grid(True, alpha=0.3)\n else:\n raise ValueError(\"Line chart requires 'x' and 'y' keys in data\")\n\ndef plot_scatter(data, ax, **kwargs):\n \"\"\"Create a scatter plot.\"\"\"\n if 'x' in data and 'y' in data:\n x = data['x']\n y = data['y']\n sizes = data.get('sizes', 50)\n legend_labels = kwargs.get('legend_labels', None)\n colors = kwargs.get('colors', None)\n show_grid = kwargs.get('show_grid', False)\n\n # Check if y is multi-series (list of lists)\n is_multi_series = isinstance(y[0], (list, tuple)) if len(y) > 0 else False\n\n if is_multi_series:\n # Multi-series scatter plot\n n_series = len(y)\n markers = ['o', 's', '^', 'D', 'v', '\u003c', '>', 'p', '*', 'h']\n\n # Get colors for each series\n if colors is None:\n colors = get_colorblind_palette(n_series)\n\n # Handle sizes for multi-series\n if isinstance(sizes, (int, float)):\n sizes = [sizes] * n_series\n\n for i, series in enumerate(y):\n label = legend_labels[i] if legend_labels and i \u003c len(legend_labels) else f\"Series {i+1}\"\n marker = markers[i % len(markers)]\n size = sizes[i] if isinstance(sizes, list) and i \u003c len(sizes) else 50\n ax.scatter(x, series, s=size, alpha=0.6,\n label=label, color=colors[i % len(colors)], marker=marker)\n else:\n # Single-series scatter plot (backward compatible)\n ax.scatter(x, y, s=sizes, alpha=0.6, color=colors[0] if colors else None)\n\n if show_grid:\n ax.grid(True, alpha=0.3)\n else:\n raise ValueError(\"Scatter plot requires 'x' and 'y' keys in data\")\n\ndef plot_pie(data, ax, **kwargs):\n \"\"\"Create a pie chart.\"\"\"\n if 'labels' in data and 'values' in data:\n labels = data['labels']\n values = data['values']\n colors = kwargs.get('colors', None)\n ax.pie(values, labels=labels, autopct='%1.1f%%', startangle=90, colors=colors)\n ax.axis('equal')\n else:\n raise ValueError(\"Pie chart requires 'labels' and 'values' keys in data\")\n\ndef plot_heatmap(data, ax, **kwargs):\n \"\"\"Create a heatmap.\"\"\"\n if 'matrix' in data:\n matrix = np.array(data['matrix'])\n im = ax.imshow(matrix, cmap='viridis', aspect='auto')\n plt.colorbar(im, ax=ax)\n\n # Add row/column labels if provided\n if 'xlabels' in data:\n ax.set_xticks(range(len(data['xlabels'])))\n ax.set_xticklabels(data['xlabels'])\n if 'ylabels' in data:\n ax.set_yticks(range(len(data['ylabels'])))\n ax.set_yticklabels(data['ylabels'])\n else:\n raise ValueError(\"Heatmap requires 'matrix' key in data\")\n\ndef plot_box(data, ax, **kwargs):\n \"\"\"Create a box plot.\"\"\"\n if 'data' in data:\n box_data = data['data']\n labels = data.get('labels', None)\n show_grid = kwargs.get('show_grid', False)\n ax.boxplot(box_data, labels=labels)\n if show_grid:\n ax.grid(True, alpha=0.3, axis='y')\n else:\n raise ValueError(\"Box plot requires 'data' key (list of lists)\")\n\ndef plot_histogram(data, ax, **kwargs):\n \"\"\"Create a histogram.\"\"\"\n if 'values' in data:\n values = data['values']\n bins = data.get('bins', 10)\n colors = kwargs.get('colors', None)\n show_grid = kwargs.get('show_grid', False)\n ax.hist(values, bins=bins, edgecolor='black', alpha=0.7, color=colors[0] if colors else None)\n if show_grid:\n ax.grid(True, alpha=0.3, axis='y')\n else:\n raise ValueError(\"Histogram requires 'values' key in data\")\n\ndef plot_area(data, ax, **kwargs):\n \"\"\"Create an area chart.\"\"\"\n if 'x' in data and 'y' in data:\n x = data['x']\n y = data['y']\n legend_labels = kwargs.get('legend_labels', None)\n colors = kwargs.get('colors', None)\n show_grid = kwargs.get('show_grid', False)\n\n # Check if y is multi-series (list of lists)\n is_multi_series = isinstance(y[0], (list, tuple)) if len(y) > 0 else False\n\n if is_multi_series:\n # Multi-series area chart (stacked)\n n_series = len(y)\n\n # Get colors for each series\n if colors is None:\n colors = get_colorblind_palette(n_series)\n\n # Convert to numpy array for stacking\n y_array = np.array(y)\n y_stack = np.zeros(len(x))\n\n for i in range(n_series):\n label = legend_labels[i] if legend_labels and i \u003c len(legend_labels) else f\"Series {i+1}\"\n ax.fill_between(x, y_stack, y_stack + y_array[i],\n alpha=0.7, label=label, color=colors[i % len(colors)])\n ax.plot(x, y_stack + y_array[i], linewidth=2, color=colors[i % len(colors)])\n y_stack += y_array[i]\n else:\n # Single-series area chart (backward compatible)\n ax.fill_between(x, y, alpha=0.7, color=colors[0] if colors else None)\n ax.plot(x, y, linewidth=2)\n\n if show_grid:\n ax.grid(True, alpha=0.3)\n else:\n raise ValueError(\"Area chart requires 'x' and 'y' keys in data\")\n\ndef plot_radar(data, ax, **kwargs):\n \"\"\"Create a radar chart.\"\"\"\n if 'labels' in data and 'values' in data:\n labels = data['labels']\n values = data['values']\n\n num_vars = len(labels)\n angles = np.linspace(0, 2 * np.pi, num_vars, endpoint=False).tolist()\n values = values + [values[0]] # Complete the circle\n angles += angles[:1]\n\n # Use the figure from the passed-in ax (or current figure) to create polar subplot\n fig = ax.get_figure() if ax is not None else plt.gcf()\n if ax is not None:\n ax.remove() # Remove the non-polar axes created by caller\n ax = fig.add_subplot(111, projection='polar')\n color = kwargs.get('colors', [None])[0] if kwargs.get('colors') else None\n ax.plot(angles, values, 'o-', linewidth=2, color=color)\n ax.fill(angles, values, alpha=0.25, color=color)\n ax.set_xticks(angles[:-1])\n ax.set_xticklabels(labels)\n ax.set_ylim(0, max(values) * 1.1)\n ax.grid(True)\n return ax\n else:\n raise ValueError(\"Radar chart requires 'labels' and 'values' keys in data\")\n\nCHART_TYPES = {\n 'bar': plot_bar,\n 'line': plot_line,\n 'scatter': plot_scatter,\n 'pie': plot_pie,\n 'heatmap': plot_heatmap,\n 'box': plot_box,\n 'histogram': plot_histogram,\n 'area': plot_area,\n 'radar': plot_radar,\n}\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description='Generate publication-quality charts for LaTeX inclusion',\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=__doc__\n )\n\n parser.add_argument('chart_type', choices=CHART_TYPES.keys(),\n help='Type of chart to generate')\n\n data_group = parser.add_mutually_exclusive_group(required=True)\n data_group.add_argument('--data', type=str,\n help='Chart data as JSON string')\n data_group.add_argument('--csv', type=str,\n help='Path to CSV file with chart data')\n\n parser.add_argument('--output', type=str, default='chart.png',\n help='Output file path (default: chart.png)')\n parser.add_argument('--title', type=str, default='',\n help='Chart title')\n parser.add_argument('--xlabel', type=str, default='',\n help='X-axis label')\n parser.add_argument('--ylabel', type=str, default='',\n help='Y-axis label')\n parser.add_argument('--style', type=str, default='seaborn-v0_8-whitegrid',\n help='Matplotlib style (default: seaborn-v0_8-whitegrid)')\n parser.add_argument('--figsize', type=str, default='8x5',\n help='Figure size as WxH in inches (default: 8x5)')\n parser.add_argument('--dpi', type=int, default=300,\n help='DPI for output image (default: 300)')\n parser.add_argument('--colors', type=str, default=None,\n help='Comma-separated hex color codes (e.g., #FF6B6B,#4ECDC4)')\n parser.add_argument('--legend', type=str, default=None,\n help='Comma-separated series names for legend (e.g., \"Series A,Series B,Series C\")')\n parser.add_argument('--legend-loc', type=str, default='best',\n help='Legend location: best, upper right, upper left, lower right, lower left, center, outside (default: best)')\n parser.add_argument('--grid', action='store_true',\n help='Enable grid lines (default: off)')\n\n return parser.parse_args()\n\ndef load_data(args):\n \"\"\"Load data from JSON string or CSV file.\"\"\"\n if args.data:\n try:\n return json.loads(args.data)\n except json.JSONDecodeError as e:\n print(f\"Error: Invalid JSON data: {e}\", file=sys.stderr)\n sys.exit(1)\n elif args.csv:\n try:\n df = pd.read_csv(args.csv)\n # Convert DataFrame to dict format\n return {col: df[col].tolist() for col in df.columns}\n except Exception as e:\n print(f\"Error: Failed to read CSV file: {e}\", file=sys.stderr)\n sys.exit(1)\n\ndef parse_figsize(figsize_str):\n \"\"\"Parse figsize string like '8x5' into tuple (8, 5).\"\"\"\n try:\n width, height = figsize_str.lower().split('x')\n return (float(width), float(height))\n except:\n print(f\"Error: Invalid figsize format: {figsize_str}. Use format like '8x5'\", file=sys.stderr)\n sys.exit(1)\n\ndef parse_colors(colors_str):\n \"\"\"Parse comma-separated color string into list.\"\"\"\n if not colors_str:\n return None\n return [c.strip() for c in colors_str.split(',')]\n\ndef parse_legend(legend_str):\n \"\"\"Parse comma-separated legend string into list.\"\"\"\n if not legend_str:\n return None\n return [label.strip() for label in legend_str.split(',')]\n\ndef get_colorblind_palette(n_colors):\n \"\"\"Return a colorblind-friendly palette with n colors using Tol color scheme.\"\"\"\n # Paul Tol's colorblind-friendly palette\n tol_bright = ['#4477AA', '#EE6677', '#228833', '#CCBB44', '#66CCEE', '#AA3377', '#BBBBBB']\n if n_colors \u003c= len(tol_bright):\n return tol_bright[:n_colors]\n # If more colors needed, cycle through the palette\n return [tol_bright[i % len(tol_bright)] for i in range(n_colors)]\n\ndef main():\n args = parse_args()\n\n # Load data\n data = load_data(args)\n\n # Parse figsize, colors, and legend\n figsize = parse_figsize(args.figsize)\n colors = parse_colors(args.colors)\n legend_labels = parse_legend(args.legend)\n\n # Set style\n try:\n plt.style.use(args.style)\n except:\n print(f\"Warning: Style '{args.style}' not found, using default\", file=sys.stderr)\n\n # Create figure\n fig, ax = plt.subplots(figsize=figsize, dpi=args.dpi)\n\n # Generate chart\n try:\n plot_func = CHART_TYPES[args.chart_type]\n result_ax = plot_func(data, ax, colors=colors, legend_labels=legend_labels, show_grid=args.grid)\n if result_ax is not None:\n ax = result_ax\n except Exception as e:\n print(f\"Error: Failed to generate chart: {e}\", file=sys.stderr)\n sys.exit(1)\n\n # Set labels and title\n if args.title:\n plt.title(args.title, fontsize=14, fontweight='bold')\n if args.xlabel and ax is not None:\n ax.set_xlabel(args.xlabel, fontsize=11)\n if args.ylabel and ax is not None:\n ax.set_ylabel(args.ylabel, fontsize=11)\n\n # Add legend if legend_labels were provided or if multi-series data exists\n if ax is not None and legend_labels is not None:\n # Handle legend location\n legend_loc = args.legend_loc\n if legend_loc == 'outside':\n ax.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)\n else:\n ax.legend(loc=legend_loc)\n\n # Tight layout for better spacing\n plt.tight_layout()\n\n # Save figure\n try:\n output_path = Path(args.output)\n output_path.parent.mkdir(parents=True, exist_ok=True)\n plt.savefig(args.output, dpi=args.dpi, bbox_inches='tight')\n print(f\"Successfully created: {args.output}\", file=sys.stderr)\n except Exception as e:\n print(f\"Error: Failed to save output: {e}\", file=sys.stderr)\n sys.exit(1)\n\nif __name__ == '__main__':\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":17555,"content_sha256":"8c6ba3f8a34a70d82e4968e0677ffa44ea3f12f9e12bc628a704ac00b8876652"},{"filename":"scripts/graphviz_to_pdf.sh","content":"#!/usr/bin/env bash\n\n# graphviz_to_pdf.sh\n# Converts Graphviz .dot files to PDF or PNG for LaTeX inclusion\n#\n# Examples:\n# ./graphviz_to_pdf.sh diagram.dot\n# ./graphviz_to_pdf.sh diagram.dot --output result.pdf --format pdf\n# ./graphviz_to_pdf.sh diagram.dot --engine neato --format png\n# ./graphviz_to_pdf.sh diagrams/source/ # Batch mode\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nFORMAT=\"pdf\"\nENGINE=\"dot\"\nOUTPUT_FILE=\"\"\nDPI=\"300\"\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cinput.dot|directory> [OPTIONS]\n\nConvert Graphviz .dot files to PDF or PNG for LaTeX inclusion.\n\nArguments:\n input.dot Input Graphviz .dot file\n directory Directory containing .dot files (batch mode)\n\nOptions:\n --output FILE Output file path (default: input name with format extension)\n --format FORMAT Output format: pdf or png (default: pdf)\n --engine ENGINE Layout engine: dot, neato, circo, fdp, twopi, sfdp (default: dot)\n --dpi DPI Resolution for PNG output (default: 300)\n -h, --help Show this help message\n\nLayout Engines:\n dot - Hierarchical/directed graphs (default)\n neato - Undirected graphs (spring model)\n circo - Circular layout\n fdp - Force-directed placement\n twopi - Radial layout\n sfdp - Scalable force-directed (large graphs)\n\nExamples:\n $0 diagram.dot\n $0 diagram.dot --output result.pdf\n $0 diagram.dot --format png --engine neato\n $0 diagrams/source/ --format pdf\n\nRequires: graphviz (auto-installs if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\nINPUT_PATH=\"$1\"\nshift\n\n# Parse options\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n --format)\n FORMAT=\"$2\"\n shift 2\n ;;\n --engine)\n ENGINE=\"$2\"\n shift 2\n ;;\n --dpi)\n DPI=\"$2\"\n shift 2\n ;;\n *)\n echo \"Error: Unknown option: $1\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\n ;;\n esac\ndone\n\n# Validate format\nif [[ \"$FORMAT\" != \"pdf\" ]] && [[ \"$FORMAT\" != \"png\" ]]; then\n echo \"Error: Format must be 'pdf' or 'png', got: $FORMAT\" >&2\n exit 1\nfi\n\n# Validate engine\ncase \"$ENGINE\" in\n dot|neato|circo|fdp|twopi|sfdp)\n ;;\n *)\n echo \"Error: Invalid engine '$ENGINE'\" >&2\n echo \"Valid engines: dot, neato, circo, fdp, twopi, sfdp\" >&2\n exit 1\n ;;\nesac\n\n# Validate DPI is a number\nif ! [[ \"$DPI\" =~ ^[0-9]+$ ]]; then\n echo \"Error: DPI must be a number, got: $DPI\" >&2\n exit 1\nfi\n\n# Check if Graphviz is installed\nif ! command -v dot &>/dev/null; then\n echo \"Graphviz not found. Installing...\" >&2\n\n # Add graphviz to the package mapping in install_deps.sh\n # For now, install directly\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt)\n run_pkg_install graphviz\n ;;\n brew)\n run_pkg_install graphviz\n ;;\n dnf)\n run_pkg_install graphviz\n ;;\n apk)\n run_pkg_install graphviz\n ;;\n pacman)\n run_pkg_install graphviz\n ;;\n *)\n echo \"Error: Could not auto-install Graphviz\" >&2\n echo \"\" >&2\n echo \"Please install manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install graphviz\" >&2\n echo \" macOS: brew install graphviz\" >&2\n echo \" Fedora/RHEL: sudo dnf install graphviz\" >&2\n echo \" Alpine: sudo apk add graphviz\" >&2\n echo \" Arch: sudo pacman -S graphviz\" >&2\n exit 1\n ;;\n esac\nfi\n\n# Verify engine is available\nif ! command -v \"$ENGINE\" &>/dev/null; then\n echo \"Error: Engine '$ENGINE' not found in PATH\" >&2\n exit 1\nfi\n\n# Function to convert a single file\nconvert_file() {\n local input_file=\"$1\"\n local output_file=\"$2\"\n\n if [[ ! -f \"$input_file\" ]]; then\n echo \"Error: Input file not found: $input_file\" >&2\n return 1\n fi\n\n # Validate .dot extension\n if [[ ! \"$input_file\" =~ \\.dot$ ]]; then\n echo \"Warning: Input file does not have .dot extension: $input_file\" >&2\n fi\n\n echo \"Converting $input_file -> $output_file (engine: $ENGINE, format: $FORMAT)\" >&2\n\n # Build command based on format\n if [[ \"$FORMAT\" == \"pdf\" ]]; then\n \"$ENGINE\" -Tpdf \"$input_file\" -o \"$output_file\"\n elif [[ \"$FORMAT\" == \"png\" ]]; then\n \"$ENGINE\" -Tpng -Gdpi=\"$DPI\" \"$input_file\" -o \"$output_file\"\n fi\n\n if [[ $? -eq 0 ]]; then\n echo \"Successfully created: $output_file\" >&2\n return 0\n else\n echo \"Error: Failed to convert $input_file\" >&2\n return 1\n fi\n}\n\n# Check if input is a directory (batch mode) or a file\nif [[ -d \"$INPUT_PATH\" ]]; then\n # Batch mode: convert all .dot files in directory\n echo \"Batch mode: converting all .dot files in $INPUT_PATH\" >&2\n\n # Remove trailing slash\n INPUT_PATH=\"${INPUT_PATH%/}\"\n\n # Find all .dot files\n shopt -s nullglob\n dot_files=(\"$INPUT_PATH\"/*.dot)\n\n if [[ ${#dot_files[@]} -eq 0 ]]; then\n echo \"Error: No .dot files found in $INPUT_PATH\" >&2\n exit 1\n fi\n\n echo \"Found ${#dot_files[@]} .dot file(s)\" >&2\n\n success_count=0\n fail_count=0\n\n for dot_file in \"${dot_files[@]}\"; do\n filename=$(basename \"$dot_file\" .dot)\n output_file=\"$INPUT_PATH/${filename}.$FORMAT\"\n\n if convert_file \"$dot_file\" \"$output_file\"; then\n ((success_count++))\n else\n ((fail_count++))\n fi\n done\n\n echo \"\" >&2\n echo \"Batch conversion complete:\" >&2\n echo \" Success: $success_count\" >&2\n echo \" Failed: $fail_count\" >&2\n\n if [[ $fail_count -gt 0 ]]; then\n exit 1\n fi\n\nelif [[ -f \"$INPUT_PATH\" ]]; then\n # Single file mode\n\n # Determine output file\n if [[ -z \"$OUTPUT_FILE\" ]]; then\n # Default: replace .dot extension with format\n OUTPUT_FILE=\"${INPUT_PATH%.dot}.$FORMAT\"\n fi\n\n convert_file \"$INPUT_PATH\" \"$OUTPUT_FILE\"\n\nelse\n echo \"Error: Input path not found: $INPUT_PATH\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":6442,"content_sha256":"4a21a2acc0dddf812964f2a607887a2302261abcbd08d7d5e307e78fe249c904"},{"filename":"scripts/install_deps.sh","content":"#!/usr/bin/env bash\n# install_deps.sh - Cross-platform dependency installer for LaTeX document skill\n#\n# Source this file from other scripts:\n# SCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n# source \"${SCRIPT_DIR}/install_deps.sh\"\n#\n# Then call:\n# install_packages texlive poppler imagemagick pandoc\n#\n# Supported package managers: apt-get, brew, dnf, apk, pacman\n# Logical package names: texlive, poppler, imagemagick, pandoc\n\n# Avoid re-sourcing\nif [[ -n \"${_INSTALL_DEPS_LOADED:-}\" ]]; then\n return 0 2>/dev/null || true\nfi\n_INSTALL_DEPS_LOADED=1\n\n# --- Detect package manager ---\n_detected_pkg_manager=\"\"\n\ndetect_pkg_manager() {\n if [[ -n \"$_detected_pkg_manager\" ]]; then\n echo \"$_detected_pkg_manager\"\n return 0\n fi\n\n if command -v apt-get &>/dev/null; then\n _detected_pkg_manager=\"apt\"\n elif command -v brew &>/dev/null; then\n _detected_pkg_manager=\"brew\"\n elif command -v dnf &>/dev/null; then\n _detected_pkg_manager=\"dnf\"\n elif command -v apk &>/dev/null; then\n _detected_pkg_manager=\"apk\"\n elif command -v pacman &>/dev/null; then\n _detected_pkg_manager=\"pacman\"\n else\n _detected_pkg_manager=\"unknown\"\n fi\n\n echo \"$_detected_pkg_manager\"\n}\n\n# --- Run sudo if available, otherwise run directly ---\n_run_privileged() {\n if command -v sudo &>/dev/null; then\n sudo \"$@\"\n else\n \"$@\"\n fi\n}\n\n# --- Low-level package install for detected manager ---\n_apt_updated=false\n\nrun_pkg_install() {\n local mgr\n mgr=\"$(detect_pkg_manager)\"\n local packages=(\"$@\")\n\n if [[ ${#packages[@]} -eq 0 ]]; then\n return 0\n fi\n\n case \"$mgr\" in\n apt)\n if [[ \"$_apt_updated\" == false ]]; then\n echo \":: Updating apt package list...\" >&2\n _run_privileged apt-get update -qq >&2 2>&1 || true\n _apt_updated=true\n fi\n echo \":: Installing (apt): ${packages[*]}\" >&2\n DEBIAN_FRONTEND=noninteractive _run_privileged apt-get install -y -qq \"${packages[@]}\" >&2 2>&1\n ;;\n brew)\n echo \":: Installing (brew): ${packages[*]}\" >&2\n for pkg in \"${packages[@]}\"; do\n if [[ \"$pkg\" == *\"--cask\"* ]]; then\n # Strip --cask marker and install as cask\n local cask_pkg=\"${pkg//--cask /}\"\n brew install --cask \"$cask_pkg\" >&2 2>&1 || true\n else\n brew install \"$pkg\" >&2 2>&1 || true\n fi\n done\n ;;\n dnf)\n echo \":: Installing (dnf): ${packages[*]}\" >&2\n _run_privileged dnf install -y \"${packages[@]}\" >&2 2>&1\n ;;\n apk)\n echo \":: Installing (apk): ${packages[*]}\" >&2\n _run_privileged apk add --no-cache \"${packages[@]}\" >&2 2>&1\n ;;\n pacman)\n echo \":: Installing (pacman): ${packages[*]}\" >&2\n _run_privileged pacman -S --noconfirm \"${packages[@]}\" >&2 2>&1\n ;;\n *)\n echo \"Error: No supported package manager found.\" >&2\n echo \"Please install the following packages manually:\" >&2\n echo \" ${packages[*]}\" >&2\n echo \"\" >&2\n echo \"Platform-specific commands:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install ${packages[*]}\" >&2\n echo \" macOS: brew install ${packages[*]}\" >&2\n echo \" Fedora/RHEL: sudo dnf install ${packages[*]}\" >&2\n echo \" Alpine: sudo apk add ${packages[*]}\" >&2\n echo \" Arch: sudo pacman -S ${packages[*]}\" >&2\n return 1\n ;;\n esac\n}\n\n# --- Map logical package names to platform-specific packages ---\n_map_packages() {\n local logical_name=\"$1\"\n local mgr\n mgr=\"$(detect_pkg_manager)\"\n\n case \"$logical_name\" in\n texlive)\n case \"$mgr\" in\n apt) echo \"texlive-latex-base texlive-latex-extra texlive-fonts-recommended texlive-fonts-extra texlive-latex-recommended texlive-science texlive-xetex texlive-luatex texlive-bibtex-extra biber\" ;;\n brew) echo \"--cask basictex\" ;;\n dnf) echo \"texlive-scheme-medium texlive-collection-science texlive-collection-xetex texlive-collection-luatex texlive-collection-bibtexextra biber\" ;;\n apk) echo \"texlive-full biber\" ;;\n pacman) echo \"texlive-most biber\" ;;\n *) echo \"texlive biber\" ;;\n esac\n ;;\n poppler)\n case \"$mgr\" in\n apt) echo \"poppler-utils\" ;;\n brew) echo \"poppler\" ;;\n dnf) echo \"poppler-utils\" ;;\n apk) echo \"poppler-utils\" ;;\n pacman) echo \"poppler\" ;;\n *) echo \"poppler-utils\" ;;\n esac\n ;;\n imagemagick)\n case \"$mgr\" in\n apt) echo \"imagemagick\" ;;\n brew) echo \"imagemagick\" ;;\n dnf) echo \"ImageMagick\" ;;\n apk) echo \"imagemagick\" ;;\n pacman) echo \"imagemagick\" ;;\n *) echo \"imagemagick\" ;;\n esac\n ;;\n pandoc)\n case \"$mgr\" in\n apt) echo \"pandoc\" ;;\n brew) echo \"pandoc\" ;;\n dnf) echo \"pandoc\" ;;\n apk) echo \"pandoc\" ;;\n pacman) echo \"pandoc\" ;;\n *) echo \"pandoc\" ;;\n esac\n ;;\n *)\n echo \"Warning: Unknown logical package '$logical_name'\" >&2\n echo \"$logical_name\"\n ;;\n esac\n}\n\n# --- Public API: install packages by logical name ---\ninstall_packages() {\n local all_packages=()\n\n for logical_name in \"$@\"; do\n local mapped\n mapped=\"$(_map_packages \"$logical_name\")\"\n # Split mapped string into array elements\n read -ra pkgs \u003c\u003c\u003c \"$mapped\"\n all_packages+=(\"${pkgs[@]}\")\n done\n\n if [[ ${#all_packages[@]} -eq 0 ]]; then\n return 0\n fi\n\n # Remove duplicates while preserving order\n local unique_packages=()\n local seen=\"\"\n for pkg in \"${all_packages[@]}\"; do\n if [[ ! \" $seen \" =~ \" $pkg \" ]]; then\n unique_packages+=(\"$pkg\")\n seen=\"$seen $pkg\"\n fi\n done\n\n run_pkg_install \"${unique_packages[@]}\"\n}\n\n# --- Brew post-install: update PATH for basictex ---\n_brew_post_texlive() {\n local mgr\n mgr=\"$(detect_pkg_manager)\"\n if [[ \"$mgr\" == \"brew\" ]]; then\n # basictex installs to /Library/TeX/texbin\n if [[ -d \"/Library/TeX/texbin\" ]] && [[ ! \"$PATH\" =~ \"/Library/TeX/texbin\" ]]; then\n export PATH=\"/Library/TeX/texbin:$PATH\"\n echo \":: Added /Library/TeX/texbin to PATH\" >&2\n fi\n fi\n}\n\n# --- Helper: print manual install instructions for a logical package ---\nprint_install_help() {\n local logical_name=\"$1\"\n echo \"\" >&2\n echo \"Install '$logical_name' manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install $(_map_packages \"$logical_name\")\" >&2\n\n # Temporarily override manager for each platform's instructions\n local orig=\"$_detected_pkg_manager\"\n\n _detected_pkg_manager=\"brew\"\n echo \" macOS: brew install $(_map_packages \"$logical_name\")\" >&2\n\n _detected_pkg_manager=\"dnf\"\n echo \" Fedora/RHEL: sudo dnf install $(_map_packages \"$logical_name\")\" >&2\n\n _detected_pkg_manager=\"apk\"\n echo \" Alpine: sudo apk add $(_map_packages \"$logical_name\")\" >&2\n\n _detected_pkg_manager=\"pacman\"\n echo \" Arch: sudo pacman -S $(_map_packages \"$logical_name\")\" >&2\n\n _detected_pkg_manager=\"$orig\"\n echo \"\" >&2\n}\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":7009,"content_sha256":"0dd444d3c007c99c13747023c87757862406c250b55a83878f57078d8adb4bdb"},{"filename":"scripts/latex_analyze.sh","content":"#!/usr/bin/env bash\n\n# latex_analyze.sh\n# Comprehensive document analysis for LaTeX files\n#\n# Examples:\n# ./latex_analyze.sh document.tex\n# ./latex_analyze.sh thesis.tex\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# ANSI color codes\nBLUE='\\033[0;34m'\nGREEN='\\033[0;32m'\nYELLOW='\\033[1;33m'\nRED='\\033[0;31m'\nBOLD='\\033[1m'\nNC='\\033[0m' # No Color\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cfile.tex>\n\nComprehensive analysis of a LaTeX document including word count, structure,\nand common issues.\n\nArguments:\n file.tex Input LaTeX file to analyze\n\nOptions:\n -h, --help Show this help message\n\nExamples:\n $0 document.tex\n $0 thesis.tex\n\nRequires: detex (included in texlive)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\nTEX_FILE=\"$1\"\n\n# Validate input file\nif [[ ! -f \"$TEX_FILE\" ]]; then\n echo \"Error: Input file not found: $TEX_FILE\" >&2\n exit 1\nfi\n\n# Check for detex\nif ! command -v detex &>/dev/null; then\n echo \"Error: detex not found\" >&2\n echo \"detex is typically included with texlive\" >&2\n echo \"Please install texlive:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install texlive-extra-utils\" >&2\n echo \" macOS: brew install texlive\" >&2\n echo \" Fedora/RHEL: sudo dnf install texlive-scheme-medium\" >&2\n echo \" Alpine: sudo apk add texlive-full\" >&2\n echo \" Arch: sudo pacman -S texlive-most\" >&2\n exit 1\nfi\n\necho -e \"${BOLD}LaTeX Document Analysis${NC}\"\necho \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\"\necho \"File: $TEX_FILE\"\necho \"\"\n\n# === WORD COUNT ===\necho -e \"${BLUE}${BOLD}Word Count${NC}\"\nWORD_COUNT=$(detex \"$TEX_FILE\" 2>/dev/null | wc -w | tr -d ' ')\necho \"Words: $WORD_COUNT\"\nPAGES=$((WORD_COUNT / 250))\nif [[ $PAGES -gt 0 ]]; then\n echo \"Estimated pages: ~$PAGES (at 250 words/page)\"\nfi\necho \"\"\n\n# === CONTENT STATISTICS ===\necho -e \"${BLUE}${BOLD}Content Statistics${NC}\"\nFIGURE_COUNT=$(grep -c '\\\\begin{figure}' \"$TEX_FILE\" 2>/dev/null || true)\nFIGURE_COUNT=${FIGURE_COUNT:-0}\necho \"Figures: $FIGURE_COUNT\"\n\nTABLE_COUNT=$(grep -c '\\\\begin{table}' \"$TEX_FILE\" 2>/dev/null || true)\nTABLE_COUNT=${TABLE_COUNT:-0}\necho \"Tables: $TABLE_COUNT\"\n\nEQUATION_COUNT=$(grep -c '\\\\begin{equation}' \"$TEX_FILE\" 2>/dev/null || true)\nEQUATION_COUNT=${EQUATION_COUNT:-0}\nALIGN_COUNT=$(grep -c '\\\\begin{align' \"$TEX_FILE\" 2>/dev/null || true)\nALIGN_COUNT=${ALIGN_COUNT:-0}\nTOTAL_EQUATIONS=$((EQUATION_COUNT + ALIGN_COUNT))\necho \"Equations: $TOTAL_EQUATIONS\"\n\nCITATION_COUNT=$(grep -o '\\\\cite{[^}]*}' \"$TEX_FILE\" 2>/dev/null | wc -l | tr -d ' \\n' || true)\nCITATION_COUNT=${CITATION_COUNT:-0}\necho \"Citations: $CITATION_COUNT\"\necho \"\"\n\n# === DOCUMENT STRUCTURE ===\necho -e \"${BLUE}${BOLD}Document Structure${NC}\"\n\n# Sections\nSECTION_COUNT=$(grep -c '^\\\\section{' \"$TEX_FILE\" 2>/dev/null || true)\nSECTION_COUNT=${SECTION_COUNT:-0}\necho \"Sections: $SECTION_COUNT\"\n\nif [[ $SECTION_COUNT -gt 0 ]]; then\n echo \"\"\n echo \"Section titles:\"\n grep '^\\\\section{' \"$TEX_FILE\" 2>/dev/null | sed 's/\\\\section{\\(.*\\)}/ • \\1/' || true\nfi\n\n# Subsections\nSUBSECTION_COUNT=$(grep -c '^\\\\subsection{' \"$TEX_FILE\" 2>/dev/null || true)\nSUBSECTION_COUNT=${SUBSECTION_COUNT:-0}\nif [[ $SUBSECTION_COUNT -gt 0 ]]; then\n echo \"\"\n echo \"Subsections: $SUBSECTION_COUNT\"\nfi\n\n# Subsubsections\nSUBSUBSECTION_COUNT=$(grep -c '^\\\\subsubsection{' \"$TEX_FILE\" 2>/dev/null || true)\nSUBSUBSECTION_COUNT=${SUBSUBSECTION_COUNT:-0}\nif [[ $SUBSUBSECTION_COUNT -gt 0 ]]; then\n echo \"Subsubsections: $SUBSUBSECTION_COUNT\"\nfi\necho \"\"\n\n# === COMMON ISSUES ===\necho -e \"${BLUE}${BOLD}Issue Detection${NC}\"\nISSUES_FOUND=0\n\n# Check for figures without labels\nFIGURES_WITHOUT_LABELS=0\nif [[ $FIGURE_COUNT -gt 0 ]]; then\n # Extract figure environments and check for labels\n TEMP_FIGURES=$(mktemp)\n trap \"rm -f $TEMP_FIGURES\" EXIT\n\n # Simple heuristic: count figures with \\label vs total figures\n FIGURES_WITH_LABELS=$(grep -A 5 '\\\\begin{figure}' \"$TEX_FILE\" 2>/dev/null | grep -c '\\\\label{' || true)\n FIGURES_WITH_LABELS=${FIGURES_WITH_LABELS:-0}\n FIGURES_WITHOUT_LABELS=$((FIGURE_COUNT - FIGURES_WITH_LABELS))\n\n if [[ $FIGURES_WITHOUT_LABELS -gt 0 ]]; then\n echo -e \"${YELLOW}⚠ $FIGURES_WITHOUT_LABELS figure(s) may be missing \\\\label commands${NC}\"\n ISSUES_FOUND=$((ISSUES_FOUND + 1))\n fi\nfi\n\n# Check for tables without labels\nTABLES_WITHOUT_LABELS=0\nif [[ $TABLE_COUNT -gt 0 ]]; then\n TABLES_WITH_LABELS=$(grep -A 5 '\\\\begin{table}' \"$TEX_FILE\" 2>/dev/null | grep -c '\\\\label{' || true)\n TABLES_WITH_LABELS=${TABLES_WITH_LABELS:-0}\n TABLES_WITHOUT_LABELS=$((TABLE_COUNT - TABLES_WITH_LABELS))\n\n if [[ $TABLES_WITHOUT_LABELS -gt 0 ]]; then\n echo -e \"${YELLOW}⚠ $TABLES_WITHOUT_LABELS table(s) may be missing \\\\label commands${NC}\"\n ISSUES_FOUND=$((ISSUES_FOUND + 1))\n fi\nfi\n\n# Check for unreferenced labels\nALL_LABELS=$(grep -o '\\\\label{[^}]*}' \"$TEX_FILE\" 2>/dev/null | sed 's/\\\\label{\\([^}]*\\)}/\\1/' || true)\nUNREFERENCED_LABELS=\"\"\n\nif [[ -n \"$ALL_LABELS\" ]]; then\n while IFS= read -r label; do\n if ! grep -q \"\\\\\\\\ref{$label}\" \"$TEX_FILE\" 2>/dev/null; then\n UNREFERENCED_LABELS=\"${UNREFERENCED_LABELS}${label}\\n\"\n ISSUES_FOUND=$((ISSUES_FOUND + 1))\n fi\n done \u003c\u003c\u003c \"$ALL_LABELS\"\n\n if [[ -n \"$UNREFERENCED_LABELS\" ]]; then\n echo -e \"${YELLOW}⚠ Unreferenced labels found:${NC}\"\n echo -e \"$UNREFERENCED_LABELS\" | sed 's/^/ /'\n fi\nfi\n\n# Check for TODO/FIXME comments\nTODO_COUNT=$(grep -c 'TODO\\|FIXME\\|XXX' \"$TEX_FILE\" 2>/dev/null || true)\nTODO_COUNT=${TODO_COUNT:-0}\nif [[ $TODO_COUNT -gt 0 ]]; then\n echo -e \"${YELLOW}⚠ $TODO_COUNT TODO/FIXME comment(s) found${NC}\"\n ISSUES_FOUND=$((ISSUES_FOUND + 1))\nfi\n\n# Check for common typos\nDOUBLE_SPACE_COUNT=$(grep -c ' ' \"$TEX_FILE\" 2>/dev/null || true)\nDOUBLE_SPACE_COUNT=${DOUBLE_SPACE_COUNT:-0}\nif [[ $DOUBLE_SPACE_COUNT -gt 10 ]]; then\n echo -e \"${YELLOW}⚠ Multiple double spaces detected (may be intentional)${NC}\"\nfi\n\n# Summary\nif [[ $ISSUES_FOUND -eq 0 ]]; then\n echo -e \"${GREEN}✓ No common issues detected${NC}\"\nfi\n\necho \"\"\necho \"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\"\necho -e \"${GREEN}Analysis complete${NC}\"\n\nexit 0\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":6580,"content_sha256":"85cd5568652b6bfc3ce7831423ea4a0e3440c64bce0a7e0bfc74524ad8dfe0e5"},{"filename":"scripts/latex_citation_extract.sh","content":"#!/usr/bin/env bash\n# latex_citation_extract.sh - Extract and analyze citations from a .tex file\n#\n# Usage:\n# latex_citation_extract.sh \u003cinput.tex> [--bib \u003cfile.bib>] [--format json|text] [--check]\n#\n# Options:\n# --bib \u003cfile> Specify .bib file (auto-detects from \\bibliography{} or \\addbibresource{})\n# --format \u003cfmt> Output format: text (default) or json\n# --check Verify all citations exist in .bib file, report missing\n#\n# Features:\n# - Extracts all \\cite{}, \\citep{}, \\citet{}, \\citealp{}, \\citealt{} commands\n# - Counts usage per citation key\n# - Auto-detects bibliography files from document\n# - Cross-references citations with .bib entries\n# - JSON output for programmatic use\n# - Identifies missing citations\n#\n# Examples:\n# latex_citation_extract.sh paper.tex\n# latex_citation_extract.sh paper.tex --bib references.bib --check\n# latex_citation_extract.sh paper.tex --format json\n# latex_citation_extract.sh paper.tex --bib refs.bib --check --format text\n\nset -euo pipefail\n\n# --- Usage function ---\nusage() {\n cat \u003c\u003c'EOF'\nlatex_citation_extract.sh - Extract and analyze citations from a .tex file\n\nUsage:\n latex_citation_extract.sh \u003cinput.tex> [--bib \u003cfile.bib>] [--format json|text] [--check]\n\nOptions:\n --bib \u003cfile> Specify .bib file (auto-detects from \\bibliography{} or \\addbibresource{})\n --format \u003cfmt> Output format: text (default) or json\n --check Verify all citations exist in .bib file, report missing\n\nFeatures:\n - Extracts all \\cite{}, \\citep{}, \\citet{}, \\citealp{}, \\citealt{} commands\n - Counts usage per citation key\n - Auto-detects bibliography files from document\n - Cross-references citations with .bib entries\n - JSON output for programmatic use\n - Identifies missing citations\n\nExamples:\n latex_citation_extract.sh paper.tex\n latex_citation_extract.sh paper.tex --bib references.bib --check\n latex_citation_extract.sh paper.tex --format json\n latex_citation_extract.sh paper.tex --bib refs.bib --check --format text\nEOF\n}\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# --- Parse arguments ---\nINPUT_TEX=\"\"\nBIB_FILE=\"\"\nFORMAT=\"text\"\nCHECK=false\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) usage; exit 0 ;;\n --bib) BIB_FILE=\"$2\"; shift 2 ;;\n --format) FORMAT=\"$2\"; shift 2 ;;\n --check) CHECK=true; shift ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *) INPUT_TEX=\"$1\"; shift ;;\n esac\ndone\n\nif [[ -z \"$INPUT_TEX\" ]]; then\n echo \"Error: No input .tex file specified\" >&2\n echo \"Usage: latex_citation_extract.sh \u003cinput.tex> [--bib \u003cfile.bib>] [--format json|text] [--check]\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_TEX\" ]]; then\n echo \"Error: File not found: $INPUT_TEX\" >&2\n exit 1\nfi\n\nif [[ \"$FORMAT\" != \"text\" && \"$FORMAT\" != \"json\" ]]; then\n echo \"Error: Invalid format '$FORMAT'. Must be 'text' or 'json'\" >&2\n exit 1\nfi\n\n# Resolve absolute path\nINPUT_TEX=\"$(realpath \"$INPUT_TEX\")\"\nINPUT_DIR=\"$(dirname \"$INPUT_TEX\")\"\n\n# --- Auto-detect bibliography file ---\ndetect_bib_file() {\n local tex_file=\"$1\"\n local tex_dir=\"$2\"\n\n # Look for \\bibliography{filename} or \\addbibresource{filename.bib}\n local bib_name=\"\"\n\n # Try \\bibliography{} first\n bib_name=$(grep -oP '\\\\bibliography\\{\\K[^\\}]+' \"$tex_file\" 2>/dev/null | head -1)\n\n if [[ -n \"$bib_name\" ]]; then\n # Add .bib extension if not present\n if [[ ! \"$bib_name\" =~ \\.bib$ ]]; then\n bib_name=\"${bib_name}.bib\"\n fi\n # Check if file exists (relative to tex file)\n if [[ -f \"${tex_dir}/${bib_name}\" ]]; then\n echo \"${tex_dir}/${bib_name}\"\n return 0\n fi\n fi\n\n # Try \\addbibresource{}\n bib_name=$(grep -oP '\\\\addbibresource\\{\\K[^\\}]+' \"$tex_file\" 2>/dev/null | head -1)\n\n if [[ -n \"$bib_name\" ]]; then\n # addbibresource requires .bib extension\n if [[ -f \"${tex_dir}/${bib_name}\" ]]; then\n echo \"${tex_dir}/${bib_name}\"\n return 0\n fi\n fi\n\n # No bibliography found\n echo \"\"\n}\n\n# --- Extract citations from .tex file ---\nextract_citations() {\n local tex_file=\"$1\"\n\n # Extract all cite commands: \\cite, \\citep, \\citet, \\citealp, \\citealt, \\nocite\n # Handle optional arguments and comma-separated keys\n grep -oP '\\\\(?:cite[a-z]*|nocite)(?:\\[[^\\]]*\\])?(?:\\[[^\\]]*\\])?\\{[^\\}]+\\}' \"$tex_file\" 2>/dev/null | \\\n sed -E 's/\\\\(cite[a-z]*|nocite)(\\[[^]]*\\])?(\\[[^]]*\\])?\\{([^}]+)\\}/\\4/' | \\\n tr ',' '\\n' | \\\n sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \\\n grep -v '^

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

|| true\n}\n\n# --- Extract citation keys from .bib file ---\nextract_bib_keys() {\n local bib_file=\"$1\"\n\n # Extract @article{key, @book{key, etc.\n grep -oP '@[a-zA-Z]+\\{\\K[^,\\}]+' \"$bib_file\" 2>/dev/null | \\\n sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \\\n grep -v '^

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

| \\\n sort -u || true\n}\n\n# --- Count citations ---\ncount_citations() {\n local citations=\"$1\"\n\n # Count occurrences of each citation\n echo \"$citations\" | sort | uniq -c | sort -rn\n}\n\n# --- Main extraction ---\nif [[ \"$FORMAT\" == \"text\" ]]; then\n echo \":: Analyzing citations in: $INPUT_TEX\" >&2\n echo \"\" >&2\nfi\n\n# Auto-detect bib file if not specified\nif [[ -z \"$BIB_FILE\" ]]; then\n BIB_FILE=$(detect_bib_file \"$INPUT_TEX\" \"$INPUT_DIR\")\n if [[ -n \"$BIB_FILE\" ]]; then\n if [[ \"$FORMAT\" == \"text\" ]]; then\n echo \":: Auto-detected bibliography: $BIB_FILE\" >&2\n echo \"\" >&2\n fi\n else\n if [[ \"$CHECK\" == true ]]; then\n echo \"Warning: No bibliography file found. Cannot verify citations.\" >&2\n echo \"Specify with --bib \u003cfile.bib>\" >&2\n echo \"\" >&2\n fi\n fi\nelif [[ ! -f \"$BIB_FILE\" ]]; then\n # If user specified a relative path, try relative to tex file\n if [[ ! \"$BIB_FILE\" =~ ^/ ]]; then\n BIB_FILE=\"${INPUT_DIR}/${BIB_FILE}\"\n fi\n if [[ ! -f \"$BIB_FILE\" ]]; then\n echo \"Error: Bibliography file not found: $BIB_FILE\" >&2\n exit 1\n fi\nfi\n\n# Extract citations\nCITATIONS=$(extract_citations \"$INPUT_TEX\")\n\nif [[ -z \"$CITATIONS\" ]]; then\n if [[ \"$FORMAT\" == \"text\" ]]; then\n echo \"No citations found in document.\"\n else\n echo '{\"citations\":[],\"total\":0,\"unique\":0}'\n fi\n exit 0\nfi\n\n# Count unique citations\nUNIQUE_CITATIONS=$(echo \"$CITATIONS\" | sort -u)\nTOTAL_CITATIONS=$(echo \"$CITATIONS\" | wc -l)\nUNIQUE_COUNT=$(echo \"$UNIQUE_CITATIONS\" | wc -l)\n\n# Get counts per citation\nCITATION_COUNTS=$(count_citations \"$CITATIONS\")\n\n# Extract bib keys if checking\nif [[ \"$CHECK\" == true && -n \"$BIB_FILE\" ]]; then\n BIB_KEYS=$(extract_bib_keys \"$BIB_FILE\")\nfi\n\n# --- Output in requested format ---\nif [[ \"$FORMAT\" == \"json\" ]]; then\n # JSON output\n echo \"{\"\n echo \" \\\"source_file\\\": \\\"$INPUT_TEX\\\",\"\n echo \" \\\"bib_file\\\": \\\"${BIB_FILE:-null}\\\",\"\n echo \" \\\"total_citations\\\": $TOTAL_CITATIONS,\"\n echo \" \\\"unique_citations\\\": $UNIQUE_COUNT,\"\n echo \" \\\"citations\\\": [\"\n\n first=true\n while IFS= read -r line; do\n count=$(echo \"$line\" | awk '{print $1}')\n key=$(echo \"$line\" | awk '{$1=\"\"; print $0}' | sed 's/^[[:space:]]*//')\n\n if [[ \"$first\" == true ]]; then\n first=false\n else\n echo \",\"\n fi\n\n echo -n \" {\\\"key\\\":\\\"$key\\\",\\\"count\\\":$count\"\n\n # Check if in bib file\n if [[ \"$CHECK\" == true && -n \"$BIB_FILE\" ]]; then\n if echo \"$BIB_KEYS\" | grep -qx \"$key\"; then\n echo -n \",\\\"in_bib\\\":true}\"\n else\n echo -n \",\\\"in_bib\\\":false}\"\n fi\n else\n echo -n \"}\"\n fi\n done \u003c\u003c\u003c \"$CITATION_COUNTS\"\n\n echo \"\"\n\n # Add missing citations if checking\n if [[ \"$CHECK\" == true && -n \"$BIB_FILE\" ]]; then\n echo \" ],\"\n echo -n \" \\\"missing_citations\\\": [\"\n\n MISSING=()\n while IFS= read -r cite_key; do\n if ! echo \"$BIB_KEYS\" | grep -qx \"$cite_key\"; then\n MISSING+=(\"$cite_key\")\n fi\n done \u003c\u003c\u003c \"$UNIQUE_CITATIONS\"\n\n first=true\n for key in \"${MISSING[@]}\"; do\n if [[ \"$first\" == true ]]; then\n first=false\n else\n echo -n \",\"\n fi\n echo -n \"\\\"$key\\\"\"\n done\n echo \"]\"\n else\n echo \" ]\"\n fi\n\n echo \"}\"\nelse\n # Text output\n echo \"=== Citation Analysis ===\"\n echo \"Total citations: $TOTAL_CITATIONS\"\n echo \"Unique citations: $UNIQUE_COUNT\"\n echo \"\"\n echo \"Citations by frequency:\"\n echo \"\"\n\n while IFS= read -r line; do\n count=$(echo \"$line\" | awk '{print $1}')\n key=$(echo \"$line\" | awk '{$1=\"\"; print $0}' | sed 's/^[[:space:]]*//')\n\n printf \" [%3d] %s\" \"$count\" \"$key\"\n\n # Check if in bib file\n if [[ \"$CHECK\" == true && -n \"$BIB_FILE\" ]]; then\n if echo \"$BIB_KEYS\" | grep -qx \"$key\"; then\n echo \" ✓\"\n else\n echo \" ✗ MISSING\"\n fi\n else\n echo \"\"\n fi\n done \u003c\u003c\u003c \"$CITATION_COUNTS\"\n\n # Summary of missing citations\n if [[ \"$CHECK\" == true && -n \"$BIB_FILE\" ]]; then\n echo \"\"\n\n MISSING=()\n while IFS= read -r cite_key; do\n if ! echo \"$BIB_KEYS\" | grep -qx \"$cite_key\"; then\n MISSING+=(\"$cite_key\")\n fi\n done \u003c\u003c\u003c \"$UNIQUE_CITATIONS\"\n\n if [[ ${#MISSING[@]} -gt 0 ]]; then\n echo \"=== Missing Citations ===\"\n echo \"The following ${#MISSING[@]} citation(s) are not in $BIB_FILE:\"\n echo \"\"\n for key in \"${MISSING[@]}\"; do\n echo \" ✗ $key\"\n done\n echo \"\"\n echo \"Add these entries to your bibliography file or remove the citations.\"\n exit 1\n else\n echo \"=== Verification ===\"\n echo \"✓ All citations are present in bibliography file\"\n fi\n fi\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":9414,"content_sha256":"16909e270683a4b8aaa2e99b9e3b7dcb5ded9d3bf55ca77e93e6c4c07c25c914"},{"filename":"scripts/latex_diff.sh","content":"#!/usr/bin/env bash\n# latex_diff.sh - Generate highlighted change-tracked PDFs between two LaTeX document versions\n#\n# Usage:\n# latex_diff.sh OLD.tex NEW.tex [OPTIONS]\n# latex_diff.sh OLD.tex NEW.tex --git # Use git for OLD version\n# latex_diff.sh document.tex --git-rev HEAD~1 # Diff against git revision\n# latex_diff.sh document.tex --git-rev v1.0..v2.0 # Diff between two git tags\n#\n# Options:\n# --output FILE Output diff .tex file (default: diff_OLD_NEW.tex)\n# --output-dir DIR Output directory (default: same as NEW file)\n# --type TYPE Markup type: UNDERLINE (default), CTRADITIONAL, CFONT,\n# CHANGEBAR, CCHANGEBAR, CULINECHBAR, FONTSTRIKE, INVISIBLE\n# --subtype SUBTYPE Markup subtype: SAFE (default), IDENTICAL, BOLD, COLOR,\n# LABEL, DVIPSCOL, ZLABEL, ONLYCHANGEDPAGE\n# --flatten Expand \\input and \\include before diffing (for multi-file docs)\n# --math-markup MODE Math markup: fine (default), coarse, off, whole\n# --color-add COLOR Color for additions (default: blue)\n# --color-del COLOR Color for deletions (default: red)\n# --compile Auto-compile the diff to PDF\n# --preview Compile and generate PNG preview\n# --compile-script Path to compile_latex.sh for compilation\n# --git-rev REV Diff current file against a git revision\n# --exclude-safecmd Comma-separated commands to exclude from safe cmd list\n# --exclude-textcmd Comma-separated commands to exclude from text cmd list\n# --packages PKGS Comma-separated packages to add to preamble\n# --verbose Show detailed latexdiff output\n# --help Show this help\n#\n# Markup Types:\n# UNDERLINE - Additions underlined in blue, deletions struck through in red (default)\n# CTRADITIONAL - Additions in blue, deletions in red with strikethrough (traditional)\n# CFONT - Additions in sans-serif blue, deletions in tiny red\n# CHANGEBAR - Change bars in margin, no inline markup\n# CCHANGEBAR - Change bars + color changes\n# CULINECHBAR - Underline + change bars (most comprehensive)\n# FONTSTRIKE - Font change + strikethrough\n# INVISIBLE - No visible markup (for testing)\n#\n# Examples:\n# # Basic diff between two files\n# latex_diff.sh paper_v1.tex paper_v2.tex --compile --preview\n#\n# # Diff with git (current vs last commit)\n# latex_diff.sh paper.tex --git-rev HEAD~1 --compile\n#\n# # Diff between two git tags\n# latex_diff.sh paper.tex --git-rev v1.0 --compile --type CULINECHBAR\n#\n# # Multi-file document diff\n# latex_diff.sh thesis_v1/main.tex thesis_v2/main.tex --flatten --compile\n#\n# # Custom colors\n# latex_diff.sh old.tex new.tex --color-add \"green!70!black\" --color-del \"red!80!black\"\n\nset -euo pipefail\n\n# --- Parse arguments ---\nOLD_FILE=\"\"\nNEW_FILE=\"\"\nOUTPUT_FILE=\"\"\nOUTPUT_DIR=\"\"\nMARKUP_TYPE=\"UNDERLINE\"\nMARKUP_SUBTYPE=\"\"\nMATH_MARKUP=\"\"\nFLATTEN=false\nCOMPILE=false\nPREVIEW=false\nCOMPILE_SCRIPT=\"\"\nGIT_REV=\"\"\nCOLOR_ADD=\"blue\"\nCOLOR_DEL=\"red\"\nEXCLUDE_SAFECMD=\"\"\nEXCLUDE_TEXTCMD=\"\"\nEXTRA_PACKAGES=\"\"\nVERBOSE=false\n\nshow_help() {\n sed -n '2,/^$/p' \"$0\" | sed 's/^# \\?//'\n exit 0\n}\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) show_help ;;\n --output) OUTPUT_FILE=\"$2\"; shift 2 ;;\n --output-dir) OUTPUT_DIR=\"$2\"; shift 2 ;;\n --type) MARKUP_TYPE=\"$2\"; shift 2 ;;\n --subtype) MARKUP_SUBTYPE=\"$2\"; shift 2 ;;\n --math-markup) MATH_MARKUP=\"$2\"; shift 2 ;;\n --flatten) FLATTEN=true; shift ;;\n --compile) COMPILE=true; shift ;;\n --preview) PREVIEW=true; COMPILE=true; shift ;;\n --compile-script) COMPILE_SCRIPT=\"$2\"; shift 2 ;;\n --git-rev) GIT_REV=\"$2\"; shift 2 ;;\n --color-add) COLOR_ADD=\"$2\"; shift 2 ;;\n --color-del) COLOR_DEL=\"$2\"; shift 2 ;;\n --exclude-safecmd) EXCLUDE_SAFECMD=\"$2\"; shift 2 ;;\n --exclude-textcmd) EXCLUDE_TEXTCMD=\"$2\"; shift 2 ;;\n --packages) EXTRA_PACKAGES=\"$2\"; shift 2 ;;\n --verbose|-v) VERBOSE=true; shift ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *)\n if [[ -z \"$OLD_FILE\" ]]; then\n OLD_FILE=\"$1\"\n elif [[ -z \"$NEW_FILE\" ]]; then\n NEW_FILE=\"$1\"\n else\n echo \"Error: Too many positional arguments\" >&2; exit 1\n fi\n shift ;;\n esac\ndone\n\n# --- Validate inputs ---\n\n# Git revision mode: only one file needed\nif [[ -n \"$GIT_REV\" ]]; then\n if [[ -z \"$OLD_FILE\" ]]; then\n echo \"Error: No .tex file specified\" >&2\n exit 1\n fi\n NEW_FILE=\"$OLD_FILE\"\n # OLD_FILE will be extracted from git\nfi\n\nif [[ -z \"$OLD_FILE\" ]]; then\n echo \"Error: No input files specified\" >&2\n echo \"Usage: latex_diff.sh OLD.tex NEW.tex [OPTIONS]\" >&2\n echo \" latex_diff.sh FILE.tex --git-rev REV [OPTIONS]\" >&2\n exit 1\nfi\n\nif [[ -z \"$GIT_REV\" && -z \"$NEW_FILE\" ]]; then\n echo \"Error: Need two files or --git-rev option\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$NEW_FILE\" ]]; then\n echo \"Error: File not found: $NEW_FILE\" >&2\n exit 1\nfi\n\nif [[ -z \"$GIT_REV\" && ! -f \"$OLD_FILE\" ]]; then\n echo \"Error: File not found: $OLD_FILE\" >&2\n exit 1\nfi\n\n# --- Ensure latexdiff is installed ---\nensure_latexdiff() {\n if command -v latexdiff &>/dev/null; then\n if [[ \"$VERBOSE\" == true ]]; then\n echo \":: latexdiff found: $(latexdiff --version 2>&1 | head -1)\" >&2\n fi\n return 0\n fi\n\n echo \":: latexdiff not found. Installing...\" >&2\n if command -v sudo &>/dev/null; then\n sudo apt-get update -q >&2 2>/dev/null\n sudo apt-get install -y -q latexdiff >&2 || {\n echo \"Error: Failed to install latexdiff\" >&2\n exit 1\n }\n elif command -v apt-get &>/dev/null; then\n apt-get update -q >&2 2>/dev/null\n apt-get install -y -q latexdiff >&2 || {\n echo \"Error: Failed to install latexdiff\" >&2\n exit 1\n }\n else\n echo \"Error: Cannot install latexdiff - apt-get not available\" >&2\n echo \"Install manually: sudo apt-get install latexdiff\" >&2\n exit 1\n fi\n\n if ! command -v latexdiff &>/dev/null; then\n echo \"Error: latexdiff still not available after install\" >&2\n exit 1\n fi\n echo \":: latexdiff installed successfully\" >&2\n}\n\n# --- Git revision extraction ---\nextract_git_version() {\n local file=\"$1\"\n local rev=\"$2\"\n local tmpfile=\"$3\"\n\n # Check we're in a git repo\n if ! git rev-parse --git-dir &>/dev/null 2>&1; then\n echo \"Error: Not in a git repository\" >&2\n exit 1\n fi\n\n # Get the file path relative to repo root\n local repo_root\n repo_root=$(git rev-parse --show-toplevel)\n local rel_path\n rel_path=$(realpath --relative-to=\"$repo_root\" \"$file\" 2>/dev/null || echo \"$file\")\n\n echo \":: Extracting $rel_path at revision $rev...\" >&2\n\n if git show \"${rev}:${rel_path}\" > \"$tmpfile\" 2>/dev/null; then\n return 0\n else\n # Try with just the filename\n if git show \"${rev}:$(basename \"$file\")\" > \"$tmpfile\" 2>/dev/null; then\n return 0\n fi\n echo \"Error: Cannot find $rel_path at revision $rev\" >&2\n echo \" Tried: git show ${rev}:${rel_path}\" >&2\n exit 1\n fi\n}\n\n# --- Build latexdiff command ---\nbuild_diff_cmd() {\n local old=\"$1\"\n local new=\"$2\"\n local output=\"$3\"\n\n local cmd=(latexdiff)\n\n # Markup type\n cmd+=(--type=\"$MARKUP_TYPE\")\n\n # Subtype\n if [[ -n \"$MARKUP_SUBTYPE\" ]]; then\n cmd+=(--subtype=\"$MARKUP_SUBTYPE\")\n fi\n\n # Math markup\n if [[ -n \"$MATH_MARKUP\" ]]; then\n cmd+=(--math-markup=\"$MATH_MARKUP\")\n fi\n\n # Flatten for multi-file documents\n if [[ \"$FLATTEN\" == true ]]; then\n cmd+=(--flatten)\n fi\n\n # Exclude commands\n if [[ -n \"$EXCLUDE_SAFECMD\" ]]; then\n cmd+=(--exclude-safecmd=\"$EXCLUDE_SAFECMD\")\n fi\n\n if [[ -n \"$EXCLUDE_TEXTCMD\" ]]; then\n cmd+=(--exclude-textcmd=\"$EXCLUDE_TEXTCMD\")\n fi\n\n # Extra packages\n if [[ -n \"$EXTRA_PACKAGES\" ]]; then\n cmd+=(--packages=\"$EXTRA_PACKAGES\")\n fi\n\n # Allow spaces in labels/refs\n cmd+=(--allow-spaces)\n\n # Input files\n cmd+=(\"$old\" \"$new\")\n\n # Store command in global array for direct execution (avoids eval)\n DIFF_CMD_ARRAY=(\"${cmd[@]}\")\n}\n\n# --- Custom color preamble injection ---\ninject_custom_colors() {\n local diff_file=\"$1\"\n local color_add=\"$2\"\n local color_del=\"$3\"\n\n # Only inject if non-default colors\n if [[ \"$color_add\" == \"blue\" && \"$color_del\" == \"red\" ]]; then\n return\n fi\n\n # Create color override commands\n local color_cmds=\"\"\n if [[ \"$color_add\" != \"blue\" ]]; then\n color_cmds+=\"\\\\\\providecommand{\\\\\\\\DIFaddcolor}{\\\\\\\\color{${color_add}}}\\n\"\n fi\n if [[ \"$color_del\" != \"red\" ]]; then\n color_cmds+=\"\\\\\\providecommand{\\\\\\\\DIFdelcolor}{\\\\\\\\color{${color_del}}}\\n\"\n fi\n\n if [[ -n \"$color_cmds\" ]]; then\n # Insert after \\begin{document}\n sed -i \"/\\\\\\\\begin{document}/a\\\\\n${color_cmds}\" \"$diff_file\"\n fi\n}\n\n# --- Main execution ---\n\nensure_latexdiff\n\n# Resolve paths\nNEW_FILE=\"$(realpath \"$NEW_FILE\")\"\nNEW_DIR=\"$(dirname \"$NEW_FILE\")\"\nNEW_BASE=\"$(basename \"$NEW_FILE\" .tex)\"\n\nif [[ -z \"$OUTPUT_DIR\" ]]; then\n OUTPUT_DIR=\"$NEW_DIR\"\nfi\nmkdir -p \"$OUTPUT_DIR\"\n\n# Handle git revision mode\nCLEANUP_TMP=false\nif [[ -n \"$GIT_REV\" ]]; then\n TMP_OLD=$(mktemp /tmp/latexdiff_old_XXXXXX.tex)\n CLEANUP_TMP=true\n extract_git_version \"$NEW_FILE\" \"$GIT_REV\" \"$TMP_OLD\"\n OLD_FILE=\"$TMP_OLD\"\n\n # Default output name for git mode\n if [[ -z \"$OUTPUT_FILE\" ]]; then\n SAFE_REV=$(echo \"$GIT_REV\" | tr '/:~^' '____')\n OUTPUT_FILE=\"${OUTPUT_DIR}/diff_${SAFE_REV}_vs_current_${NEW_BASE}.tex\"\n fi\nelse\n OLD_FILE=\"$(realpath \"$OLD_FILE\")\"\n OLD_BASE=\"$(basename \"$OLD_FILE\" .tex)\"\n\n if [[ -z \"$OUTPUT_FILE\" ]]; then\n OUTPUT_FILE=\"${OUTPUT_DIR}/diff_${OLD_BASE}_vs_${NEW_BASE}.tex\"\n fi\nfi\n\necho \":: Generating diff...\"\necho \" Old: $(basename \"$OLD_FILE\")\"\necho \" New: $(basename \"$NEW_FILE\")\"\necho \" Type: $MARKUP_TYPE\"\necho \" Output: $OUTPUT_FILE\"\n\n# Build and run latexdiff\nDIFF_CMD_ARRAY=()\nbuild_diff_cmd \"$OLD_FILE\" \"$NEW_FILE\" \"$OUTPUT_FILE\"\n\nif [[ \"$VERBOSE\" == true ]]; then\n echo \":: Running: ${DIFF_CMD_ARRAY[*]}\" >&2\nfi\n\nif \"${DIFF_CMD_ARRAY[@]}\" > \"$OUTPUT_FILE\" 2>/tmp/latexdiff_stderr.txt; then\n echo \":: Diff generated: $OUTPUT_FILE\"\nelse\n STDERR=$(cat /tmp/latexdiff_stderr.txt)\n # latexdiff often writes warnings to stderr but still produces output\n if [[ -s \"$OUTPUT_FILE\" ]]; then\n echo \":: Diff generated with warnings: $OUTPUT_FILE\" >&2\n if [[ \"$VERBOSE\" == true ]]; then\n echo \":: Warnings: $STDERR\" >&2\n fi\n else\n echo \"Error: latexdiff failed\" >&2\n echo \"$STDERR\" >&2\n [[ \"$CLEANUP_TMP\" == true ]] && rm -f \"$TMP_OLD\"\n exit 1\n fi\nfi\n\n# Inject custom colors\ninject_custom_colors \"$OUTPUT_FILE\" \"$COLOR_ADD\" \"$COLOR_DEL\"\n\n# Cleanup temp files\n[[ \"$CLEANUP_TMP\" == true ]] && rm -f \"$TMP_OLD\"\n\n# --- Compile diff ---\nif [[ \"$COMPILE\" == true ]]; then\n echo \":: Compiling diff PDF...\"\n\n COMPILE_CMD_ARRAY=()\n if [[ -n \"$COMPILE_SCRIPT\" ]]; then\n COMPILE_CMD_ARRAY=(bash \"$COMPILE_SCRIPT\" \"$OUTPUT_FILE\")\n if [[ \"$PREVIEW\" == true ]]; then\n COMPILE_CMD_ARRAY+=(--preview --preview-dir \"$OUTPUT_DIR\")\n fi\n else\n # Find compile_latex.sh relative to this script\n SCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\n if [[ -f \"${SCRIPT_DIR}/compile_latex.sh\" ]]; then\n COMPILE_CMD_ARRAY=(bash \"${SCRIPT_DIR}/compile_latex.sh\" \"$OUTPUT_FILE\")\n if [[ \"$PREVIEW\" == true ]]; then\n COMPILE_CMD_ARRAY+=(--preview --preview-dir \"$OUTPUT_DIR\")\n fi\n else\n # Direct compilation fallback\n ENGINE=\"pdflatex\"\n # Auto-detect engine from the diff file\n if grep -qE '\\\\usepackage\\{fontspec\\}|\\\\usepackage\\{xeCJK\\}' \"$OUTPUT_FILE\" 2>/dev/null; then\n ENGINE=\"xelatex\"\n fi\n COMPILE_CMD_ARRAY=(\"$ENGINE\" -interaction=nonstopmode -output-directory \"$(dirname \"$OUTPUT_FILE\")\" \"$OUTPUT_FILE\")\n fi\n fi\n\n if [[ \"$VERBOSE\" == true ]]; then\n echo \":: Running: ${COMPILE_CMD_ARRAY[*]}\" >&2\n fi\n\n if \"${COMPILE_CMD_ARRAY[@]}\"; then\n PDF_FILE=\"${OUTPUT_FILE%.tex}.pdf\"\n if [[ -f \"$PDF_FILE\" ]]; then\n echo \":: Diff PDF: $PDF_FILE\"\n fi\n else\n echo \":: Compilation had errors (diff PDF may still be usable)\" >&2\n fi\nfi\n\necho \":: Done.\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":12802,"content_sha256":"7e18d293b1ea52cdcee6d6603a25791eab399b4e3022d872fb1e0c6d6f8d6be5"},{"filename":"scripts/latex_lint.sh","content":"#!/usr/bin/env bash\n\n# latex_lint.sh\n# Run chktex on a .tex file with human-readable formatted output\n#\n# Examples:\n# ./latex_lint.sh document.tex\n# ./latex_lint.sh document.tex --strict\n# ./latex_lint.sh document.tex --quiet\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nSTRICT=false\nQUIET=false\n\n# ANSI color codes\nRED='\\033[0;31m'\nYELLOW='\\033[1;33m'\nGREEN='\\033[0;32m'\nBLUE='\\033[0;34m'\nNC='\\033[0m' # No Color\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cfile.tex> [OPTIONS]\n\nRun chktex on a LaTeX file with formatted output.\n\nArguments:\n file.tex Input LaTeX file to lint\n\nOptions:\n --strict Treat all warnings as errors (exit 1 if any)\n --quiet Only show count summary\n -h, --help Show this help message\n\nExamples:\n $0 document.tex\n $0 document.tex --strict\n $0 document.tex --quiet\n\nRequires: chktex (auto-installed if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nTEX_FILE=\"\"\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --strict)\n STRICT=true\n shift\n ;;\n --quiet)\n QUIET=true\n shift\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n if [[ -z \"$TEX_FILE\" ]]; then\n TEX_FILE=\"$1\"\n else\n echo \"Error: Multiple input files specified\" >&2\n exit 1\n fi\n shift\n ;;\n esac\ndone\n\n# Validate input file\nif [[ -z \"$TEX_FILE\" ]]; then\n echo \"Error: No input file specified\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$TEX_FILE\" ]]; then\n echo \"Error: Input file not found: $TEX_FILE\" >&2\n exit 1\nfi\n\n# Check for chktex, install if missing\nif ! command -v chktex &>/dev/null; then\n echo \"chktex not found. Installing...\" >&2\n\n # Map chktex to platform packages\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt) run_pkg_install chktex ;;\n brew) run_pkg_install chktex ;;\n dnf) run_pkg_install chktex ;;\n apk) run_pkg_install chktex ;;\n pacman) run_pkg_install chktex ;;\n *)\n echo \"Error: Could not auto-install chktex\" >&2\n echo \"Please install manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install chktex\" >&2\n echo \" macOS: brew install chktex\" >&2\n echo \" Fedora/RHEL: sudo dnf install chktex\" >&2\n echo \" Alpine: sudo apk add chktex\" >&2\n echo \" Arch: sudo pacman -S chktex\" >&2\n exit 1\n ;;\n esac\n\n if ! command -v chktex &>/dev/null; then\n echo \"Error: chktex installation failed\" >&2\n exit 1\n fi\nfi\n\n# Run chktex and capture output\nTEMP_OUTPUT=$(mktemp)\ntrap \"rm -f $TEMP_OUTPUT\" EXIT\n\n# Build chktex command with optional .chktexrc config\nCHKTEX_ARGS=(-q -v0)\n# Look for .chktexrc in skill root (parent of scripts dir)\nSKILL_CHKTEXRC=\"${SCRIPT_DIR}/../.chktexrc\"\nif [[ -f \"$SKILL_CHKTEXRC\" ]]; then\n CHKTEX_ARGS+=(-l \"$SKILL_CHKTEXRC\")\nfi\n\n# Run chktex (ignore exit code for now)\nchktex \"${CHKTEX_ARGS[@]}\" \"$TEX_FILE\" > \"$TEMP_OUTPUT\" 2>&1 || true\n\n# Count warnings and errors (match chktex output format: \"Warning N in ...\" / \"Error N in ...\")\nWARNING_COUNT=$(grep -cE \"^Warning [0-9]+ in \" \"$TEMP_OUTPUT\" || true)\nERROR_COUNT=$(grep -cE \"^Error [0-9]+ in \" \"$TEMP_OUTPUT\" || true)\nTOTAL_COUNT=$((WARNING_COUNT + ERROR_COUNT))\n\n# Display output\nif [[ \"$QUIET\" == false ]] && [[ -s \"$TEMP_OUTPUT\" ]]; then\n echo -e \"${BLUE}Linting $TEX_FILE...${NC}\" >&2\n echo \"\" >&2\n\n while IFS= read -r line; do\n if [[ \"$line\" =~ \"Warning\" ]]; then\n echo -e \"${YELLOW}$line${NC}\" >&2\n elif [[ \"$line\" =~ \"Error\" ]]; then\n echo -e \"${RED}$line${NC}\" >&2\n else\n echo \"$line\" >&2\n fi\n done \u003c \"$TEMP_OUTPUT\"\n echo \"\" >&2\nfi\n\n# Display summary\nif [[ $TOTAL_COUNT -eq 0 ]]; then\n echo -e \"${GREEN}✓ No issues found${NC}\" >&2\n exit 0\nelse\n if [[ $ERROR_COUNT -gt 0 ]]; then\n echo -e \"${RED}✗ Found $ERROR_COUNT error(s) and $WARNING_COUNT warning(s)${NC}\" >&2\n else\n echo -e \"${YELLOW}⚠ Found $WARNING_COUNT warning(s)${NC}\" >&2\n fi\n\n # Exit with error if strict mode or if there are actual errors\n if [[ \"$STRICT\" == true ]] || [[ $ERROR_COUNT -gt 0 ]]; then\n exit 1\n fi\nfi\n\nexit 0\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4691,"content_sha256":"b6b438309dbbd6bfedfdb98aed62b8e0a4aa37bcd7e4912309d876117048ebeb"},{"filename":"scripts/latex_package_check.sh","content":"#!/usr/bin/env bash\n# latex_package_check.sh - Pre-flight check for LaTeX package availability\n#\n# Usage:\n# latex_package_check.sh \u003cinput.tex> [--install] [--verbose]\n#\n# Options:\n# --install Attempt to install missing packages via tlmgr\n# --verbose Show check details for each package\n#\n# Features:\n# - Scans .tex file for \\usepackage commands\n# - Checks availability with kpsewhich\n# - Reports available and missing packages\n# - Optional auto-install with tlmgr\n# - Provides install suggestions for missing packages\n# - Detects documentclass and checks availability\n#\n# Examples:\n# latex_package_check.sh document.tex\n# latex_package_check.sh paper.tex --verbose\n# latex_package_check.sh report.tex --install\n# latex_package_check.sh thesis.tex --install --verbose\n\nset -euo pipefail\n\n# --- Usage function ---\nusage() {\n cat \u003c\u003c'EOF'\nlatex_package_check.sh - Pre-flight check for LaTeX package availability\n\nUsage:\n latex_package_check.sh \u003cinput.tex> [--install] [--verbose]\n\nOptions:\n --install Attempt to install missing packages via tlmgr\n --verbose Show check details for each package\n\nFeatures:\n - Scans .tex file for \\usepackage commands\n - Checks availability with kpsewhich\n - Reports available and missing packages\n - Optional auto-install with tlmgr\n - Provides install suggestions for missing packages\n - Detects documentclass and checks availability\n\nExamples:\n latex_package_check.sh document.tex\n latex_package_check.sh paper.tex --verbose\n latex_package_check.sh report.tex --install\n latex_package_check.sh thesis.tex --install --verbose\nEOF\n}\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# --- Parse arguments ---\nINPUT_TEX=\"\"\nINSTALL=false\nVERBOSE=false\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) usage; exit 0 ;;\n --install) INSTALL=true; shift ;;\n --verbose) VERBOSE=true; shift ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *) INPUT_TEX=\"$1\"; shift ;;\n esac\ndone\n\nif [[ -z \"$INPUT_TEX\" ]]; then\n echo \"Error: No input .tex file specified\" >&2\n echo \"Usage: latex_package_check.sh \u003cinput.tex> [--install] [--verbose]\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_TEX\" ]]; then\n echo \"Error: File not found: $INPUT_TEX\" >&2\n exit 1\nfi\n\n# Resolve absolute path\nINPUT_TEX=\"$(realpath \"$INPUT_TEX\")\"\n\n# --- Ensure LaTeX is installed ---\nensure_latex() {\n if command -v kpsewhich &>/dev/null; then\n return 0\n fi\n echo \":: LaTeX (kpsewhich) not found. Installing TeX Live...\" >&2\n install_packages \"texlive\" || {\n echo \"Error: Failed to install TeX Live.\" >&2\n print_install_help \"texlive\"\n exit 1\n }\n _brew_post_texlive\n if ! command -v kpsewhich &>/dev/null; then\n echo \"Error: kpsewhich still not available after install\" >&2\n exit 1\n fi\n echo \":: TeX Live installed successfully\" >&2\n}\n\n# --- Extract packages from .tex file ---\nextract_packages() {\n local tex_file=\"$1\"\n\n # Extract \\usepackage{...} and \\usepackage[...]{...}\n # Handle multi-line \\usepackage commands and comma-separated packages\n grep -oP '\\\\usepackage(?:\\[[^\\]]*\\])?\\{[^\\}]+\\}' \"$tex_file\" 2>/dev/null | \\\n sed -E 's/\\\\usepackage(\\[[^\\]]*\\])?\\{([^\\}]+)\\}/\\2/' | \\\n tr ',' '\\n' | \\\n sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | \\\n grep -v '^

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

| \\\n sort -u || true\n}\n\n# --- Extract document class ---\nextract_documentclass() {\n local tex_file=\"$1\"\n grep -oP '\\\\documentclass(?:\\[[^\\]]*\\])?\\{\\K[^\\}]+' \"$tex_file\" 2>/dev/null | head -1\n}\n\n# --- Check if package is available ---\ncheck_package() {\n local package=\"$1\"\n kpsewhich \"${package}.sty\" &>/dev/null\n}\n\n# --- Check if document class is available ---\ncheck_documentclass() {\n local docclass=\"$1\"\n kpsewhich \"${docclass}.cls\" &>/dev/null\n}\n\n# --- Install package with tlmgr ---\ninstall_package() {\n local package=\"$1\"\n\n if ! command -v tlmgr &>/dev/null; then\n echo \" → tlmgr not available (TeX Live package manager)\" >&2\n return 1\n fi\n\n echo \" → Installing $package via tlmgr...\" >&2\n tlmgr install \"$package\" 2>&1 | grep -v \"^tlmgr: package repository\" | grep -v \"^$\" >&2 || {\n # Try updating tlmgr first, then retry\n echo \" → Updating tlmgr and retrying...\" >&2\n tlmgr update --self 2>&1 | grep -v \"^tlmgr: package repository\" >&2 || true\n tlmgr install \"$package\" 2>&1 | grep -v \"^tlmgr: package repository\" | grep -v \"^$\" >&2\n }\n}\n\n# --- Main check ---\nensure_latex\n\necho \":: Checking LaTeX packages for: $INPUT_TEX\" >&2\necho \"\" >&2\n\n# Check document class\nDOCCLASS=$(extract_documentclass \"$INPUT_TEX\")\nif [[ -n \"$DOCCLASS\" ]]; then\n echo \"Document class: $DOCCLASS\"\n if check_documentclass \"$DOCCLASS\"; then\n if [[ \"$VERBOSE\" == true ]]; then\n echo \" ✓ Available\"\n fi\n else\n echo \" ✗ MISSING\"\n if [[ \"$INSTALL\" == true ]]; then\n install_package \"$DOCCLASS\" && echo \" ✓ Installed successfully\" || echo \" ✗ Installation failed\"\n else\n echo \" → Install with: tlmgr install $DOCCLASS\"\n fi\n fi\n echo \"\"\nfi\n\n# Extract and check packages\nPACKAGES=$(extract_packages \"$INPUT_TEX\")\n\nif [[ -z \"$PACKAGES\" ]]; then\n echo \"No packages found in document.\"\n exit 0\nfi\n\nPACKAGE_COUNT=$(echo \"$PACKAGES\" | wc -l)\necho \"Found $PACKAGE_COUNT package(s) to check:\"\necho \"\"\n\nAVAILABLE=()\nMISSING=()\n\nwhile IFS= read -r package; do\n if [[ -z \"$package\" ]]; then\n continue\n fi\n\n if [[ \"$VERBOSE\" == true ]]; then\n echo -n \"Checking: $package ... \"\n fi\n\n if check_package \"$package\"; then\n AVAILABLE+=(\"$package\")\n if [[ \"$VERBOSE\" == true ]]; then\n echo \"✓ Available\"\n fi\n else\n MISSING+=(\"$package\")\n if [[ \"$VERBOSE\" == true ]]; then\n echo \"✗ MISSING\"\n else\n echo \"✗ MISSING: $package\"\n fi\n\n if [[ \"$INSTALL\" == true ]]; then\n install_package \"$package\" && {\n # Verify installation\n if check_package \"$package\"; then\n echo \" ✓ Installed successfully\"\n # Move from MISSING to AVAILABLE\n AVAILABLE+=(\"$package\")\n unset 'MISSING[-1]'\n else\n echo \" ✗ Installation failed or package not found\"\n fi\n }\n else\n echo \" → Install with: tlmgr install $package\"\n echo \" → Or: sudo apt-get install texlive-latex-extra (Debian/Ubuntu)\"\n fi\n fi\ndone \u003c\u003c\u003c \"$PACKAGES\"\n\necho \"\"\necho \"=== Summary ===\"\necho \"Available: ${#AVAILABLE[@]} package(s)\"\necho \"Missing: ${#MISSING[@]} package(s)\"\n\nif [[ ${#MISSING[@]} -gt 0 ]]; then\n echo \"\"\n echo \"Missing packages:\"\n for pkg in \"${MISSING[@]}\"; do\n echo \" - $pkg\"\n done\n\n if [[ \"$INSTALL\" == false ]]; then\n echo \"\"\n echo \"To auto-install missing packages, run with --install flag\"\n echo \"\"\n echo \"Manual installation options:\"\n echo \" tlmgr install ${MISSING[*]}\"\n echo \" sudo apt-get install texlive-latex-extra (Debian/Ubuntu)\"\n echo \" sudo dnf install texlive-collection-latexextra (Fedora/RHEL)\"\n fi\n\n exit 1\nelse\n echo \"\"\n echo \"✓ All packages are available!\"\n exit 0\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":7101,"content_sha256":"b7df2878add86387a66786966fb6a747901de36d65f62838ea8bef59c9154b07"},{"filename":"scripts/latex_wordcount.sh","content":"#!/usr/bin/env bash\n\n# latex_wordcount.sh\n# Count words in a LaTeX document (stripping LaTeX commands)\n#\n# Examples:\n# ./latex_wordcount.sh document.tex\n# ./latex_wordcount.sh thesis.tex --detailed\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nDETAILED=false\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cfile.tex> [OPTIONS]\n\nCount words in a LaTeX document by stripping LaTeX commands.\n\nArguments:\n file.tex Input LaTeX file\n\nOptions:\n --detailed Show detailed statistics (figures, tables, equations, citations)\n -h, --help Show this help message\n\nExamples:\n $0 document.tex\n $0 thesis.tex --detailed\n\nRequires: detex (included in texlive)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nTEX_FILE=\"\"\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --detailed)\n DETAILED=true\n shift\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n if [[ -z \"$TEX_FILE\" ]]; then\n TEX_FILE=\"$1\"\n else\n echo \"Error: Multiple input files specified\" >&2\n exit 1\n fi\n shift\n ;;\n esac\ndone\n\n# Validate input file\nif [[ -z \"$TEX_FILE\" ]]; then\n echo \"Error: No input file specified\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$TEX_FILE\" ]]; then\n echo \"Error: Input file not found: $TEX_FILE\" >&2\n exit 1\nfi\n\n# Check for detex\nif ! command -v detex &>/dev/null; then\n echo \"Error: detex not found\" >&2\n echo \"detex is typically included with texlive\" >&2\n echo \"Please install texlive:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install texlive-extra-utils\" >&2\n echo \" macOS: brew install texlive\" >&2\n echo \" Fedora/RHEL: sudo dnf install texlive-scheme-medium\" >&2\n echo \" Alpine: sudo apk add texlive-full\" >&2\n echo \" Arch: sudo pacman -S texlive-most\" >&2\n exit 1\nfi\n\n# Count words using detex\nWORD_COUNT=$(detex \"$TEX_FILE\" 2>/dev/null | wc -w | tr -d ' ')\n\n# Basic output\necho \"Word count: $WORD_COUNT words\"\n\n# Estimate page count (250 words per page is standard)\nPAGES=$((WORD_COUNT / 250))\nif [[ $PAGES -gt 0 ]]; then\n echo \"Estimated pages: ~$PAGES pages (250 words/page)\"\nfi\n\n# Detailed statistics if requested\nif [[ \"$DETAILED\" == true ]]; then\n echo \"\"\n echo \"Detailed Statistics:\"\n echo \"===================\"\n\n # Count figures\n FIGURE_COUNT=$(grep -c '\\\\begin{figure}' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n echo \"Figures: $FIGURE_COUNT\"\n\n # Count tables\n TABLE_COUNT=$(grep -c '\\\\begin{table}' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n echo \"Tables: $TABLE_COUNT\"\n\n # Count equations (equation environment + align environment)\n EQUATION_COUNT=$(grep -c '\\\\begin{equation}' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n ALIGN_COUNT=$(grep -c '\\\\begin{align' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n TOTAL_EQUATIONS=$((EQUATION_COUNT + ALIGN_COUNT))\n echo \"Equations: $TOTAL_EQUATIONS\"\n\n # Count citations\n CITATION_COUNT=$(grep -o '\\\\cite{[^}]*}' \"$TEX_FILE\" 2>/dev/null | wc -l | tr -d ' ')\n echo \"Citations: $CITATION_COUNT\"\n\n # Count sections\n SECTION_COUNT=$(grep -c '^\\\\section{' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n SUBSECTION_COUNT=$(grep -c '^\\\\subsection{' \"$TEX_FILE\" 2>/dev/null || echo \"0\")\n echo \"\"\n echo \"Structure:\"\n echo \" Sections: $SECTION_COUNT\"\n echo \" Subsections: $SUBSECTION_COUNT\"\n\n # Character count (including spaces)\n CHAR_COUNT=$(detex \"$TEX_FILE\" 2>/dev/null | wc -c | tr -d ' ')\n echo \"\"\n echo \"Characters (with spaces): $CHAR_COUNT\"\n\n # Line count of raw .tex file\n LINE_COUNT=$(wc -l \u003c \"$TEX_FILE\" | tr -d ' ')\n echo \"LaTeX source lines: $LINE_COUNT\"\nfi\n\nexit 0\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4029,"content_sha256":"f723ec8b2db4850ad2cab003217cc22b9122537a130a8eeb44837d6f8fee59c2"},{"filename":"scripts/mail_merge.py","content":"#!/usr/bin/env python3\n\"\"\"\nmail_merge.py - Generate personalized LaTeX documents from templates + data sources.\n\nReads a LaTeX template with {{placeholder}} variables and a CSV or JSON data source,\ngenerates one .tex file per record, compiles each to PDF, and optionally merges all PDFs.\n\nSupports:\n - CSV and JSON data sources\n - Jinja2-style {{variable}} placeholders in LaTeX templates\n - Conditional sections: {% if variable %}...{% endif %}\n - Loop sections: {% for item in items %}...{% endfor %}\n - LaTeX special character auto-escaping in data values\n - Parallel compilation with configurable worker count\n - Output file naming from data fields\n - Merged PDF output (all documents in one file)\n - Error logging and graceful failure handling\n\nExamples:\n # Basic mail merge from CSV\n python3 mail_merge.py template.tex data.csv --output-dir ./outputs\n\n # Mail merge from JSON with custom naming\n python3 mail_merge.py template.tex students.json --output-dir ./outputs --name-field \"last_name\"\n\n # Merge all into single PDF\n python3 mail_merge.py template.tex data.csv --output-dir ./outputs --merge --merge-name \"all_letters.pdf\"\n\n # Parallel compilation (4 workers)\n python3 mail_merge.py template.tex data.csv --output-dir ./outputs --workers 4\n\n # Custom compile script\n python3 mail_merge.py template.tex data.csv --output-dir ./outputs --compile-script ./scripts/compile_latex.sh\n\nDependencies:\n - Python 3.7+\n - jinja2 (pip install jinja2)\n - pandas (pip install pandas) -- for CSV reading\n - pdflatex/xelatex/lualatex -- for compilation\n - pdfunite (from poppler-utils) -- for PDF merging (optional)\n\"\"\"\n\nimport argparse\nimport csv\nimport json\nimport os\nimport re\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\nfrom concurrent.futures import ProcessPoolExecutor, as_completed\nfrom pathlib import Path\n\n# Try importing optional dependencies\ntry:\n import jinja2\n HAS_JINJA2 = True\nexcept ImportError:\n HAS_JINJA2 = False\n\ntry:\n import pandas as pd\n HAS_PANDAS = True\nexcept ImportError:\n HAS_PANDAS = False\n\n\n# --- LaTeX escaping ---\n\nLATEX_SPECIAL_CHARS = {\n '&': r'\\&',\n '%': r'\\%',\n '

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

: r'\\

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…

,\n '#': r'\\#',\n '_': r'\\_',\n '{': r'\\{',\n '}': r'\\}',\n '~': r'\\textasciitilde{}',\n '^': r'\\textasciicircum{}',\n}\n\ndef escape_latex(value):\n \"\"\"Escape special LaTeX characters in a string value.\"\"\"\n if value is None:\n return ''\n s = str(value)\n # First escape backslashes (must be first to avoid double-escaping)\n s = s.replace('\\\\', r'\\textbackslash{}')\n # Then escape other special chars\n for char, replacement in LATEX_SPECIAL_CHARS.items():\n s = s.replace(char, replacement)\n return s\n\n\ndef escape_latex_preserve_commands(value):\n \"\"\"Escape LaTeX specials but preserve intentional LaTeX commands.\n\n If a value starts with '\\\\' (literal backslash indicating a LaTeX command),\n it is returned as-is. Otherwise, standard escaping is applied.\n \"\"\"\n if value is None:\n return ''\n s = str(value)\n if s.startswith('\\\\'):\n return s # Assume intentional LaTeX\n return escape_latex(s)\n\n\n# --- Data loading ---\n\ndef load_csv(path):\n \"\"\"Load records from a CSV file. Returns list of dicts.\"\"\"\n if HAS_PANDAS:\n df = pd.read_csv(path, keep_default_na=False)\n return df.to_dict('records')\n else:\n with open(path, 'r', newline='', encoding='utf-8') as f:\n reader = csv.DictReader(f)\n return list(reader)\n\n\ndef load_json(path):\n \"\"\"Load records from a JSON file. Supports array of objects or {records: [...]}.\"\"\"\n with open(path, 'r', encoding='utf-8') as f:\n data = json.load(f)\n\n if isinstance(data, list):\n return data\n elif isinstance(data, dict):\n # Look for common wrapper keys\n for key in ('records', 'data', 'items', 'rows', 'entries'):\n if key in data and isinstance(data[key], list):\n return data[key]\n # Single record\n return [data]\n else:\n raise ValueError(f\"Unsupported JSON structure in {path}\")\n\n\ndef load_data(path):\n \"\"\"Auto-detect format and load data records.\"\"\"\n path = Path(path)\n ext = path.suffix.lower()\n\n if ext == '.csv':\n return load_csv(path)\n elif ext in ('.json', '.jsonl'):\n if ext == '.jsonl':\n records = []\n with open(path, 'r', encoding='utf-8') as f:\n for line in f:\n line = line.strip()\n if line:\n records.append(json.loads(line))\n return records\n return load_json(path)\n else:\n raise ValueError(f\"Unsupported data format: {ext}. Use .csv or .json\")\n\n\n# --- Template rendering ---\n\ndef setup_jinja_env():\n \"\"\"Create a Jinja2 environment configured for LaTeX templates.\"\"\"\n env = jinja2.Environment(\n # Use block/variable/comment strings that don't conflict with LaTeX\n block_start_string='\u003c%',\n block_end_string='%>',\n variable_start_string='\u003c\u003c',\n variable_end_string='>>',\n comment_start_string='\u003c#',\n comment_end_string='#>',\n # Auto-escape is off (we handle LaTeX escaping ourselves)\n autoescape=False,\n # Keep trailing newline\n keep_trailing_newline=True,\n # Undefined variables raise errors\n undefined=jinja2.StrictUndefined,\n )\n # Add LaTeX escape filter\n env.filters['e'] = escape_latex\n env.filters['escape_latex'] = escape_latex\n env.filters['raw'] = lambda x: x # Pass through without escaping\n return env\n\n\ndef render_simple(template_str, record):\n \"\"\"Simple {{variable}} replacement without Jinja2.\n\n Supports only basic variable substitution (no conditionals or loops).\n Variables are auto-escaped for LaTeX.\n \"\"\"\n def replace_var(match):\n var_name = match.group(1).strip()\n if var_name in record:\n return escape_latex(record[var_name])\n else:\n print(f\" Warning: Variable '{var_name}' not found in record\", file=sys.stderr)\n return match.group(0) # Leave placeholder as-is\n\n # Match {{variable_name}} patterns\n return re.sub(r'\\{\\{(\\s*\\w+\\s*)\\}\\}', replace_var, template_str)\n\n\ndef render_jinja(template_str, record, env):\n \"\"\"Render template using Jinja2 with LaTeX-safe delimiters.\n\n Uses \u003c\u003c >> for variables and \u003c% %> for blocks to avoid LaTeX conflicts.\n Data values are auto-escaped unless |raw filter is used.\n \"\"\"\n template = env.from_string(template_str)\n\n # Auto-escape all string values in record\n escaped_record = {}\n for key, value in record.items():\n if isinstance(value, str):\n escaped_record[key] = escape_latex(value)\n elif isinstance(value, list):\n escaped_record[key] = [\n {k: escape_latex(v) if isinstance(v, str) else v for k, v in item.items()}\n if isinstance(item, dict) else\n escape_latex(item) if isinstance(item, str) else item\n for item in value\n ]\n else:\n escaped_record[key] = value\n\n return template.render(**escaped_record)\n\n\ndef render_template(template_str, record, use_jinja=None):\n \"\"\"Render a template with the given record data.\n\n Auto-detects whether to use Jinja2 or simple replacement based on\n template content (presence of \u003c% %> or \u003c\u003c >> delimiters).\n \"\"\"\n if use_jinja is None:\n # Auto-detect: use Jinja2 if template contains block/advanced syntax\n # Strip LaTeX comment lines (lines starting with %) before checking\n non_comment_lines = '\\n'.join(\n line for line in template_str.split('\\n')\n if not line.lstrip().startswith('%')\n )\n use_jinja = bool(re.search(r'\u003c%|\u003c\u003c|\u003c#', non_comment_lines))\n\n if use_jinja:\n if not HAS_JINJA2:\n print(\"Error: Jinja2 required for advanced templates. Install with: pip install jinja2\",\n file=sys.stderr)\n sys.exit(1)\n env = setup_jinja_env()\n return render_jinja(template_str, record, env)\n else:\n return render_simple(template_str, record)\n\n\n# --- Compilation ---\n\ndef compile_tex(tex_path, compile_script=None, engine=None):\n \"\"\"Compile a .tex file to PDF. Returns (success, pdf_path, error_msg).\"\"\"\n tex_path = Path(tex_path)\n pdf_path = tex_path.with_suffix('.pdf')\n\n if compile_script:\n cmd = ['bash', compile_script, str(tex_path)]\n else:\n # Direct compilation\n eng = engine or 'pdflatex'\n cmd = [eng, '-interaction=nonstopmode', '-output-directory',\n str(tex_path.parent), str(tex_path)]\n\n try:\n result = subprocess.run(\n cmd,\n capture_output=True,\n text=True,\n timeout=120,\n cwd=str(tex_path.parent)\n )\n\n if pdf_path.exists():\n return (True, str(pdf_path), None)\n else:\n error_lines = result.stderr[-500:] if result.stderr else result.stdout[-500:]\n return (False, None, f\"No PDF produced. Output:\\n{error_lines}\")\n\n except subprocess.TimeoutExpired:\n return (False, None, \"Compilation timed out (120s)\")\n except FileNotFoundError as e:\n return (False, None, f\"Command not found: {e}\")\n except Exception as e:\n return (False, None, str(e))\n\n\ndef compile_record(args_tuple):\n \"\"\"Wrapper for parallel compilation. Takes (tex_path, compile_script, engine, index).\"\"\"\n tex_path, compile_script, engine, index = args_tuple\n success, pdf_path, error = compile_tex(tex_path, compile_script, engine)\n return (index, success, pdf_path, error)\n\n\n# --- PDF merging ---\n\ndef merge_pdfs(pdf_paths, output_path):\n \"\"\"Merge multiple PDFs into one using pdfunite (poppler-utils).\"\"\"\n if not pdf_paths:\n print(\"Warning: No PDFs to merge\", file=sys.stderr)\n return False\n\n # Check for pdfunite\n if not shutil.which('pdfunite'):\n print(\"Installing poppler-utils for PDF merging...\", file=sys.stderr)\n # Cross-platform package installation\n install_cmds = [\n (['apt-get', 'install', '-y', '-q', 'poppler-utils'], 'apt-get'),\n (['dnf', 'install', '-y', '-q', 'poppler-utils'], 'dnf'),\n (['brew', 'install', 'poppler'], 'brew'),\n (['apk', 'add', '--no-cache', 'poppler-utils'], 'apk'),\n (['pacman', '-S', '--noconfirm', 'poppler'], 'pacman'),\n ]\n installed = False\n for cmd, mgr in install_cmds:\n if shutil.which(mgr):\n # Prepend sudo for non-brew package managers if available\n if mgr != 'brew' and shutil.which('sudo'):\n cmd = ['sudo'] + cmd\n result = subprocess.run(cmd, capture_output=True)\n if result.returncode == 0:\n installed = True\n break\n if not installed and not shutil.which('pdfunite'):\n print(\"Error: pdfunite not available. Install poppler-utils.\", file=sys.stderr)\n return False\n\n cmd = ['pdfunite'] + [str(p) for p in pdf_paths] + [str(output_path)]\n result = subprocess.run(cmd, capture_output=True, text=True)\n\n if result.returncode == 0 and Path(output_path).exists():\n return True\n else:\n print(f\"Error merging PDFs: {result.stderr}\", file=sys.stderr)\n return False\n\n\n# --- Output naming ---\n\ndef sanitize_filename(name):\n \"\"\"Make a string safe for use as a filename.\"\"\"\n # Replace spaces and special chars with underscores\n name = re.sub(r'[^\\w\\-.]', '_', str(name))\n # Collapse multiple underscores\n name = re.sub(r'_+', '_', name)\n # Remove leading/trailing underscores\n name = name.strip('_')\n return name or 'document'\n\n\ndef generate_output_name(record, name_field=None, index=0, prefix=''):\n \"\"\"Generate an output filename for a record.\"\"\"\n if name_field and name_field in record:\n base = sanitize_filename(record[name_field])\n elif 'name' in record:\n base = sanitize_filename(record['name'])\n elif 'Name' in record:\n base = sanitize_filename(record['Name'])\n else:\n base = f\"document_{index + 1:04d}\"\n\n if prefix:\n base = f\"{prefix}_{base}\"\n\n return base\n\n\n# --- Main workflow ---\n\ndef main():\n parser = argparse.ArgumentParser(\n description='Generate personalized LaTeX documents from templates + data sources',\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=__doc__\n )\n\n parser.add_argument('template', help='LaTeX template file (.tex)')\n parser.add_argument('data', help='Data source file (.csv or .json)')\n parser.add_argument('--output-dir', '-o', default='./outputs',\n help='Output directory (default: ./outputs)')\n parser.add_argument('--name-field', '-n', default=None,\n help='Data field to use for output filenames')\n parser.add_argument('--prefix', default='',\n help='Prefix for output filenames')\n parser.add_argument('--compile-script', default=None,\n help='Path to compile script (default: use pdflatex directly)')\n parser.add_argument('--engine', default=None,\n choices=['pdflatex', 'xelatex', 'lualatex'],\n help='LaTeX engine (default: pdflatex)')\n parser.add_argument('--workers', '-w', type=int, default=1,\n help='Number of parallel compilation workers (default: 1)')\n parser.add_argument('--merge', action='store_true',\n help='Merge all PDFs into a single file')\n parser.add_argument('--merge-name', default='merged_output.pdf',\n help='Filename for merged PDF (default: merged_output.pdf)')\n parser.add_argument('--no-compile', action='store_true',\n help='Generate .tex files only, do not compile')\n parser.add_argument('--no-escape', action='store_true',\n help='Disable auto-escaping of LaTeX special characters')\n parser.add_argument('--jinja', action='store_true',\n help='Force Jinja2 rendering (auto-detected by default)')\n parser.add_argument('--simple', action='store_true',\n help='Force simple {{var}} replacement (no Jinja2)')\n parser.add_argument('--limit', type=int, default=None,\n help='Process only first N records')\n parser.add_argument('--dry-run', action='store_true',\n help='Show what would be generated without creating files')\n parser.add_argument('--copy-assets', nargs='*', default=[],\n help='Additional files to copy to each compilation directory (images, .bib, etc.)')\n parser.add_argument('--verbose', '-v', action='store_true',\n help='Verbose output')\n\n args = parser.parse_args()\n\n # --- Validate inputs ---\n template_path = Path(args.template)\n data_path = Path(args.data)\n\n if not template_path.exists():\n print(f\"Error: Template not found: {args.template}\", file=sys.stderr)\n sys.exit(1)\n\n if not data_path.exists():\n print(f\"Error: Data file not found: {args.data}\", file=sys.stderr)\n sys.exit(1)\n\n # --- Load template ---\n template_str = template_path.read_text(encoding='utf-8')\n print(f\":: Loaded template: {template_path}\")\n\n # --- Load data ---\n try:\n records = load_data(data_path)\n except Exception as e:\n print(f\"Error loading data: {e}\", file=sys.stderr)\n sys.exit(1)\n\n if not records:\n print(\"Error: No records found in data file\", file=sys.stderr)\n sys.exit(1)\n\n if args.limit:\n records = records[:args.limit]\n\n print(f\":: Loaded {len(records)} records from {data_path}\")\n\n # Detect rendering mode\n if args.simple:\n use_jinja = False\n elif args.jinja:\n use_jinja = True\n else:\n use_jinja = None # Auto-detect\n\n # --- Dry run ---\n if args.dry_run:\n print(\"\\n:: DRY RUN -- would generate:\")\n for i, record in enumerate(records):\n name = generate_output_name(record, args.name_field, i, args.prefix)\n print(f\" [{i+1}] {name}.tex → {name}.pdf\")\n if args.verbose:\n for key, val in record.items():\n print(f\" {key}: {val}\")\n print(f\"\\n:: Total: {len(records)} documents\")\n return\n\n # --- Create output directory ---\n output_dir = Path(args.output_dir)\n output_dir.mkdir(parents=True, exist_ok=True)\n\n # --- Generate .tex files ---\n tex_files = []\n errors = []\n\n print(f\"\\n:: Generating {len(records)} documents...\")\n\n for i, record in enumerate(records):\n name = generate_output_name(record, args.name_field, i, args.prefix)\n tex_path = output_dir / f\"{name}.tex\"\n\n try:\n rendered = render_template(template_str, record, use_jinja=use_jinja)\n tex_path.write_text(rendered, encoding='utf-8')\n tex_files.append((str(tex_path), i, name))\n\n if args.verbose:\n print(f\" [{i+1}/{len(records)}] Generated: {tex_path}\")\n\n except Exception as e:\n error_msg = f\"Record {i+1}: {e}\"\n errors.append(error_msg)\n print(f\" Error generating {name}: {e}\", file=sys.stderr)\n\n print(f\":: Generated {len(tex_files)} .tex files ({len(errors)} errors)\")\n\n # --- Copy assets ---\n for asset in args.copy_assets:\n asset_path = Path(asset)\n if asset_path.exists():\n dest = output_dir / asset_path.name\n shutil.copy2(asset_path, dest)\n if args.verbose:\n print(f\" Copied asset: {asset_path.name}\")\n else:\n print(f\" Warning: Asset not found: {asset}\", file=sys.stderr)\n\n # --- Compile ---\n if args.no_compile:\n print(\":: Skipping compilation (--no-compile)\")\n print(f\"\\n:: Done. {len(tex_files)} .tex files in {output_dir}/\")\n return\n\n print(f\"\\n:: Compiling {len(tex_files)} documents (workers: {args.workers})...\")\n\n pdf_files = []\n compile_errors = []\n\n if args.workers > 1:\n # Parallel compilation\n tasks = [(tex_path, args.compile_script, args.engine, idx)\n for tex_path, idx, name in tex_files]\n\n with ProcessPoolExecutor(max_workers=args.workers) as executor:\n futures = {executor.submit(compile_record, task): task for task in tasks}\n\n for future in as_completed(futures):\n idx, success, pdf_path, error = future.result()\n if success:\n pdf_files.append((idx, pdf_path))\n if args.verbose:\n print(f\" Compiled: {Path(pdf_path).name}\")\n else:\n compile_errors.append(f\"Record {idx+1}: {error}\")\n print(f\" Error compiling record {idx+1}: {error}\", file=sys.stderr)\n else:\n # Sequential compilation\n for tex_path, idx, name in tex_files:\n success, pdf_path, error = compile_tex(tex_path, args.compile_script, args.engine)\n if success:\n pdf_files.append((idx, pdf_path))\n if args.verbose:\n print(f\" [{idx+1}/{len(tex_files)}] Compiled: {Path(pdf_path).name}\")\n else:\n compile_errors.append(f\"Record {idx+1}: {error}\")\n print(f\" Error compiling record {idx+1}: {error}\", file=sys.stderr)\n\n # Sort PDFs by original index\n pdf_files.sort(key=lambda x: x[0])\n pdf_paths = [p for _, p in pdf_files]\n\n print(f\":: Compiled {len(pdf_paths)} PDFs ({len(compile_errors)} errors)\")\n\n # --- Merge PDFs ---\n if args.merge and pdf_paths:\n merge_path = output_dir / args.merge_name\n print(f\"\\n:: Merging {len(pdf_paths)} PDFs into {merge_path}...\")\n\n if merge_pdfs(pdf_paths, merge_path):\n print(f\":: Merged PDF: {merge_path}\")\n else:\n print(\":: PDF merge failed\", file=sys.stderr)\n\n # --- Summary ---\n print(f\"\\n:: Done.\")\n print(f\" Generated: {len(tex_files)} .tex files\")\n print(f\" Compiled: {len(pdf_paths)} PDFs\")\n if errors or compile_errors:\n print(f\" Errors: {len(errors) + len(compile_errors)}\")\n print(f\" Output: {output_dir}/\")\n\n if compile_errors and args.verbose:\n print(\"\\n:: Compilation errors:\")\n for err in compile_errors:\n print(f\" - {err}\")\n\n # Exit with error if any failures\n if errors or compile_errors:\n sys.exit(1)\n\n\nif __name__ == '__main__':\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":20817,"content_sha256":"7a076bb8c5c64ada84cdaa59189093fcad143456c3ed2e9e6427c2670b797c3d"},{"filename":"scripts/mermaid_to_image.sh","content":"#!/usr/bin/env bash\n\n# mermaid_to_image.sh\n# Converts Mermaid diagram files (.mmd) to PNG or PDF images for LaTeX inclusion\n#\n# Examples:\n# ./mermaid_to_image.sh diagram.mmd output.png\n# ./mermaid_to_image.sh diagram.mmd output.pdf --format pdf --theme dark\n# ./mermaid_to_image.sh flowchart.mmd chart.png --width 1200 --background transparent\n\nset -euo pipefail\n\n# Default values\nFORMAT=\"png\"\nWIDTH=\"800\"\nTHEME=\"default\"\nBACKGROUND=\"white\"\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cinput.mmd> \u003coutput> [OPTIONS]\n\nConvert Mermaid diagram files to PNG or PDF for LaTeX inclusion.\n\nArguments:\n input.mmd Input Mermaid diagram file\n output Output file path (e.g., diagram.png or diagram.pdf)\n\nOptions:\n --format FORMAT Output format: png or pdf (default: png)\n --width PIXELS Width in pixels (default: 800)\n --theme THEME Theme: default, dark, forest, neutral (default: default)\n --background BG Background: white or transparent (default: white)\n -h, --help Show this help message\n\nExamples:\n $0 diagram.mmd output.png\n $0 diagram.mmd output.pdf --format pdf --theme dark\n $0 flowchart.mmd chart.png --width 1200 --background transparent\n\nRequires: npx and @mermaid-js/mermaid-cli\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Check minimum arguments\nif [[ $# -lt 2 ]]; then\n echo \"Error: Missing required arguments\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\nINPUT_FILE=\"$1\"\nOUTPUT_FILE=\"$2\"\nshift 2\n\n# --- Check for Node.js/npx ---\nif ! command -v npx &>/dev/null; then\n echo \"Error: npx not found. Mermaid diagram conversion requires Node.js and npm.\" >&2\n echo \"\" >&2\n echo \"Install Node.js:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install nodejs npm\" >&2\n echo \" macOS: brew install node\" >&2\n echo \" Fedora/RHEL: sudo dnf install nodejs npm\" >&2\n echo \" Alpine: sudo apk add nodejs npm\" >&2\n echo \" Arch: sudo pacman -S nodejs npm\" >&2\n echo \"\" >&2\n echo \"Or download from: https://nodejs.org/\" >&2\n exit 1\nfi\n\nif command -v node &>/dev/null; then\n NODE_VERSION=$(node --version | sed 's/v//' | cut -d. -f1)\n if [[ \"$NODE_VERSION\" -lt 18 ]]; then\n echo \"Warning: Node.js v${NODE_VERSION} detected. Mermaid CLI requires Node 18+.\" >&2\n echo \"Consider upgrading: https://nodejs.org/\" >&2\n fi\nfi\n\n# Parse options\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --format)\n FORMAT=\"$2\"\n shift 2\n ;;\n --width)\n WIDTH=\"$2\"\n shift 2\n ;;\n --theme)\n THEME=\"$2\"\n shift 2\n ;;\n --background)\n BACKGROUND=\"$2\"\n shift 2\n ;;\n *)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n esac\ndone\n\n# Validate input file\nif [[ ! -f \"$INPUT_FILE\" ]]; then\n echo \"Error: Input file not found: $INPUT_FILE\" >&2\n exit 1\nfi\n\n# Validate format\nif [[ \"$FORMAT\" != \"png\" ]] && [[ \"$FORMAT\" != \"pdf\" ]]; then\n echo \"Error: Format must be 'png' or 'pdf', got: $FORMAT\" >&2\n exit 1\nfi\n\n# Validate theme\nif [[ \"$THEME\" != \"default\" ]] && [[ \"$THEME\" != \"dark\" ]] && [[ \"$THEME\" != \"forest\" ]] && [[ \"$THEME\" != \"neutral\" ]]; then\n echo \"Error: Theme must be 'default', 'dark', 'forest', or 'neutral', got: $THEME\" >&2\n exit 1\nfi\n\n# Validate background\nif [[ \"$BACKGROUND\" != \"white\" ]] && [[ \"$BACKGROUND\" != \"transparent\" ]]; then\n echo \"Error: Background must be 'white' or 'transparent', got: $BACKGROUND\" >&2\n exit 1\nfi\n\n# Validate width is a number\nif ! [[ \"$WIDTH\" =~ ^[0-9]+$ ]]; then\n echo \"Error: Width must be a number, got: $WIDTH\" >&2\n exit 1\nfi\n\n# Create temporary puppeteer config\nPUPPETEER_CONFIG=$(mktemp /tmp/puppeteer-config.XXXXXX.json)\ntrap \"rm -f $PUPPETEER_CONFIG\" EXIT\n\ncat > \"$PUPPETEER_CONFIG\" \u003c\u003c EOF\n{\n \"args\": [\"--no-sandbox\", \"--disable-setuid-sandbox\"]\n}\nEOF\n\n# Build mermaid-cli command\necho \"Converting $INPUT_FILE to $OUTPUT_FILE...\" >&2\n\nMMD_CMD=(\n npx -y @mermaid-js/mermaid-cli mmdc\n -i \"$INPUT_FILE\"\n -o \"$OUTPUT_FILE\"\n -t \"$THEME\"\n -w \"$WIDTH\"\n -p \"$PUPPETEER_CONFIG\"\n)\n\n# Add background option\nif [[ \"$BACKGROUND\" == \"transparent\" ]]; then\n MMD_CMD+=(-b transparent)\nelse\n MMD_CMD+=(-b white)\nfi\n\n# Execute conversion\nif \"${MMD_CMD[@]}\" 2>&1; then\n echo \"Successfully created: $OUTPUT_FILE\" >&2\n exit 0\nelse\n echo \"Error: Failed to convert Mermaid diagram\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4637,"content_sha256":"30957d2c414f9552765195b866b3459ce182712752bb6c1eafcca097a485b456"},{"filename":"scripts/pdf_check_form.py","content":"#!/usr/bin/env python3\n\"\"\"\npdf_check_form.py\nCheck whether a PDF has fillable form fields.\n\nThis is the first step in the form-filling workflow. Based on the result,\nuse either pdf_fill_form.py (fillable) or pdf_fill_annotations.py (non-fillable).\n\nExamples:\n python3 pdf_check_form.py document.pdf\n python3 pdf_check_form.py /path/to/form.pdf\n\"\"\"\n\nimport subprocess\nimport sys\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"pypdf\")\n\nimport argparse\nfrom pathlib import Path\nfrom pypdf import PdfReader\n\n\ndef check_form(pdf_path: str) -> bool:\n \"\"\"Check if a PDF has fillable form fields.\n\n Args:\n pdf_path: Path to the PDF file.\n\n Returns:\n True if the PDF has fillable form fields, False otherwise.\n \"\"\"\n reader = PdfReader(pdf_path)\n fields = reader.get_fields()\n return bool(fields)\n\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description=\"Check whether a PDF has fillable form fields.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\nExamples:\n %(prog)s document.pdf\n %(prog)s /path/to/form.pdf\n\nBased on the result, use:\n - Fillable: pdf_fill_form.py\n - Non-fillable: pdf_fill_annotations.py\n \"\"\"\n )\n parser.add_argument(\"pdf_file\", help=\"Path to the PDF file to check\")\n return parser.parse_args()\n\n\ndef main():\n args = parse_args()\n pdf_path = Path(args.pdf_file)\n\n if not pdf_path.exists():\n print(f\"Error: File not found: {pdf_path}\", file=sys.stderr)\n sys.exit(1)\n\n try:\n has_fields = check_form(str(pdf_path))\n if has_fields:\n print(\"This PDF has fillable form fields\")\n print(\"Use pdf_extract_fields.py to extract field info, then pdf_fill_form.py to fill them.\")\n else:\n print(\"This PDF does not have fillable form fields; you will need to visually determine where to enter data\")\n print(\"Use pdf_fill_annotations.py to add text annotations at specific positions.\")\n except Exception as e:\n print(f\"Error reading PDF: {e}\", file=sys.stderr)\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":3214,"content_sha256":"216b0ddb7995cb49adb2927292611bfb1cf544dd5d119385467c9e8edbfeb852"},{"filename":"scripts/pdf_encrypt.sh","content":"#!/usr/bin/env bash\n\n# pdf_encrypt.sh\n# Password-protect a PDF using qpdf\n#\n# Examples:\n# ./pdf_encrypt.sh document.pdf --user-password mypass123\n# ./pdf_encrypt.sh document.pdf --user-password mypass --owner-password admin --output secure.pdf\n# ./pdf_encrypt.sh document.pdf --user-password pass --restrict-print --restrict-modify\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nUSER_PASSWORD=\"\"\nOWNER_PASSWORD=\"\"\nOUTPUT_FILE=\"\"\nRESTRICT_PRINT=false\nRESTRICT_COPY=false\nRESTRICT_MODIFY=false\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cinput.pdf> [OPTIONS]\n\nPassword-protect a PDF using 256-bit AES encryption.\n\nArguments:\n input.pdf Input PDF file to encrypt\n\nOptions:\n --user-password \u003cpw> Password required to open the PDF (required)\n --owner-password \u003cpw> Password for full access (defaults to user password)\n --output \u003cfile> Output file path (default: input_encrypted.pdf)\n --restrict-print Prevent printing\n --restrict-copy Prevent text/graphics copying\n --restrict-modify Prevent document modification\n -h, --help Show this help message\n\nExamples:\n $0 document.pdf --user-password mypass123\n $0 document.pdf --user-password pass --owner-password admin --output secure.pdf\n $0 document.pdf --user-password pass --restrict-print --restrict-modify\n\nRequires: qpdf (auto-installed if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nINPUT_FILE=\"\"\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --user-password)\n USER_PASSWORD=\"$2\"\n shift 2\n ;;\n --owner-password)\n OWNER_PASSWORD=\"$2\"\n shift 2\n ;;\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n --restrict-print)\n RESTRICT_PRINT=true\n shift\n ;;\n --restrict-copy)\n RESTRICT_COPY=true\n shift\n ;;\n --restrict-modify)\n RESTRICT_MODIFY=true\n shift\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n if [[ -z \"$INPUT_FILE\" ]]; then\n INPUT_FILE=\"$1\"\n else\n echo \"Error: Multiple input files specified\" >&2\n exit 1\n fi\n shift\n ;;\n esac\ndone\n\n# Validate input file\nif [[ -z \"$INPUT_FILE\" ]]; then\n echo \"Error: No input file specified\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_FILE\" ]]; then\n echo \"Error: Input file not found: $INPUT_FILE\" >&2\n exit 1\nfi\n\n# Validate user password\nif [[ -z \"$USER_PASSWORD\" ]]; then\n echo \"Error: --user-password is required\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\n# Set owner password to user password if not specified\nif [[ -z \"$OWNER_PASSWORD\" ]]; then\n OWNER_PASSWORD=\"$USER_PASSWORD\"\nfi\n\n# Set default output file\nif [[ -z \"$OUTPUT_FILE\" ]]; then\n BASENAME=\"${INPUT_FILE%.pdf}\"\n OUTPUT_FILE=\"${BASENAME}_encrypted.pdf\"\nfi\n\n# Check for qpdf, install if missing\nif ! command -v qpdf &>/dev/null; then\n echo \"qpdf not found. Installing...\" >&2\n\n # Map qpdf to platform packages\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt) run_pkg_install qpdf ;;\n brew) run_pkg_install qpdf ;;\n dnf) run_pkg_install qpdf ;;\n apk) run_pkg_install qpdf ;;\n pacman) run_pkg_install qpdf ;;\n *)\n echo \"Error: Could not auto-install qpdf\" >&2\n echo \"Please install manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install qpdf\" >&2\n echo \" macOS: brew install qpdf\" >&2\n echo \" Fedora/RHEL: sudo dnf install qpdf\" >&2\n echo \" Alpine: sudo apk add qpdf\" >&2\n echo \" Arch: sudo pacman -S qpdf\" >&2\n exit 1\n ;;\n esac\n\n if ! command -v qpdf &>/dev/null; then\n echo \"Error: qpdf installation failed\" >&2\n exit 1\n fi\nfi\n\n# Build qpdf command\nQPDF_CMD=(\n qpdf\n --encrypt \"$USER_PASSWORD\" \"$OWNER_PASSWORD\" 256\n)\n\n# Add restriction flags\nRESTRICTIONS=\"\"\nif [[ \"$RESTRICT_PRINT\" == true ]]; then\n RESTRICTIONS=\"${RESTRICTIONS} --print=none\"\nelse\n RESTRICTIONS=\"${RESTRICTIONS} --print=full\"\nfi\n\nif [[ \"$RESTRICT_COPY\" == true ]]; then\n RESTRICTIONS=\"${RESTRICTIONS} --extract=n\"\nelse\n RESTRICTIONS=\"${RESTRICTIONS} --extract=y\"\nfi\n\nif [[ \"$RESTRICT_MODIFY\" == true ]]; then\n RESTRICTIONS=\"${RESTRICTIONS} --modify=none\"\nelse\n RESTRICTIONS=\"${RESTRICTIONS} --modify=all\"\nfi\n\n# Add remaining arguments\nQPDF_CMD+=(\n $RESTRICTIONS\n --\n \"$INPUT_FILE\"\n \"$OUTPUT_FILE\"\n)\n\n# Execute encryption\necho \"Encrypting $INPUT_FILE...\" >&2\n\nif \"${QPDF_CMD[@]}\" 2>&1; then\n echo \"Successfully created encrypted PDF: $OUTPUT_FILE\" >&2\n\n # Show restrictions summary\n if [[ \"$RESTRICT_PRINT\" == true ]] || [[ \"$RESTRICT_COPY\" == true ]] || [[ \"$RESTRICT_MODIFY\" == true ]]; then\n echo \"\" >&2\n echo \"Applied restrictions:\" >&2\n [[ \"$RESTRICT_PRINT\" == true ]] && echo \" - Printing disabled\" >&2\n [[ \"$RESTRICT_COPY\" == true ]] && echo \" - Text/graphics copying disabled\" >&2\n [[ \"$RESTRICT_MODIFY\" == true ]] && echo \" - Document modification disabled\" >&2\n fi\n\n exit 0\nelse\n echo \"Error: Failed to encrypt PDF\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":5699,"content_sha256":"eddf693996d4b93b4a6b33f0848442424489d26022e55881b935e1b3b364fcc7"},{"filename":"scripts/pdf_extract_fields.py","content":"#!/usr/bin/env python3\n\"\"\"\npdf_extract_fields.py\nExtract fillable form field metadata from a PDF to JSON.\n\nExtracts field IDs, types (text, checkbox, radio_group, choice), page numbers,\nbounding rectangles, and option values. Output is used by pdf_fill_form.py.\n\nExamples:\n python3 pdf_extract_fields.py form.pdf field_info.json\n python3 pdf_extract_fields.py /path/to/form.pdf /tmp/fields.json\n\"\"\"\n\nimport subprocess\nimport sys\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"pypdf\")\n\nimport argparse\nimport json\nfrom pathlib import Path\nfrom pypdf import PdfReader\n\n\ndef get_full_annotation_field_id(annotation):\n \"\"\"Build the full hierarchical field ID by walking parent chain.\n\n This matches the format used by PdfReader's get_fields() and\n update_page_form_field_values() methods.\n \"\"\"\n components = []\n while annotation:\n field_name = annotation.get('/T')\n if field_name:\n components.append(field_name)\n annotation = annotation.get('/Parent')\n return \".\".join(reversed(components)) if components else None\n\n\ndef make_field_dict(field, field_id):\n \"\"\"Create a field info dictionary from a PDF form field.\"\"\"\n field_dict = {\"field_id\": field_id}\n ft = field.get('/FT')\n if ft == \"/Tx\":\n field_dict[\"type\"] = \"text\"\n elif ft == \"/Btn\":\n field_dict[\"type\"] = \"checkbox\" # radio groups handled separately\n states = field.get(\"/_States_\", [])\n if len(states) == 2:\n # \"/Off\" is always the unchecked value per PDF spec\n # https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf#page=448\n if \"/Off\" in states:\n field_dict[\"checked_value\"] = states[0] if states[0] != \"/Off\" else states[1]\n field_dict[\"unchecked_value\"] = \"/Off\"\n else:\n print(f\"Warning: Unexpected state values for checkbox `{field_id}`. \"\n \"Its checked/unchecked values may not be correct; visually verify results.\",\n file=sys.stderr)\n field_dict[\"checked_value\"] = states[0]\n field_dict[\"unchecked_value\"] = states[1]\n elif ft == \"/Ch\":\n field_dict[\"type\"] = \"choice\"\n states = field.get(\"/_States_\", [])\n field_dict[\"choice_options\"] = [{\n \"value\": state[0],\n \"text\": state[1],\n } for state in states]\n else:\n field_dict[\"type\"] = f\"unknown ({ft})\"\n return field_dict\n\n\ndef get_field_info(reader: PdfReader):\n \"\"\"Extract all fillable field metadata from a PDF.\n\n Returns a list of field info dicts:\n [\n {\n \"field_id\": str,\n \"page\": int (1-based),\n \"rect\": [left, bottom, right, top],\n \"type\": \"text\" | \"checkbox\" | \"radio_group\" | \"choice\",\n // type-specific fields (checked_value, radio_options, choice_options)\n }\n ]\n \"\"\"\n fields = reader.get_fields()\n if not fields:\n return []\n\n field_info_by_id = {}\n possible_radio_names = set()\n\n for field_id, field in fields.items():\n # Skip container fields with children, except radio button parent groups\n if field.get(\"/Kids\"):\n if field.get(\"/FT\") == \"/Btn\":\n possible_radio_names.add(field_id)\n continue\n field_info_by_id[field_id] = make_field_dict(field, field_id)\n\n # Bounding rects are stored in annotations on page objects\n # Radio button options have a separate annotation for each choice\n radio_fields_by_id = {}\n\n for page_index, page in enumerate(reader.pages):\n annotations = page.get('/Annots', [])\n for ann in annotations:\n field_id = get_full_annotation_field_id(ann)\n if field_id in field_info_by_id:\n field_info_by_id[field_id][\"page\"] = page_index + 1\n field_info_by_id[field_id][\"rect\"] = ann.get('/Rect')\n elif field_id in possible_radio_names:\n try:\n on_values = [v for v in ann[\"/AP\"][\"/N\"] if v != \"/Off\"]\n except KeyError:\n continue\n if len(on_values) == 1:\n rect = ann.get(\"/Rect\")\n if field_id not in radio_fields_by_id:\n radio_fields_by_id[field_id] = {\n \"field_id\": field_id,\n \"type\": \"radio_group\",\n \"page\": page_index + 1,\n \"radio_options\": [],\n }\n radio_fields_by_id[field_id][\"radio_options\"].append({\n \"value\": on_values[0],\n \"rect\": rect,\n })\n\n # Filter out fields without location data (orphaned definitions)\n fields_with_location = []\n for field_info in field_info_by_id.values():\n if \"page\" in field_info:\n fields_with_location.append(field_info)\n else:\n print(f\"Warning: Unable to determine location for field: {field_info.get('field_id')}, ignoring\",\n file=sys.stderr)\n\n # Sort by page number, then Y position (flipped), then X\n def sort_key(f):\n if \"radio_options\" in f:\n rect = f[\"radio_options\"][0][\"rect\"] or [0, 0, 0, 0]\n else:\n rect = f.get(\"rect\") or [0, 0, 0, 0]\n adjusted_position = [-rect[1], rect[0]]\n return [f.get(\"page\"), adjusted_position]\n\n sorted_fields = fields_with_location + list(radio_fields_by_id.values())\n sorted_fields.sort(key=sort_key)\n\n return sorted_fields\n\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description=\"Extract fillable form field metadata from a PDF to JSON.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\nExamples:\n %(prog)s form.pdf field_info.json\n %(prog)s /path/to/form.pdf /tmp/fields.json\n\nOutput JSON format:\n [\n {\"field_id\": \"name\", \"page\": 1, \"type\": \"text\", \"rect\": [x1,y1,x2,y2]},\n {\"field_id\": \"agree\", \"page\": 1, \"type\": \"checkbox\", \"checked_value\": \"/Yes\", \"unchecked_value\": \"/Off\"},\n {\"field_id\": \"gender\", \"page\": 2, \"type\": \"radio_group\", \"radio_options\": [...]},\n {\"field_id\": \"country\", \"page\": 2, \"type\": \"choice\", \"choice_options\": [...]}\n ]\n \"\"\"\n )\n parser.add_argument(\"pdf_file\", help=\"Path to the PDF file\")\n parser.add_argument(\"output_json\", help=\"Path for the output JSON file\")\n return parser.parse_args()\n\n\ndef main():\n args = parse_args()\n pdf_path = Path(args.pdf_file)\n output_path = Path(args.output_json)\n\n if not pdf_path.exists():\n print(f\"Error: File not found: {pdf_path}\", file=sys.stderr)\n sys.exit(1)\n\n try:\n reader = PdfReader(str(pdf_path))\n field_info = get_field_info(reader)\n with open(output_path, \"w\") as f:\n json.dump(field_info, f, indent=2)\n print(f\"Wrote {len(field_info)} fields to {output_path}\")\n except Exception as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":8202,"content_sha256":"d93bcd027c10d525697fca9f41802595dd5d6a75964821e5dded493ec447578a"},{"filename":"scripts/pdf_extract_pages.sh","content":"#!/usr/bin/env bash\n# pdf_extract_pages.sh - Extract page ranges from a PDF\n#\n# Usage:\n# pdf_extract_pages.sh \u003cinput.pdf> --pages \u003crange> [--output \u003coutput.pdf>]\n#\n# Options:\n# --pages \u003crange> Page range to extract (required)\n# --output \u003cfile> Output PDF file (default: auto-generated)\n#\n# Page range formats:\n# Single page: --pages 5\n# Range: --pages 1-10\n# Multiple: --pages 1,3,5-8\n# Odd pages: --pages odd\n# Even pages: --pages even\n# Last N pages: --pages last:3\n#\n# Features:\n# - Auto-installs qpdf if missing\n# - Preserves PDF metadata and bookmarks\n# - Smart output naming (input_pages_X-Y.pdf)\n# - Validates page ranges against document\n#\n# Examples:\n# pdf_extract_pages.sh document.pdf --pages 1-5\n# pdf_extract_pages.sh report.pdf --pages 1,3,5-8 --output selected.pdf\n# pdf_extract_pages.sh book.pdf --pages odd\n# pdf_extract_pages.sh paper.pdf --pages last:3 --output appendix.pdf\n\nset -euo pipefail\n\n# --- Usage function ---\nusage() {\n cat \u003c\u003c'EOF'\npdf_extract_pages.sh - Extract page ranges from a PDF\n\nUsage:\n pdf_extract_pages.sh \u003cinput.pdf> --pages \u003crange> [--output \u003coutput.pdf>]\n\nOptions:\n --pages \u003crange> Page range to extract (required)\n --output \u003cfile> Output PDF file (default: auto-generated)\n\nPage range formats:\n Single page: --pages 5\n Range: --pages 1-10\n Multiple: --pages 1,3,5-8\n Odd pages: --pages odd\n Even pages: --pages even\n Last N pages: --pages last:3\n\nFeatures:\n - Auto-installs qpdf if missing\n - Preserves PDF metadata and bookmarks\n - Smart output naming (input_pages_X-Y.pdf)\n - Validates page ranges against document\n\nExamples:\n pdf_extract_pages.sh document.pdf --pages 1-5\n pdf_extract_pages.sh report.pdf --pages 1,3,5-8 --output selected.pdf\n pdf_extract_pages.sh book.pdf --pages odd\n pdf_extract_pages.sh paper.pdf --pages last:3 --output appendix.pdf\nEOF\n}\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# --- Parse arguments ---\nINPUT_PDF=\"\"\nPAGES=\"\"\nOUTPUT_PDF=\"\"\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) usage; exit 0 ;;\n --pages) PAGES=\"$2\"; shift 2 ;;\n --output) OUTPUT_PDF=\"$2\"; shift 2 ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *) INPUT_PDF=\"$1\"; shift ;;\n esac\ndone\n\nif [[ -z \"$INPUT_PDF\" ]]; then\n echo \"Error: No input PDF file specified\" >&2\n echo \"Usage: pdf_extract_pages.sh \u003cinput.pdf> --pages \u003crange> [--output \u003coutput.pdf>]\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_PDF\" ]]; then\n echo \"Error: File not found: $INPUT_PDF\" >&2\n exit 1\nfi\n\nif [[ -z \"$PAGES\" ]]; then\n echo \"Error: No page range specified. Use --pages \u003crange>\" >&2\n echo \"Examples: --pages 1-5, --pages 1,3,5, --pages odd\" >&2\n exit 1\nfi\n\n# Resolve absolute paths\nINPUT_PDF=\"$(realpath \"$INPUT_PDF\")\"\nINPUT_DIR=\"$(dirname \"$INPUT_PDF\")\"\nINPUT_BASE=\"$(basename \"$INPUT_PDF\" .pdf)\"\n\n# --- Ensure qpdf is installed ---\nensure_qpdf() {\n if command -v qpdf &>/dev/null; then\n return 0\n fi\n echo \":: qpdf not found. Installing qpdf...\" >&2\n\n # Map qpdf package name per platform\n local mgr\n mgr=\"$(detect_pkg_manager)\"\n local pkg_name=\"qpdf\"\n\n case \"$mgr\" in\n apt) pkg_name=\"qpdf\" ;;\n brew) pkg_name=\"qpdf\" ;;\n dnf) pkg_name=\"qpdf\" ;;\n apk) pkg_name=\"qpdf\" ;;\n pacman) pkg_name=\"qpdf\" ;;\n esac\n\n run_pkg_install \"$pkg_name\" || {\n echo \"Error: Failed to install qpdf.\" >&2\n echo \"\" >&2\n echo \"Install qpdf manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install qpdf\" >&2\n echo \" macOS: brew install qpdf\" >&2\n echo \" Fedora/RHEL: sudo dnf install qpdf\" >&2\n echo \" Alpine: sudo apk add qpdf\" >&2\n echo \" Arch: sudo pacman -S qpdf\" >&2\n echo \"\" >&2\n exit 1\n }\n\n if ! command -v qpdf &>/dev/null; then\n echo \"Error: qpdf still not available after install\" >&2\n exit 1\n fi\n echo \":: qpdf installed successfully\" >&2\n}\n\n# --- Get total page count ---\nget_page_count() {\n local pdf=\"$1\"\n qpdf --show-npages \"$pdf\" 2>/dev/null || {\n echo \"Error: Unable to read PDF page count\" >&2\n exit 1\n }\n}\n\n# --- Parse page range into qpdf format ---\nparse_page_range() {\n local range=\"$1\"\n local total_pages=\"$2\"\n\n # Handle special keywords\n case \"$range\" in\n odd)\n echo \"1-$total_pages:odd\"\n return 0\n ;;\n even)\n echo \"1-$total_pages:even\"\n return 0\n ;;\n last:*)\n local n=\"${range#last:}\"\n if ! [[ \"$n\" =~ ^[0-9]+$ ]]; then\n echo \"Error: Invalid last:N format - N must be a number\" >&2\n exit 1\n fi\n local start=$((total_pages - n + 1))\n if [[ $start -lt 1 ]]; then\n start=1\n fi\n echo \"$start-$total_pages\"\n return 0\n ;;\n esac\n\n # Validate range format (numbers, commas, dashes only)\n if ! [[ \"$range\" =~ ^[0-9,\\-]+$ ]]; then\n echo \"Error: Invalid page range format: $range\" >&2\n echo \"Valid formats: 5, 1-10, 1,3,5-8, odd, even, last:3\" >&2\n exit 1\n fi\n\n # Return range as-is for qpdf\n echo \"$range\"\n}\n\n# --- Generate output filename ---\ngenerate_output_name() {\n local range=\"$1\"\n local base=\"$2\"\n local dir=\"$3\"\n\n # Clean range for filename (replace commas and colons with underscores)\n local clean_range=\"${range//,/_}\"\n clean_range=\"${clean_range//:/_}\"\n\n echo \"${dir}/${base}_pages_${clean_range}.pdf\"\n}\n\n# --- Main extraction ---\nensure_qpdf\n\nTOTAL_PAGES=$(get_page_count \"$INPUT_PDF\")\necho \":: Input PDF: $INPUT_PDF ($TOTAL_PAGES pages)\" >&2\n\nQPDF_RANGE=$(parse_page_range \"$PAGES\" \"$TOTAL_PAGES\")\n\n# Determine output file\nif [[ -z \"$OUTPUT_PDF\" ]]; then\n OUTPUT_PDF=$(generate_output_name \"$PAGES\" \"$INPUT_BASE\" \"$INPUT_DIR\")\nelse\n OUTPUT_PDF=\"$(realpath \"$OUTPUT_PDF\")\"\nfi\n\necho \":: Extracting pages: $PAGES\" >&2\necho \":: Output PDF: $OUTPUT_PDF\" >&2\n\n# Extract pages with qpdf\nqpdf \"$INPUT_PDF\" --pages . \"$QPDF_RANGE\" -- \"$OUTPUT_PDF\" 2>&1 | while read -r line; do\n # Filter out warnings we don't care about\n if [[ ! \"$line\" =~ \"ignoring attempt to remove page we don't have\" ]]; then\n echo \"$line\" >&2\n fi\ndone || {\n echo \"Error: qpdf extraction failed\" >&2\n exit 1\n}\n\nif [[ ! -f \"$OUTPUT_PDF\" ]]; then\n echo \"Error: Output PDF not created\" >&2\n exit 1\nfi\n\nOUTPUT_PAGES=$(get_page_count \"$OUTPUT_PDF\")\necho \":: Extraction complete: $OUTPUT_PAGES pages extracted\"\necho \":: Output: $OUTPUT_PDF\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":6465,"content_sha256":"2ac354b4784b425a4769da40b5821fdb235c334bbc76fba28c35079f09badade"},{"filename":"scripts/pdf_fill_annotations.py","content":"#!/usr/bin/env python3\n\"\"\"\npdf_fill_annotations.py\nFill a non-fillable PDF by adding text annotations at specified positions.\n\nFor PDFs that don't have fillable form fields, this script adds FreeText\nannotations at bounding box positions defined in a fields.json file.\nUse pdf_validate_boxes.py to validate bounding boxes before filling.\n\nExamples:\n python3 pdf_fill_annotations.py form.pdf fields.json filled_form.pdf\n\"\"\"\n\nimport subprocess\nimport sys\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"pypdf\")\n\nimport argparse\nimport json\nfrom pathlib import Path\nfrom pypdf import PdfReader, PdfWriter\nfrom pypdf.annotations import FreeText\n\n\ndef transform_coordinates(bbox, image_width, image_height, pdf_width, pdf_height):\n \"\"\"Transform bounding box from image coordinates to PDF coordinates.\n\n Image coordinates: origin at top-left, y increases downward.\n PDF coordinates: origin at bottom-left, y increases upward.\n\n Args:\n bbox: [left, top, right, bottom] in image coordinates.\n image_width: Width of the source image in pixels.\n image_height: Height of the source image in pixels.\n pdf_width: Width of the PDF page in points.\n pdf_height: Height of the PDF page in points.\n\n Returns:\n Tuple of (left, bottom, right, top) in PDF coordinates.\n \"\"\"\n x_scale = pdf_width / image_width\n y_scale = pdf_height / image_height\n\n left = bbox[0] * x_scale\n right = bbox[2] * x_scale\n\n # Flip Y coordinates for PDF\n top = pdf_height - (bbox[1] * y_scale)\n bottom = pdf_height - (bbox[3] * y_scale)\n\n return left, bottom, right, top\n\n\ndef fill_pdf_form(input_pdf_path, fields_json_path, output_pdf_path):\n \"\"\"Fill a PDF form with data from fields.json using text annotations.\n\n Args:\n input_pdf_path: Path to the input PDF.\n fields_json_path: Path to fields.json with bounding box data.\n output_pdf_path: Path for the output filled PDF.\n \"\"\"\n with open(fields_json_path, \"r\") as f:\n fields_data = json.load(f)\n\n reader = PdfReader(input_pdf_path)\n writer = PdfWriter()\n writer.append(reader)\n\n # Get PDF dimensions for each page\n pdf_dimensions = {}\n for i, page in enumerate(reader.pages):\n mediabox = page.mediabox\n pdf_dimensions[i + 1] = [float(mediabox.width), float(mediabox.height)]\n\n # Process each form field\n annotations = []\n for field in fields_data[\"form_fields\"]:\n page_num = field[\"page_number\"]\n\n # Get page dimensions and transform coordinates\n page_info = next(p for p in fields_data[\"pages\"] if p[\"page_number\"] == page_num)\n image_width = page_info[\"image_width\"]\n image_height = page_info[\"image_height\"]\n pdf_width, pdf_height = pdf_dimensions[page_num]\n\n transformed_entry_box = transform_coordinates(\n field[\"entry_bounding_box\"],\n image_width, image_height,\n pdf_width, pdf_height\n )\n\n # Skip empty fields\n if \"entry_text\" not in field or \"text\" not in field[\"entry_text\"]:\n continue\n entry_text = field[\"entry_text\"]\n text = entry_text[\"text\"]\n if not text:\n continue\n\n font_name = entry_text.get(\"font\", \"Arial\")\n font_size = str(entry_text.get(\"font_size\", 14)) + \"pt\"\n font_color = entry_text.get(\"font_color\", \"000000\")\n\n # Note: Font size/color may render inconsistently across PDF viewers\n # https://github.com/py-pdf/pypdf/issues/2084\n annotation = FreeText(\n text=text,\n rect=transformed_entry_box,\n font=font_name,\n font_size=font_size,\n font_color=font_color,\n border_color=None,\n background_color=None,\n )\n annotations.append(annotation)\n writer.add_annotation(page_number=page_num - 1, annotation=annotation)\n\n with open(output_pdf_path, \"wb\") as output:\n writer.write(output)\n\n print(f\"Successfully filled PDF form and saved to {output_pdf_path}\")\n print(f\"Added {len(annotations)} text annotations\")\n\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description=\"Fill a non-fillable PDF by adding text annotations at specified positions.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\nExamples:\n %(prog)s form.pdf fields.json filled_form.pdf\n\nfields.json format:\n {\n \"pages\": [\n {\"page_number\": 1, \"image_width\": 800, \"image_height\": 1100}\n ],\n \"form_fields\": [\n {\n \"page_number\": 1,\n \"description\": \"Last name field\",\n \"field_label\": \"Last name\",\n \"label_bounding_box\": [30, 125, 95, 142],\n \"entry_bounding_box\": [100, 125, 280, 142],\n \"entry_text\": {\"text\": \"Johnson\", \"font_size\": 14, \"font_color\": \"000000\"}\n }\n ]\n }\n\nWorkflow:\n 1. python3 pdf_check_form.py form.pdf # Confirm non-fillable\n 2. Convert PDF to images (scripts/pdf_to_images.sh)\n 3. Visually identify fields and create fields.json\n 4. python3 pdf_validate_boxes.py fields.json # Validate boxes\n 5. python3 pdf_fill_annotations.py form.pdf fields.json output.pdf\n \"\"\"\n )\n parser.add_argument(\"input_pdf\", help=\"Path to the input PDF\")\n parser.add_argument(\"fields_json\", help=\"Path to fields.json with bounding box data\")\n parser.add_argument(\"output_pdf\", help=\"Path for the output filled PDF\")\n return parser.parse_args()\n\n\ndef main():\n args = parse_args()\n\n input_path = Path(args.input_pdf)\n fields_path = Path(args.fields_json)\n\n if not input_path.exists():\n print(f\"Error: Input PDF not found: {input_path}\", file=sys.stderr)\n sys.exit(1)\n if not fields_path.exists():\n print(f\"Error: Fields JSON not found: {fields_path}\", file=sys.stderr)\n sys.exit(1)\n\n try:\n fill_pdf_form(str(input_path), str(fields_path), args.output_pdf)\n except Exception as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":7141,"content_sha256":"f30a695321162c613ca0302ae285a60135049585135743acbe2bb6d1cee2a664"},{"filename":"scripts/pdf_fill_form.py","content":"#!/usr/bin/env python3\n\"\"\"\npdf_fill_form.py\nFill fillable form fields in a PDF with validated data.\n\nReads a field_values.json file specifying values for each field,\nvalidates all field IDs, page numbers, and type-specific values,\nthen writes the filled PDF. Exits with error if any validation fails.\n\nExamples:\n python3 pdf_fill_form.py form.pdf field_values.json filled_form.pdf\n python3 pdf_fill_form.py /path/to/form.pdf /tmp/values.json /tmp/output.pdf\n\"\"\"\n\nimport subprocess\nimport sys\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\n_ensure_package(\"pypdf\")\n\nimport argparse\nimport json\nfrom pathlib import Path\nfrom pypdf import PdfReader, PdfWriter\nfrom pdf_extract_fields import get_field_info\n\n\ndef validation_error_for_field_value(field_info, field_value):\n \"\"\"Validate a field value against its type constraints.\n\n Returns an error message string, or None if valid.\n \"\"\"\n field_type = field_info[\"type\"]\n field_id = field_info[\"field_id\"]\n if field_type == \"checkbox\":\n checked_val = field_info[\"checked_value\"]\n unchecked_val = field_info[\"unchecked_value\"]\n if field_value != checked_val and field_value != unchecked_val:\n return (f'ERROR: Invalid value \"{field_value}\" for checkbox field \"{field_id}\". '\n f'The checked value is \"{checked_val}\" and the unchecked value is \"{unchecked_val}\"')\n elif field_type == \"radio_group\":\n option_values = [opt[\"value\"] for opt in field_info[\"radio_options\"]]\n if field_value not in option_values:\n return (f'ERROR: Invalid value \"{field_value}\" for radio group field \"{field_id}\". '\n f'Valid values are: {option_values}')\n elif field_type == \"choice\":\n choice_values = [opt[\"value\"] for opt in field_info[\"choice_options\"]]\n if field_value not in choice_values:\n return (f'ERROR: Invalid value \"{field_value}\" for choice field \"{field_id}\". '\n f'Valid values are: {choice_values}')\n return None\n\n\ndef monkeypatch_pypdf_method():\n \"\"\"Fix pypdf bug with selection list fields.\n\n pypdf (at least version 5.7.0) has a bug in _writer.py around line 966:\n For selection lists, get_inherited returns a list of two-element lists like\n [[\"value1\", \"Text 1\"], [\"value2\", \"Text 2\"], ...] but join() expects strings.\n This patch extracts just the value strings when the result is a list of pairs.\n \"\"\"\n from pypdf.generic import DictionaryObject\n from pypdf.constants import FieldDictionaryAttributes\n\n original_get_inherited = DictionaryObject.get_inherited\n\n def patched_get_inherited(self, key: str, default=None):\n result = original_get_inherited(self, key, default)\n if key == FieldDictionaryAttributes.Opt:\n if isinstance(result, list) and all(isinstance(v, list) and len(v) == 2 for v in result):\n result = [r[0] for r in result]\n return result\n\n DictionaryObject.get_inherited = patched_get_inherited\n\n\ndef fill_pdf_fields(input_pdf_path: str, fields_json_path: str, output_pdf_path: str):\n \"\"\"Fill fillable form fields in a PDF.\n\n Args:\n input_pdf_path: Path to the input PDF with fillable fields.\n fields_json_path: Path to JSON file with field values.\n output_pdf_path: Path for the output filled PDF.\n\n The field_values.json format:\n [\n {\"field_id\": \"last_name\", \"page\": 1, \"value\": \"Simpson\"},\n {\"field_id\": \"Checkbox12\", \"page\": 1, \"value\": \"/On\"},\n ...\n ]\n \"\"\"\n with open(fields_json_path) as f:\n fields = json.load(f)\n\n # Group by page number\n fields_by_page = {}\n for field in fields:\n if \"value\" in field:\n field_id = field[\"field_id\"]\n page = field[\"page\"]\n if page not in fields_by_page:\n fields_by_page[page] = {}\n fields_by_page[page][field_id] = field[\"value\"]\n\n reader = PdfReader(input_pdf_path)\n\n # Pre-validate all fields before writing\n has_error = False\n field_info = get_field_info(reader)\n fields_by_ids = {f[\"field_id\"]: f for f in field_info}\n\n for field in fields:\n existing_field = fields_by_ids.get(field[\"field_id\"])\n if not existing_field:\n has_error = True\n print(f\"ERROR: `{field['field_id']}` is not a valid field ID\")\n elif field[\"page\"] != existing_field[\"page\"]:\n has_error = True\n print(f\"ERROR: Incorrect page number for `{field['field_id']}` \"\n f\"(got {field['page']}, expected {existing_field['page']})\")\n else:\n if \"value\" in field:\n err = validation_error_for_field_value(existing_field, field[\"value\"])\n if err:\n print(err)\n has_error = True\n\n if has_error:\n sys.exit(1)\n\n writer = PdfWriter(clone_from=reader)\n for page, field_values in fields_by_page.items():\n writer.update_page_form_field_values(\n writer.pages[page - 1], field_values, auto_regenerate=False\n )\n\n # Necessary for many PDF viewers to format the form values correctly\n writer.set_need_appearances_writer(True)\n\n with open(output_pdf_path, \"wb\") as f:\n writer.write(f)\n\n print(f\"Successfully filled PDF form and saved to {output_pdf_path}\")\n\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description=\"Fill fillable form fields in a PDF with validated data.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\nExamples:\n %(prog)s form.pdf field_values.json filled_form.pdf\n\nfield_values.json format:\n [\n {\"field_id\": \"last_name\", \"page\": 1, \"value\": \"Simpson\"},\n {\"field_id\": \"Checkbox12\", \"page\": 1, \"value\": \"/On\"},\n {\"field_id\": \"country\", \"page\": 2, \"value\": \"US\"}\n ]\n\nWorkflow:\n 1. python3 pdf_check_form.py form.pdf # Check if fillable\n 2. python3 pdf_extract_fields.py form.pdf fields.json # Extract field info\n 3. Create field_values.json with values for each field\n 4. python3 pdf_fill_form.py form.pdf field_values.json output.pdf\n \"\"\"\n )\n parser.add_argument(\"input_pdf\", help=\"Path to the input PDF with fillable fields\")\n parser.add_argument(\"field_values_json\", help=\"Path to JSON file with field values\")\n parser.add_argument(\"output_pdf\", help=\"Path for the output filled PDF\")\n return parser.parse_args()\n\n\ndef main():\n args = parse_args()\n\n input_path = Path(args.input_pdf)\n values_path = Path(args.field_values_json)\n\n if not input_path.exists():\n print(f\"Error: Input PDF not found: {input_path}\", file=sys.stderr)\n sys.exit(1)\n if not values_path.exists():\n print(f\"Error: Field values JSON not found: {values_path}\", file=sys.stderr)\n sys.exit(1)\n\n try:\n monkeypatch_pypdf_method()\n fill_pdf_fields(str(input_path), str(values_path), args.output_pdf)\n except Exception as e:\n print(f\"Error: {e}\", file=sys.stderr)\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":8118,"content_sha256":"468cd05ba2e3f27d3015720905bb9d9b56173d1917e9a6337c2ba8d9e1fac8cd"},{"filename":"scripts/pdf_merge.sh","content":"#!/usr/bin/env bash\n\n# pdf_merge.sh\n# Merge multiple PDFs into one\n#\n# Examples:\n# ./pdf_merge.sh file1.pdf file2.pdf file3.pdf --output combined.pdf\n# ./pdf_merge.sh chapter*.pdf --output book.pdf\n# ./pdf_merge.sh intro.pdf body.pdf appendix.pdf\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nOUTPUT_FILE=\"merged.pdf\"\nINPUT_FILES=()\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cfile1.pdf> \u003cfile2.pdf> ... [OPTIONS]\n\nMerge multiple PDFs into one document.\n\nArguments:\n file1.pdf file2.pdf ... Input PDF files to merge (minimum 2 files)\n\nOptions:\n --output \u003cfile> Output file path (default: merged.pdf)\n -h, --help Show this help message\n\nExamples:\n $0 file1.pdf file2.pdf file3.pdf --output combined.pdf\n $0 chapter*.pdf --output book.pdf\n $0 intro.pdf body.pdf appendix.pdf\n\nRequires: qpdf (auto-installed if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n INPUT_FILES+=(\"$1\")\n shift\n ;;\n esac\ndone\n\n# Validate input files\nif [[ ${#INPUT_FILES[@]} -lt 2 ]]; then\n echo \"Error: At least 2 PDF files are required for merging\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\n# Check all input files exist\nfor file in \"${INPUT_FILES[@]}\"; do\n if [[ ! -f \"$file\" ]]; then\n echo \"Error: Input file not found: $file\" >&2\n exit 1\n fi\n # Verify it's a PDF\n if ! file \"$file\" | grep -q \"PDF\"; then\n echo \"Error: Not a valid PDF file: $file\" >&2\n exit 1\n fi\ndone\n\n# Check for qpdf, install if missing\nif ! command -v qpdf &>/dev/null; then\n echo \"qpdf not found. Installing...\" >&2\n\n # Map qpdf to platform packages\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt) run_pkg_install qpdf ;;\n brew) run_pkg_install qpdf ;;\n dnf) run_pkg_install qpdf ;;\n apk) run_pkg_install qpdf ;;\n pacman) run_pkg_install qpdf ;;\n *)\n echo \"Error: Could not auto-install qpdf\" >&2\n echo \"Please install manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install qpdf\" >&2\n echo \" macOS: brew install qpdf\" >&2\n echo \" Fedora/RHEL: sudo dnf install qpdf\" >&2\n echo \" Alpine: sudo apk add qpdf\" >&2\n echo \" Arch: sudo pacman -S qpdf\" >&2\n exit 1\n ;;\n esac\n\n if ! command -v qpdf &>/dev/null; then\n echo \"Error: qpdf installation failed\" >&2\n exit 1\n fi\nfi\n\n# Build qpdf command\necho \"Merging ${#INPUT_FILES[@]} PDF files...\" >&2\n\n# Display files being merged\nfor i in \"${!INPUT_FILES[@]}\"; do\n echo \" $((i+1)). ${INPUT_FILES[$i]}\" >&2\ndone\necho \"\" >&2\n\n# Execute merge using qpdf\n# The first file is the base, then we append the rest\nif qpdf --empty --pages \"${INPUT_FILES[@]}\" -- \"$OUTPUT_FILE\" 2>&1; then\n # Get file size\n SIZE=$(du -h \"$OUTPUT_FILE\" | cut -f1)\n echo \"Successfully created: $OUTPUT_FILE ($SIZE)\" >&2\n exit 0\nelse\n echo \"Error: Failed to merge PDF files\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":3508,"content_sha256":"64d884e4b5da88b2f541161a28150b10c8790cfc68b932f08bdfadd361643158"},{"filename":"scripts/pdf_optimize.sh","content":"#!/usr/bin/env bash\n\n# pdf_optimize.sh\n# Compress and linearize PDFs for web/email\n#\n# Examples:\n# ./pdf_optimize.sh document.pdf\n# ./pdf_optimize.sh large_file.pdf --output compressed.pdf\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nOUTPUT_FILE=\"\"\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cinput.pdf> [OPTIONS]\n\nCompress and linearize PDFs for fast web viewing and reduced file size.\n\nArguments:\n input.pdf Input PDF file to optimize\n\nOptions:\n --output \u003cfile> Output file path (default: input_optimized.pdf)\n -h, --help Show this help message\n\nExamples:\n $0 document.pdf\n $0 large_file.pdf --output compressed.pdf\n\nRequires: qpdf (auto-installed if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\n# Parse arguments\nINPUT_FILE=\"\"\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n -*)\n echo \"Error: Unknown option: $1\" >&2\n exit 1\n ;;\n *)\n if [[ -z \"$INPUT_FILE\" ]]; then\n INPUT_FILE=\"$1\"\n else\n echo \"Error: Multiple input files specified\" >&2\n exit 1\n fi\n shift\n ;;\n esac\ndone\n\n# Validate input file\nif [[ -z \"$INPUT_FILE\" ]]; then\n echo \"Error: No input file specified\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\nfi\n\nif [[ ! -f \"$INPUT_FILE\" ]]; then\n echo \"Error: Input file not found: $INPUT_FILE\" >&2\n exit 1\nfi\n\n# Set default output file\nif [[ -z \"$OUTPUT_FILE\" ]]; then\n BASENAME=\"${INPUT_FILE%.pdf}\"\n OUTPUT_FILE=\"${BASENAME}_optimized.pdf\"\nfi\n\n# Check for qpdf, install if missing\nif ! command -v qpdf &>/dev/null; then\n echo \"qpdf not found. Installing...\" >&2\n\n # Map qpdf to platform packages\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt) run_pkg_install qpdf ;;\n brew) run_pkg_install qpdf ;;\n dnf) run_pkg_install qpdf ;;\n apk) run_pkg_install qpdf ;;\n pacman) run_pkg_install qpdf ;;\n *)\n echo \"Error: Could not auto-install qpdf\" >&2\n echo \"Please install manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install qpdf\" >&2\n echo \" macOS: brew install qpdf\" >&2\n echo \" Fedora/RHEL: sudo dnf install qpdf\" >&2\n echo \" Alpine: sudo apk add qpdf\" >&2\n echo \" Arch: sudo pacman -S qpdf\" >&2\n exit 1\n ;;\n esac\n\n if ! command -v qpdf &>/dev/null; then\n echo \"Error: qpdf installation failed\" >&2\n exit 1\n fi\nfi\n\n# Get original file size\nORIGINAL_SIZE=$(stat -f%z \"$INPUT_FILE\" 2>/dev/null || stat -c%s \"$INPUT_FILE\" 2>/dev/null)\nORIGINAL_SIZE_HUMAN=$(du -h \"$INPUT_FILE\" | cut -f1)\n\necho \"Optimizing $INPUT_FILE...\" >&2\necho \"Original size: $ORIGINAL_SIZE_HUMAN\" >&2\n\n# Optimize with qpdf\n# --linearize: optimize for fast web viewing (byte-serving)\n# --compress-streams=y: compress internal streams\n# --recompress-flate: recompress with better compression\n# --object-streams=generate: pack objects into streams for smaller size\nif qpdf \\\n --linearize \\\n --compress-streams=y \\\n --recompress-flate \\\n --object-streams=generate \\\n \"$INPUT_FILE\" \\\n \"$OUTPUT_FILE\" 2>&1; then\n\n # Get optimized file size\n OPTIMIZED_SIZE=$(stat -f%z \"$OUTPUT_FILE\" 2>/dev/null || stat -c%s \"$OUTPUT_FILE\" 2>/dev/null)\n OPTIMIZED_SIZE_HUMAN=$(du -h \"$OUTPUT_FILE\" | cut -f1)\n\n # Calculate size reduction\n if [[ $ORIGINAL_SIZE -gt 0 ]]; then\n REDUCTION=$((100 - (OPTIMIZED_SIZE * 100 / ORIGINAL_SIZE)))\n echo \"Optimized size: $OPTIMIZED_SIZE_HUMAN (${REDUCTION}% reduction)\" >&2\n else\n echo \"Optimized size: $OPTIMIZED_SIZE_HUMAN\" >&2\n fi\n\n echo \"\" >&2\n echo \"Successfully created: $OUTPUT_FILE\" >&2\n echo \"The PDF is now linearized for fast web viewing\" >&2\n exit 0\nelse\n echo \"Error: Failed to optimize PDF\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4224,"content_sha256":"e8675cea94ca53a751f1dfc315af3607892d17254fae0b78e56b35216eefa9ed"},{"filename":"scripts/pdf_to_images.sh","content":"#!/usr/bin/env bash\n# pdf_to_images.sh - Split a PDF into page images for OCR/vision processing\n#\n# Usage:\n# pdf_to_images.sh \u003cinput.pdf> \u003coutput_dir> [--dpi \u003cdpi>] [--max-dim \u003cpixels>]\n#\n# Options:\n# --dpi Resolution for rendering (default: 200)\n# --max-dim Max dimension in pixels; images are resized if larger (default: 2000)\n#\n# Output:\n# Creates page-001.png, page-002.png, etc. in output_dir\n# Prints total page count on success\n\nset -euo pipefail\n\n# --- Usage function ---\nusage() {\n cat \u003c\u003c'EOF'\npdf_to_images.sh - Split a PDF into page images for OCR/vision processing\n\nUsage:\n pdf_to_images.sh \u003cinput.pdf> \u003coutput_dir> [--dpi \u003cdpi>] [--max-dim \u003cpixels>]\n\nOptions:\n --dpi Resolution for rendering (default: 200)\n --max-dim Max dimension in pixels; images are resized if larger (default: 2000)\n\nOutput:\n Creates page-001.png, page-002.png, etc. in output_dir\n Prints total page count on success\nEOF\n}\n\n# --- Source cross-platform dependency installer ---\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\nINPUT_PDF=\"\"\nOUTPUT_DIR=\"\"\nDPI=200\nMAX_DIM=2000\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --help|-h) usage; exit 0 ;;\n --dpi) DPI=\"$2\"; shift 2 ;;\n --max-dim) MAX_DIM=\"$2\"; shift 2 ;;\n -*) echo \"Error: Unknown option $1\" >&2; exit 1 ;;\n *)\n if [[ -z \"$INPUT_PDF\" ]]; then\n INPUT_PDF=\"$1\"\n elif [[ -z \"$OUTPUT_DIR\" ]]; then\n OUTPUT_DIR=\"$1\"\n fi\n shift ;;\n esac\ndone\n\nif [[ -z \"$INPUT_PDF\" || -z \"$OUTPUT_DIR\" ]]; then\n echo \"Usage: pdf_to_images.sh \u003cinput.pdf> \u003coutput_dir> [--dpi \u003cdpi>] [--max-dim \u003cpixels>]\" >&2\n exit 1\nfi\n\n# Ensure dependencies\nMISSING_DEPS=()\ncommand -v pdftoppm &>/dev/null || MISSING_DEPS+=(\"poppler\")\ncommand -v pdfinfo &>/dev/null || { [[ ! \" ${MISSING_DEPS[*]} \" =~ \" poppler \" ]] && MISSING_DEPS+=(\"poppler\"); }\ncommand -v mogrify &>/dev/null || MISSING_DEPS+=(\"imagemagick\")\n\nif [[ ${#MISSING_DEPS[@]} -gt 0 ]]; then\n echo \":: Installing dependencies: ${MISSING_DEPS[*]}...\" >&2\n install_packages \"${MISSING_DEPS[@]}\" || {\n echo \"Error: Failed to install dependencies.\" >&2\n for dep in \"${MISSING_DEPS[@]}\"; do\n print_install_help \"$dep\"\n done\n exit 1\n }\nfi\n\nmkdir -p \"$OUTPUT_DIR\"\n\n# Get page count\nPAGES=$(pdfinfo \"$INPUT_PDF\" 2>/dev/null | grep \"Pages:\" | awk '{print $2}')\nif [[ -z \"$PAGES\" || \"$PAGES\" -eq 0 ]]; then\n echo \"Error: Could not determine page count from PDF\" >&2\n exit 1\nfi\necho \":: PDF has $PAGES pages\" >&2\n\n# Render to PNG\necho \":: Rendering at ${DPI} DPI...\" >&2\npdftoppm -png -r \"$DPI\" \"$INPUT_PDF\" \"${OUTPUT_DIR}/page\"\n\n# Rename to zero-padded 3-digit format\ncd \"$OUTPUT_DIR\"\nshopt -s nullglob\nFILES=(page-*.png)\nshopt -u nullglob\n\nif [[ ${#FILES[@]} -eq 0 ]]; then\n echo \"Error: pdftoppm produced no PNG files\" >&2\n exit 1\nfi\n\nfor f in \"${FILES[@]}\"; do\n # pdftoppm may produce page-1.png or page-01.png depending on page count\n NUM=$(echo \"$f\" | sed 's/page-0*\\([0-9]*\\)\\.png/\\1/')\n PADDED=$(printf \"page-%03d.png\" \"$NUM\")\n if [[ \"$f\" != \"$PADDED\" ]]; then\n mv \"$f\" \"$PADDED\" 2>/dev/null || true\n fi\ndone\n\n# Resize if needed (API limit: 2000px max for multi-image requests)\nshopt -s nullglob\nPNG_FILES=(page-*.png)\nshopt -u nullglob\n\nif [[ ${#PNG_FILES[@]} -gt 0 ]]; then\n SAMPLE=\"${PNG_FILES[0]}\"\n WIDTH=$(identify -format '%w' \"$SAMPLE\" 2>/dev/null || echo 0)\n HEIGHT=$(identify -format '%h' \"$SAMPLE\" 2>/dev/null || echo 0)\n\n if [[ \"$WIDTH\" -gt \"$MAX_DIM\" || \"$HEIGHT\" -gt \"$MAX_DIM\" ]]; then\n echo \":: Resizing ${#PNG_FILES[@]} images from ${WIDTH}x${HEIGHT} to fit within ${MAX_DIM}px...\" >&2\n local_count=0\n for img in \"${PNG_FILES[@]}\"; do\n mogrify -resize \"${MAX_DIM}x${MAX_DIM}>\" \"$img\"\n local_count=$((local_count + 1))\n if (( local_count % 10 == 0 )); then\n echo \":: Resized ${local_count}/${#PNG_FILES[@]}...\" >&2\n fi\n done\n NEW_W=$(identify -format '%w' \"$SAMPLE\" 2>/dev/null)\n NEW_H=$(identify -format '%h' \"$SAMPLE\" 2>/dev/null)\n echo \":: Resized all ${#PNG_FILES[@]} images to ~${NEW_W}x${NEW_H}\" >&2\n fi\nfi\n\nFINAL_COUNT=${#PNG_FILES[@]}\necho \":: Created $FINAL_COUNT page images in $OUTPUT_DIR\" >&2\necho \"$FINAL_COUNT\"\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":4223,"content_sha256":"207963f6acace8dd175722f17e27984e672cfa5f73d8aa588f891a48466ddcba"},{"filename":"scripts/pdf_validate_boxes.py","content":"#!/usr/bin/env python3\n\"\"\"\npdf_validate_boxes.py\nValidate bounding boxes in fields.json and optionally create validation images.\n\nChecks that bounding boxes don't intersect and that entry boxes are tall enough\nfor their font sizes. Can also generate overlay images with colored rectangles\nfor visual verification (red = entry areas, blue = label areas).\n\nExamples:\n # Validate only\n python3 pdf_validate_boxes.py fields.json\n\n # Validate + create validation image for page 1\n python3 pdf_validate_boxes.py fields.json --image page_1.png --output validation_1.png --page 1\n\"\"\"\n\nimport subprocess\nimport sys\n\n\ndef _ensure_package(pip_name, import_name=None):\n \"\"\"Try importing a package; auto-install via pip if missing.\"\"\"\n if import_name is None:\n import_name = pip_name\n try:\n __import__(import_name)\n except ImportError:\n print(f\":: Package '{import_name}' not found. Installing {pip_name}...\", file=sys.stderr)\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except subprocess.CalledProcessError:\n try:\n subprocess.check_call(\n [sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n \"--break-system-packages\", pip_name],\n stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,\n )\n except Exception as e:\n print(f\"Error: Failed to install {pip_name}: {e}\", file=sys.stderr)\n print(f\"Please install manually: pip install {pip_name}\", file=sys.stderr)\n sys.exit(1)\n\n\nimport argparse\nimport json\nfrom dataclasses import dataclass\nfrom pathlib import Path\n\n\n@dataclass\nclass RectAndField:\n rect: list\n rect_type: str\n field: dict\n\n\ndef rects_intersect(r1, r2):\n \"\"\"Check if two rectangles [left, top, right, bottom] intersect.\"\"\"\n disjoint_horizontal = r1[0] >= r2[2] or r1[2] \u003c= r2[0]\n disjoint_vertical = r1[1] >= r2[3] or r1[3] \u003c= r2[1]\n return not (disjoint_horizontal or disjoint_vertical)\n\n\ndef get_bounding_box_messages(fields_data) -> list:\n \"\"\"Validate bounding boxes in fields data.\n\n Returns a list of validation messages (SUCCESS or FAILURE).\n \"\"\"\n messages = []\n messages.append(f\"Read {len(fields_data['form_fields'])} fields\")\n\n rects_and_fields = []\n for f in fields_data[\"form_fields\"]:\n rects_and_fields.append(RectAndField(f[\"label_bounding_box\"], \"label\", f))\n rects_and_fields.append(RectAndField(f[\"entry_bounding_box\"], \"entry\", f))\n\n has_error = False\n for i, ri in enumerate(rects_and_fields):\n for j in range(i + 1, len(rects_and_fields)):\n rj = rects_and_fields[j]\n if ri.field[\"page_number\"] == rj.field[\"page_number\"] and rects_intersect(ri.rect, rj.rect):\n has_error = True\n if ri.field is rj.field:\n messages.append(\n f\"FAILURE: intersection between label and entry bounding boxes \"\n f\"for `{ri.field['description']}` ({ri.rect}, {rj.rect})\")\n else:\n messages.append(\n f\"FAILURE: intersection between {ri.rect_type} bounding box \"\n f\"for `{ri.field['description']}` ({ri.rect}) and {rj.rect_type} \"\n f\"bounding box for `{rj.field['description']}` ({rj.rect})\")\n if len(messages) >= 20:\n messages.append(\"Aborting further checks; fix bounding boxes and try again\")\n return messages\n\n if ri.rect_type == \"entry\":\n if \"entry_text\" in ri.field:\n font_size = ri.field[\"entry_text\"].get(\"font_size\", 14)\n entry_height = ri.rect[3] - ri.rect[1]\n if entry_height \u003c font_size:\n has_error = True\n messages.append(\n f\"FAILURE: entry bounding box height ({entry_height}) for \"\n f\"`{ri.field['description']}` is too short for the text content \"\n f\"(font size: {font_size}). Increase the box height or decrease the font size.\")\n if len(messages) >= 20:\n messages.append(\"Aborting further checks; fix bounding boxes and try again\")\n return messages\n\n if not has_error:\n messages.append(\"SUCCESS: All bounding boxes are valid\")\n return messages\n\n\ndef create_validation_image(page_number, fields_data, input_path, output_path):\n \"\"\"Create a validation image with colored bounding box overlays.\n\n Red rectangles = entry areas (where text will be placed).\n Blue rectangles = label areas (field labels).\n\n Args:\n page_number: Page number to create validation image for (1-based).\n fields_data: Parsed fields.json data dict.\n input_path: Path to the source page image (PNG).\n output_path: Path for the output validation image.\n \"\"\"\n _ensure_package(\"Pillow\", \"PIL\")\n from PIL import Image, ImageDraw\n\n img = Image.open(input_path)\n draw = ImageDraw.Draw(img)\n num_boxes = 0\n\n for field in fields_data[\"form_fields\"]:\n if field[\"page_number\"] == page_number:\n entry_box = field['entry_bounding_box']\n label_box = field['label_bounding_box']\n draw.rectangle(entry_box, outline='red', width=2)\n draw.rectangle(label_box, outline='blue', width=2)\n num_boxes += 2\n\n img.save(output_path)\n print(f\"Created validation image at {output_path} with {num_boxes} bounding boxes\")\n\n\ndef parse_args():\n parser = argparse.ArgumentParser(\n description=\"Validate bounding boxes in fields.json and optionally create validation images.\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\nExamples:\n # Validate bounding boxes only\n %(prog)s fields.json\n\n # Validate + create validation image for page 1\n %(prog)s fields.json --image page_1.png --output validation_1.png --page 1\n\nValidation checks:\n - No intersections between bounding boxes on the same page\n - No overlap between label and entry boxes of the same field\n - Entry box height is sufficient for the font size\n\nValidation image colors:\n - Red rectangles = entry areas (where text will be placed)\n - Blue rectangles = label areas (field labels)\n \"\"\"\n )\n parser.add_argument(\"fields_json\", help=\"Path to fields.json file\")\n parser.add_argument(\"--image\", help=\"Path to page image (PNG) for validation overlay\")\n parser.add_argument(\"--output\", help=\"Path for the output validation image\")\n parser.add_argument(\"--page\", type=int, help=\"Page number for validation image (1-based)\")\n return parser.parse_args()\n\n\ndef main():\n args = parse_args()\n\n fields_path = Path(args.fields_json)\n if not fields_path.exists():\n print(f\"Error: Fields JSON not found: {fields_path}\", file=sys.stderr)\n sys.exit(1)\n\n try:\n with open(fields_path) as f:\n fields_data = json.load(f)\n except json.JSONDecodeError as e:\n print(f\"Error: Invalid JSON in {fields_path}: {e}\", file=sys.stderr)\n sys.exit(1)\n\n # Run validation\n messages = get_bounding_box_messages(fields_data)\n for msg in messages:\n print(msg)\n\n # Create validation image if requested\n if args.image:\n if not args.output:\n print(\"Error: --output is required when --image is specified\", file=sys.stderr)\n sys.exit(1)\n if not args.page:\n print(\"Error: --page is required when --image is specified\", file=sys.stderr)\n sys.exit(1)\n\n image_path = Path(args.image)\n if not image_path.exists():\n print(f\"Error: Image not found: {image_path}\", file=sys.stderr)\n sys.exit(1)\n\n create_validation_image(args.page, fields_data, str(image_path), args.output)\n\n # Exit with error if validation failed\n if any(\"FAILURE\" in msg for msg in messages):\n sys.exit(1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":8226,"content_sha256":"0640a05c41a1b121350c1c8a0320c13f7d1af29bb26104f0777335d85c352602"},{"filename":"scripts/plantuml_to_pdf.sh","content":"#!/usr/bin/env bash\n\n# plantuml_to_pdf.sh\n# Converts PlantUML .puml files to PDF, PNG, or SVG for LaTeX inclusion\n#\n# Examples:\n# ./plantuml_to_pdf.sh diagram.puml\n# ./plantuml_to_pdf.sh diagram.puml --output result.pdf --format pdf\n# ./plantuml_to_pdf.sh diagram.puml --format svg\n# ./plantuml_to_pdf.sh diagrams/source/ # Batch mode\n\nset -euo pipefail\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nsource \"${SCRIPT_DIR}/install_deps.sh\"\n\n# Default values\nFORMAT=\"pdf\"\nOUTPUT_FILE=\"\"\nRESOLUTION=\"300\"\n\n# Print usage\nusage() {\n cat \u003c\u003c EOF\nUsage: $0 \u003cinput.puml|directory> [OPTIONS]\n\nConvert PlantUML .puml files to PDF, PNG, or SVG for LaTeX inclusion.\n\nArguments:\n input.puml Input PlantUML .puml file\n directory Directory containing .puml files (batch mode)\n\nOptions:\n --output FILE Output file path (default: input name with format extension)\n --format FORMAT Output format: pdf, png, or svg (default: pdf)\n --resolution RES Resolution for PNG output (default: 300)\n -h, --help Show this help message\n\nExamples:\n $0 diagram.puml\n $0 diagram.puml --output result.pdf\n $0 diagram.puml --format png\n $0 diagrams/source/ --format pdf\n\nRequires: plantuml and Java (auto-installs if missing)\nEOF\n exit 0\n}\n\n# Check if help is requested or no args\nif [[ $# -eq 0 ]] || [[ \"${1:-}\" == \"-h\" ]] || [[ \"${1:-}\" == \"--help\" ]]; then\n usage\nfi\n\nINPUT_PATH=\"$1\"\nshift\n\n# Parse options\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n --output)\n OUTPUT_FILE=\"$2\"\n shift 2\n ;;\n --format)\n FORMAT=\"$2\"\n shift 2\n ;;\n --resolution)\n RESOLUTION=\"$2\"\n shift 2\n ;;\n *)\n echo \"Error: Unknown option: $1\" >&2\n echo \"Run '$0 --help' for usage information\" >&2\n exit 1\n ;;\n esac\ndone\n\n# Validate format\ncase \"$FORMAT\" in\n pdf|png|svg)\n ;;\n *)\n echo \"Error: Format must be 'pdf', 'png', or 'svg', got: $FORMAT\" >&2\n exit 1\n ;;\nesac\n\n# Validate resolution is a number\nif ! [[ \"$RESOLUTION\" =~ ^[0-9]+$ ]]; then\n echo \"Error: Resolution must be a number, got: $RESOLUTION\" >&2\n exit 1\nfi\n\n# Check if Java is installed (required for PlantUML)\nif ! command -v java &>/dev/null; then\n echo \"Java not found. PlantUML requires Java.\" >&2\n echo \"\" >&2\n echo \"Installing Java...\" >&2\n\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt)\n run_pkg_install default-jre\n ;;\n brew)\n run_pkg_install openjdk\n ;;\n dnf)\n run_pkg_install java-latest-openjdk\n ;;\n apk)\n run_pkg_install openjdk11-jre\n ;;\n pacman)\n run_pkg_install jre-openjdk\n ;;\n *)\n echo \"Error: Could not auto-install Java\" >&2\n echo \"\" >&2\n echo \"Please install Java manually:\" >&2\n echo \" Debian/Ubuntu: sudo apt-get install default-jre\" >&2\n echo \" macOS: brew install openjdk\" >&2\n echo \" Fedora/RHEL: sudo dnf install java-latest-openjdk\" >&2\n echo \" Alpine: sudo apk add openjdk11-jre\" >&2\n echo \" Arch: sudo pacman -S jre-openjdk\" >&2\n echo \"\" >&2\n echo \"Or download from: https://adoptium.net/\" >&2\n exit 1\n ;;\n esac\nfi\n\n# Check if PlantUML is installed\nPLANTUML_CMD=\"\"\n\nif command -v plantuml &>/dev/null; then\n # PlantUML is installed as a command\n PLANTUML_CMD=\"plantuml\"\nelif [[ -f \"$HOME/.local/share/plantuml/plantuml.jar\" ]]; then\n # PlantUML JAR is in local directory\n PLANTUML_CMD=\"java -jar $HOME/.local/share/plantuml/plantuml.jar\"\nelif [[ -f \"/usr/share/plantuml/plantuml.jar\" ]]; then\n # PlantUML JAR is in system directory\n PLANTUML_CMD=\"java -jar /usr/share/plantuml/plantuml.jar\"\nelse\n # Try to install PlantUML\n echo \"PlantUML not found. Installing...\" >&2\n\n mgr=\"$(detect_pkg_manager)\"\n case \"$mgr\" in\n apt)\n run_pkg_install plantuml\n PLANTUML_CMD=\"plantuml\"\n ;;\n brew)\n run_pkg_install plantuml\n PLANTUML_CMD=\"plantuml\"\n ;;\n dnf)\n run_pkg_install plantuml\n PLANTUML_CMD=\"plantuml\"\n ;;\n apk)\n run_pkg_install plantuml\n PLANTUML_CMD=\"plantuml\"\n ;;\n pacman)\n run_pkg_install plantuml\n PLANTUML_CMD=\"plantuml\"\n ;;\n *)\n # Download PlantUML JAR manually\n echo \"Package manager installation not available. Downloading PlantUML JAR...\" >&2\n mkdir -p \"$HOME/.local/share/plantuml\"\n PLANTUML_JAR=\"$HOME/.local/share/plantuml/plantuml.jar\"\n\n if command -v curl &>/dev/null; then\n curl -L -o \"$PLANTUML_JAR\" \"https://github.com/plantuml/plantuml/releases/download/v1.2024.8/plantuml-1.2024.8.jar\"\n elif command -v wget &>/dev/null; then\n wget -O \"$PLANTUML_JAR\" \"https://github.com/plantuml/plantuml/releases/download/v1.2024.8/plantuml-1.2024.8.jar\"\n else\n echo \"Error: Neither curl nor wget found. Cannot download PlantUML.\" >&2\n echo \"\" >&2\n echo \"Please install PlantUML manually:\" >&2\n echo \" 1. Download from: https://plantuml.com/download\" >&2\n echo \" 2. Save as: $PLANTUML_JAR\" >&2\n exit 1\n fi\n\n if [[ -f \"$PLANTUML_JAR\" ]]; then\n echo \"Successfully downloaded PlantUML to $PLANTUML_JAR\" >&2\n PLANTUML_CMD=\"java -jar $PLANTUML_JAR\"\n else\n echo \"Error: Failed to download PlantUML\" >&2\n exit 1\n fi\n ;;\n esac\nfi\n\n# Verify PlantUML works\nif ! $PLANTUML_CMD -version &>/dev/null; then\n echo \"Error: PlantUML installation failed or is not working\" >&2\n exit 1\nfi\n\n# Function to convert a single file\nconvert_file() {\n local input_file=\"$1\"\n local output_file=\"$2\"\n\n if [[ ! -f \"$input_file\" ]]; then\n echo \"Error: Input file not found: $input_file\" >&2\n return 1\n fi\n\n # Validate .puml extension\n if [[ ! \"$input_file\" =~ \\.(puml|plantuml|pu)$ ]]; then\n echo \"Warning: Input file does not have .puml extension: $input_file\" >&2\n fi\n\n echo \"Converting $input_file -> $output_file (format: $FORMAT)\" >&2\n\n # Build command based on format\n local format_flag=\"\"\n case \"$FORMAT\" in\n pdf)\n format_flag=\"-tpdf\"\n ;;\n png)\n format_flag=\"-tpng\"\n ;;\n svg)\n format_flag=\"-tsvg\"\n ;;\n esac\n\n # PlantUML outputs to the same directory as input by default\n # We need to handle output path specially\n local output_dir\n output_dir=\"$(dirname \"$output_file\")\"\n local output_filename\n output_filename=\"$(basename \"$output_file\")\"\n\n # Create a temporary copy if we need to control output location\n if [[ \"$output_dir\" != \"$(dirname \"$input_file\")\" ]]; then\n # Output to different directory - use -o flag\n if [[ \"$FORMAT\" == \"png\" ]]; then\n $PLANTUML_CMD \"$format_flag\" -Sresolution=\"$RESOLUTION\" -o \"$(realpath \"$output_dir\")\" \"$input_file\" 2>&1\n else\n $PLANTUML_CMD \"$format_flag\" -o \"$(realpath \"$output_dir\")\" \"$input_file\" 2>&1\n fi\n\n # PlantUML uses input filename, may need to rename\n local default_output\n default_output=\"$output_dir/$(basename \"${input_file%.*}\").$FORMAT\"\n if [[ \"$default_output\" != \"$output_file\" ]] && [[ -f \"$default_output\" ]]; then\n mv \"$default_output\" \"$output_file\"\n fi\n else\n # Output to same directory as input\n if [[ \"$FORMAT\" == \"png\" ]]; then\n $PLANTUML_CMD \"$format_flag\" -Sresolution=\"$RESOLUTION\" \"$input_file\" 2>&1\n else\n $PLANTUML_CMD \"$format_flag\" \"$input_file\" 2>&1\n fi\n\n # Rename if needed\n local default_output\n default_output=\"$(dirname \"$input_file\")/$(basename \"${input_file%.*}\").$FORMAT\"\n if [[ \"$default_output\" != \"$output_file\" ]] && [[ -f \"$default_output\" ]]; then\n mv \"$default_output\" \"$output_file\"\n fi\n fi\n\n if [[ -f \"$output_file\" ]]; then\n echo \"Successfully created: $output_file\" >&2\n return 0\n else\n echo \"Error: Failed to convert $input_file\" >&2\n return 1\n fi\n}\n\n# Check if input is a directory (batch mode) or a file\nif [[ -d \"$INPUT_PATH\" ]]; then\n # Batch mode: convert all .puml files in directory\n echo \"Batch mode: converting all .puml files in $INPUT_PATH\" >&2\n\n # Remove trailing slash\n INPUT_PATH=\"${INPUT_PATH%/}\"\n\n # Find all .puml files (and variants)\n shopt -s nullglob\n puml_files=(\"$INPUT_PATH\"/*.puml \"$INPUT_PATH\"/*.plantuml \"$INPUT_PATH\"/*.pu)\n\n if [[ ${#puml_files[@]} -eq 0 ]]; then\n echo \"Error: No .puml files found in $INPUT_PATH\" >&2\n exit 1\n fi\n\n echo \"Found ${#puml_files[@]} .puml file(s)\" >&2\n\n success_count=0\n fail_count=0\n\n for puml_file in \"${puml_files[@]}\"; do\n # Handle different extensions\n if [[ \"$puml_file\" =~ \\.puml$ ]]; then\n filename=$(basename \"$puml_file\" .puml)\n elif [[ \"$puml_file\" =~ \\.plantuml$ ]]; then\n filename=$(basename \"$puml_file\" .plantuml)\n elif [[ \"$puml_file\" =~ \\.pu$ ]]; then\n filename=$(basename \"$puml_file\" .pu)\n else\n filename=$(basename \"$puml_file\")\n fi\n\n output_file=\"$INPUT_PATH/${filename}.$FORMAT\"\n\n if convert_file \"$puml_file\" \"$output_file\"; then\n ((success_count++))\n else\n ((fail_count++))\n fi\n done\n\n echo \"\" >&2\n echo \"Batch conversion complete:\" >&2\n echo \" Success: $success_count\" >&2\n echo \" Failed: $fail_count\" >&2\n\n if [[ $fail_count -gt 0 ]]; then\n exit 1\n fi\n\nelif [[ -f \"$INPUT_PATH\" ]]; then\n # Single file mode\n\n # Determine output file\n if [[ -z \"$OUTPUT_FILE\" ]]; then\n # Default: replace extension with format\n if [[ \"$INPUT_PATH\" =~ \\.puml$ ]]; then\n OUTPUT_FILE=\"${INPUT_PATH%.puml}.$FORMAT\"\n elif [[ \"$INPUT_PATH\" =~ \\.plantuml$ ]]; then\n OUTPUT_FILE=\"${INPUT_PATH%.plantuml}.$FORMAT\"\n elif [[ \"$INPUT_PATH\" =~ \\.pu$ ]]; then\n OUTPUT_FILE=\"${INPUT_PATH%.pu}.$FORMAT\"\n else\n OUTPUT_FILE=\"${INPUT_PATH}.$FORMAT\"\n fi\n fi\n\n convert_file \"$INPUT_PATH\" \"$OUTPUT_FILE\"\n\nelse\n echo \"Error: Input path not found: $INPUT_PATH\" >&2\n exit 1\nfi\n","content_type":"application/x-sh; charset=utf-8","language":"bash","size":10825,"content_sha256":"dde405a26657707a5d0df9499f74744b4d1fe7ecfeef2e45849b539a206461e0"},{"filename":"scripts/validate_latex.py","content":"#!/usr/bin/env python3\n\"\"\"\nLaTeX Batch File Validator for PDF-to-LaTeX Conversion Pipeline.\n\nValidates batch .tex files BEFORE assembly to catch common errors early.\nDesigned to run on body-only LaTeX (no \\\\documentclass, no \\\\begin{document}).\n\nChecks:\n 1. Balanced \\\\begin{}/\\\\end{} environments\n 2. Undefined commands not present in preamble\n 3. \\\\begin{table}[H] or \\\\begin{figure}[H] inside tcolorbox environments\n 4. TikZ commands (\\\\node, \\\\draw, \\\\path, \\\\fill) outside \\\\begin{tikzpicture}\n 5. Missing node labels (TikZ \\\\node without {})\n 6. Stray & characters outside tabular/align/matrix environments\n\nUsage:\n python3 validate_latex.py tmp/batch_*.tex --preamble tmp/preamble.tex\n python3 validate_latex.py tmp/batch_001_007.tex\n python3 validate_latex.py tmp/batch_*.tex --json\n\"\"\"\n\nimport argparse\nimport re\nimport sys\nfrom pathlib import Path\n\n\n# tcolorbox theorem-like environments (cannot contain floats)\nTCOLORBOX_ENVS = {\n \"theorem\", \"lemma\", \"corollary\", \"proposition\",\n \"definition\", \"example\", \"remark\", \"notebox\", \"proof\",\n}\n\n# Environments where & is valid as a column/alignment separator\nAMPERSAND_ENVS = {\n \"tabular\", \"tabularx\", \"longtable\", \"array\",\n \"align\", \"align*\", \"aligned\", \"alignat\", \"alignat*\",\n \"gather\", \"gather*\", \"gathered\",\n \"split\", \"cases\", \"matrix\", \"pmatrix\", \"bmatrix\",\n \"vmatrix\", \"Vmatrix\", \"smallmatrix\",\n \"eqnarray\", \"eqnarray*\", \"flalign\", \"flalign*\",\n \"multiline\", \"multiline*\",\n}\n\n# TikZ commands that must be inside tikzpicture\nTIKZ_COMMANDS_RE = re.compile(\n r\"^[^%]*\\\\(node|draw|fill|path|coordinate|filldraw|shade|clip)\\s*[\\[({]\",\n)\n\n\ndef extract_preamble_commands(preamble_path: str) -> set:\n \"\"\"Extract \\\\newcommand and \\\\renewcommand names from a preamble file.\"\"\"\n commands = set()\n if not preamble_path:\n return commands\n\n path = Path(preamble_path)\n if not path.exists():\n print(f\"WARNING: Preamble file not found: {preamble_path}\", file=sys.stderr)\n return commands\n\n text = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n\n # Match \\newcommand{\\foo}, \\renewcommand{\\foo}, \\DeclareMathOperator{\\foo}\n for m in re.finditer(\n r\"\\\\(?:re)?newcommand\\*?\\{(\\\\[a-zA-Z]+)\\}\", text\n ):\n commands.add(m.group(1))\n\n for m in re.finditer(\n r\"\\\\DeclareMathOperator\\*?\\{(\\\\[a-zA-Z]+)\\}\", text\n ):\n commands.add(m.group(1))\n\n # newtcbtheorem defines environment names, not commands\n # newtcolorbox defines environment names\n # Extract \\usepackage names for reference\n for m in re.finditer(r\"\\\\newtcbtheorem[^{]*\\{([^}]+)\\}\", text):\n commands.add(f\"\\\\begin{{{m.group(1)}}}\")\n\n for m in re.finditer(r\"\\\\newtcolorbox\\{([^}]+)\\}\", text):\n commands.add(f\"\\\\begin{{{m.group(1)}}}\")\n\n return commands\n\n\ndef extract_preamble_packages(preamble_path: str) -> set:\n \"\"\"Extract loaded package names from a preamble file.\"\"\"\n packages = set()\n if not preamble_path:\n return packages\n\n path = Path(preamble_path)\n if not path.exists():\n return packages\n\n text = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n\n for m in re.finditer(r\"\\\\usepackage(?:\\[[^\\]]*\\])?\\{([^}]+)\\}\", text):\n # Handle comma-separated packages\n for pkg in m.group(1).split(\",\"):\n packages.add(pkg.strip())\n\n return packages\n\n\ndef extract_tikz_libraries(preamble_path: str) -> set:\n \"\"\"Extract loaded TikZ library names from a preamble file.\"\"\"\n libraries = set()\n if not preamble_path:\n return libraries\n\n path = Path(preamble_path)\n if not path.exists():\n return libraries\n\n text = path.read_text(encoding=\"utf-8\", errors=\"replace\")\n\n for m in re.finditer(r\"\\\\usetikzlibrary\\{([^}]+)\\}\", text):\n for lib in m.group(1).split(\",\"):\n lib = lib.strip().strip(\"\\n\")\n if lib:\n libraries.add(lib)\n\n return libraries\n\n\nclass ValidationError:\n \"\"\"A single validation error.\"\"\"\n\n def __init__(self, file: str, line: int, category: str, message: str):\n self.file = file\n self.line = line\n self.category = category\n self.message = message\n\n def __str__(self):\n return f\"{self.file}:{self.line}: [{self.category}] {self.message}\"\n\n def to_dict(self):\n return {\n \"file\": self.file,\n \"line\": self.line,\n \"category\": self.category,\n \"message\": self.message,\n }\n\n\ndef is_comment_line(line: str) -> bool:\n \"\"\"Check if a line is a LaTeX comment (ignoring leading whitespace).\"\"\"\n return line.lstrip().startswith(\"%\")\n\n\ndef validate_file(filepath: str, preamble_commands: set) -> list:\n \"\"\"Validate a single batch .tex file. Returns list of ValidationError.\"\"\"\n errors = []\n path = Path(filepath)\n if not path.exists():\n errors.append(ValidationError(filepath, 0, \"FILE\", f\"File not found: {filepath}\"))\n return errors\n\n lines = path.read_text(encoding=\"utf-8\", errors=\"replace\").splitlines()\n filename = path.name\n\n # --- Check 1: Balanced environments ---\n env_stack = [] # [(env_name, line_number), ...]\n\n for i, line in enumerate(lines, start=1):\n if is_comment_line(line):\n continue\n\n # Remove inline comments (but not escaped %)\n clean = re.sub(r\"(?\u003c!\\\\)%.*$\", \"\", line)\n\n # Find \\begin{env} and \\end{env}\n for m in re.finditer(r\"\\\\begin\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n # Skip document-level envs (shouldn't appear in batch files)\n if env_name in (\"document\",):\n errors.append(ValidationError(\n filename, i, \"STRUCTURE\",\n f\"\\\\begin{{{env_name}}} should not appear in batch files (body only)\"\n ))\n continue\n env_stack.append((env_name, i))\n\n for m in re.finditer(r\"\\\\end\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n if env_name in (\"document\",):\n errors.append(ValidationError(\n filename, i, \"STRUCTURE\",\n f\"\\\\end{{{env_name}}} should not appear in batch files (body only)\"\n ))\n continue\n\n if not env_stack:\n errors.append(ValidationError(\n filename, i, \"ENV_MISMATCH\",\n f\"\\\\end{{{env_name}}} without matching \\\\begin{{{env_name}}}\"\n ))\n else:\n top_env, top_line = env_stack[-1]\n if top_env == env_name:\n env_stack.pop()\n else:\n errors.append(ValidationError(\n filename, i, \"ENV_MISMATCH\",\n f\"\\\\end{{{env_name}}} does not match \\\\begin{{{top_env}}} at line {top_line}\"\n ))\n # Try to recover: pop if mismatched\n # Look deeper in stack for a match\n found = False\n for j in range(len(env_stack) - 1, -1, -1):\n if env_stack[j][0] == env_name:\n # Report unclosed environments between\n for k in range(len(env_stack) - 1, j, -1):\n errors.append(ValidationError(\n filename, env_stack[k][1], \"ENV_UNCLOSED\",\n f\"\\\\begin{{{env_stack[k][0]}}} opened but never closed \"\n f\"(interrupted by \\\\end{{{env_name}}} at line {i})\"\n ))\n env_stack = env_stack[:j]\n found = True\n break\n if not found:\n # No match found in stack; leave stack as is\n pass\n\n # Report remaining unclosed environments\n for env_name, line_num in env_stack:\n errors.append(ValidationError(\n filename, line_num, \"ENV_UNCLOSED\",\n f\"\\\\begin{{{env_name}}} opened but never closed (reached end of file)\"\n ))\n\n # --- Check 2: Float inside tcolorbox ---\n tcolorbox_depth = 0\n tcolorbox_stack = []\n\n for i, line in enumerate(lines, start=1):\n if is_comment_line(line):\n continue\n clean = re.sub(r\"(?\u003c!\\\\)%.*$\", \"\", line)\n\n for m in re.finditer(r\"\\\\begin\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n if env_name in TCOLORBOX_ENVS:\n tcolorbox_depth += 1\n tcolorbox_stack.append((env_name, i))\n\n # Check for floats while inside tcolorbox\n if tcolorbox_depth > 0:\n if re.search(r\"\\\\begin\\{table\\}\", clean):\n parent = tcolorbox_stack[-1][0] if tcolorbox_stack else \"unknown\"\n errors.append(ValidationError(\n filename, i, \"FLOAT_IN_TCOLORBOX\",\n f\"\\\\begin{{table}} inside \\\\begin{{{parent}}} \"\n f\"(opened at line {tcolorbox_stack[-1][1]}). \"\n f\"Use \\\\begin{{tabular}} directly instead.\"\n ))\n if re.search(r\"\\\\begin\\{figure\\}\", clean):\n parent = tcolorbox_stack[-1][0] if tcolorbox_stack else \"unknown\"\n errors.append(ValidationError(\n filename, i, \"FLOAT_IN_TCOLORBOX\",\n f\"\\\\begin{{figure}} inside \\\\begin{{{parent}}} \"\n f\"(opened at line {tcolorbox_stack[-1][1]}). \"\n f\"Remove the figure wrapper.\"\n ))\n\n for m in re.finditer(r\"\\\\end\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n if env_name in TCOLORBOX_ENVS and tcolorbox_depth > 0:\n tcolorbox_depth -= 1\n if tcolorbox_stack:\n tcolorbox_stack.pop()\n\n # --- Check 3: TikZ commands outside tikzpicture ---\n in_tikzpicture = 0\n\n for i, line in enumerate(lines, start=1):\n if is_comment_line(line):\n continue\n clean = re.sub(r\"(?\u003c!\\\\)%.*$\", \"\", line)\n\n if r\"\\begin{tikzpicture}\" in clean:\n in_tikzpicture += 1\n if r\"\\end{tikzpicture}\" in clean:\n in_tikzpicture = max(0, in_tikzpicture - 1)\n\n if in_tikzpicture == 0 and TIKZ_COMMANDS_RE.search(clean):\n errors.append(ValidationError(\n filename, i, \"TIKZ_OUTSIDE\",\n f\"TikZ command outside \\\\begin{{tikzpicture}}: {clean.strip()[:80]}\"\n ))\n\n # --- Check 4: Missing TikZ node labels ---\n for i, line in enumerate(lines, start=1):\n if is_comment_line(line):\n continue\n clean = re.sub(r\"(?\u003c!\\\\)%.*$\", \"\", line)\n\n # Find \\node that doesn't end with {something};\n # Pattern: \\node followed by options/name/at but no {} before ;\n node_matches = list(re.finditer(r\"\\\\node\\b\", clean))\n for m in node_matches:\n after = clean[m.end():]\n # Check if there's a {}, even empty, before the semicolon\n # Simple heuristic: there should be { ... } somewhere after \\node before ;\n semi_pos = after.find(\";\")\n if semi_pos == -1:\n # No semicolon on this line -- might continue on next line, skip\n continue\n segment = after[:semi_pos]\n if \"{\" not in segment:\n errors.append(ValidationError(\n filename, i, \"TIKZ_NODE_LABEL\",\n f\"\\\\node without label braces {{}}. Add {{}} even if empty: \"\n f\"{clean.strip()[:80]}\"\n ))\n\n # --- Check 5: Stray & outside valid environments ---\n ampersand_depth = 0\n\n for i, line in enumerate(lines, start=1):\n if is_comment_line(line):\n continue\n clean = re.sub(r\"(?\u003c!\\\\)%.*$\", \"\", line)\n\n # Track whether this line opens an ampersand-valid environment\n line_opens_amp_env = False\n for m in re.finditer(r\"\\\\begin\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n if env_name in AMPERSAND_ENVS:\n ampersand_depth += 1\n line_opens_amp_env = True\n\n # Only check for stray & if we're outside ampersand environments\n # AND this line didn't open one (handles single-line envs like\n # \\begin{aligned}...&...\\end{aligned} all on one line)\n if ampersand_depth == 0 and not line_opens_amp_env:\n stray = re.findall(r\"(?\u003c!\\\\)&\", clean)\n if stray:\n errors.append(ValidationError(\n filename, i, \"STRAY_AMPERSAND\",\n f\"Unescaped '&' outside tabular/align environment. \"\n f\"Use '\\\\&' in text mode: {clean.strip()[:80]}\"\n ))\n\n for m in re.finditer(r\"\\\\end\\{([^}]+)\\}\", clean):\n env_name = m.group(1)\n if env_name in AMPERSAND_ENVS:\n ampersand_depth = max(0, ampersand_depth - 1)\n\n return errors\n\n\ndef main():\n parser = argparse.ArgumentParser(\n description=\"Validate LaTeX batch files before assembly.\",\n epilog=\"Example: python3 validate_latex.py tmp/batch_*.tex --preamble tmp/preamble.tex\",\n )\n parser.add_argument(\n \"files\",\n nargs=\"+\",\n help=\"Batch .tex files to validate\",\n )\n parser.add_argument(\n \"--preamble\",\n default=None,\n help=\"Path to the shared preamble.tex (for command/package checking)\",\n )\n parser.add_argument(\n \"--json\",\n action=\"store_true\",\n help=\"Output errors as JSON instead of plain text\",\n )\n args = parser.parse_args()\n\n # Load preamble info\n preamble_commands = extract_preamble_commands(args.preamble)\n\n # Validate each file\n all_errors = []\n for filepath in sorted(args.files):\n file_errors = validate_file(filepath, preamble_commands)\n all_errors.extend(file_errors)\n\n # Output\n if args.json:\n import json\n result = {\n \"total_errors\": len(all_errors),\n \"files_checked\": len(args.files),\n \"errors\": [e.to_dict() for e in all_errors],\n }\n print(json.dumps(result, indent=2))\n else:\n if not all_errors:\n print(f\"OK: {len(args.files)} file(s) validated, 0 errors found.\")\n else:\n # Group by file\n by_file = {}\n for e in all_errors:\n by_file.setdefault(e.file, []).append(e)\n\n print(f\"ERRORS: {len(all_errors)} error(s) in {len(by_file)} file(s):\\n\")\n for fname in sorted(by_file.keys()):\n print(f\"--- {fname} ({len(by_file[fname])} errors) ---\")\n for e in by_file[fname]:\n print(f\" Line {e.line}: [{e.category}] {e.message}\")\n print()\n\n # Summary by category\n categories = {}\n for e in all_errors:\n categories[e.category] = categories.get(e.category, 0) + 1\n\n print(\"Summary by category:\")\n for cat, count in sorted(categories.items(), key=lambda x: -x[1]):\n print(f\" {cat}: {count}\")\n\n return 1 if all_errors else 0\n\n\nif __name__ == \"__main__\":\n sys.exit(main())\n","content_type":"text/x-python; charset=utf-8","language":"python","size":15283,"content_sha256":"445e0ef6bf76b12047fba11f6b715014f5463a3550abf1a9f5a676797e7ee4fb"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"LaTeX Document Skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Create Documents","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If the target is an IEEE journal / Transactions / IEEE two-column paper:","type":"text","marks":[{"type":"strong"}]},{"text":" Read ","type":"text"},{"text":"references/ieee-journal-twocolumn-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ieee-journal-twocolumn-guide.md","title":null}}]},{"text":" before choosing a template. Start from ","type":"text"},{"text":"examples/ieee-twocolumn-sample.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" for a working IEEEtran baseline and use ","type":"text"},{"text":"examples/ieee-twocolumn.png","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"examples/ieee-twocolumn-p1.png","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"examples/ieee-twocolumn-p2.png","type":"text","marks":[{"type":"code_inline"}]},{"text":" as visual references.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If poster:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the poster sub-workflow (see ","type":"text"},{"text":"Poster Sub-Workflow","type":"text","marks":[{"type":"link","attrs":{"href":"#poster-sub-workflow","title":null}}]},{"text":" below), then skip to step 5.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If cheat sheet / reference card:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the cheat sheet sub-workflow (see ","type":"text"},{"text":"Cheat Sheet / Reference Card Sub-Workflow","type":"text","marks":[{"type":"link","attrs":{"href":"#cheat-sheet--reference-card-sub-workflow","title":null}}]},{"text":" below), then skip to step 5.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Ask the user which enrichment elements they want","type":"text","marks":[{"type":"strong"}]},{"text":" (use AskUserQuestion tool with multiSelect). Offer relevant options based on document type:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AI-generated images","type":"text","marks":[{"type":"strong"}]},{"text":" -- custom illustrations, diagrams, photos (uses generate-image skill)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Charts/graphs","type":"text","marks":[{"type":"strong"}]},{"text":" -- bar, line, pie, scatter, heatmap (pgfplots or matplotlib)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Flowcharts/diagrams","type":"text","marks":[{"type":"strong"}]},{"text":" -- process flows, architecture, decision trees (TikZ or Mermaid)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Citations/bibliography","type":"text","marks":[{"type":"strong"}]},{"text":" -- academic references, footnotes, works cited (BibTeX/biblatex)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tables with data","type":"text","marks":[{"type":"strong"}]},{"text":" -- comparison matrices, financial data, statistics (booktabs)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Watermarks","type":"text","marks":[{"type":"strong"}]},{"text":" -- DRAFT, CONFIDENTIAL, or company logo background","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Skip this step for simple documents (cover letters, invoices) or when the user has already specified exactly what they want.","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Copy the appropriate template from ","type":"text"},{"text":"assets/templates/","type":"text","marks":[{"type":"code_inline"}]},{"text":" or write from scratch","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Customize content based on user requirements","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate external assets based on user's element choices:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"AI images: ","type":"text"},{"text":"python3 \u003cskill_path>/../generate-image/scripts/generate_image.py \"prompt\" --output ./outputs/figure.png","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"matplotlib charts: ","type":"text"},{"text":"python3 \u003cskill_path>/scripts/generate_chart.py \u003ctype> --data '\u003cjson>' --output chart.png","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Mermaid diagrams: ","type":"text"},{"text":"bash \u003cskill_path>/scripts/mermaid_to_image.sh diagram.mmd output.png","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"For documents 5+ pages:","type":"text","marks":[{"type":"strong"}]},{"text":" Review the ","type":"text"},{"text":"Long-Form Document Anti-Patterns","type":"text","marks":[{"type":"link","attrs":{"href":"#long-form-document-anti-patterns-must-read-for-reports-theses-books","title":null}}]},{"text":" section and run the Content Generation Checklist before compiling. Key rules: prefer prose over bullets, include global list compaction, escape ","type":"text"},{"text":"\u003c","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":">","type":"text","marks":[{"type":"code_inline"}]},{"text":" in text mode, vary section formats, limit ","type":"text"},{"text":"\\newpage","type":"text","marks":[{"type":"code_inline"}]},{"text":", size images at 0.75-0.85 textwidth.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Compile with ","type":"text"},{"text":"scripts/compile_latex.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" (auto-detects XeLaTeX for CJK/RTL, glossaries, bibliography)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Show PNG preview to user, deliver PDF","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Poster Sub-Workflow","type":"text"}]},{"type":"paragraph","content":[{"text":"When the user requests a poster: read ","type":"text"},{"text":"references/poster-design-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/poster-design-guide.md","title":null}}]},{"text":" for the complete workflow including conference size presets (NeurIPS/ICML/CVPR/ICLR dimensions), layout archetypes (Traditional/BetterPoster/Visual-Heavy), color schemes, and typography standards. Use ","type":"text"},{"text":"poster.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (portrait) or ","type":"text"},{"text":"poster-landscape.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (landscape). Ask the user for conference/orientation, layout style, and color scheme using AskUserQuestion, then proceed to step 5.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Cheat Sheet / Reference Card Sub-Workflow","type":"text"}]},{"type":"paragraph","content":[{"text":"When the user requests a cheat sheet, reference card, or formula sheet:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Read ","type":"text"},{"text":"references/cheatsheet-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/cheatsheet-guide.md","title":null}}]},{"text":" for the complete workflow including template selection, content budgets, typography rules, and the PDF-to-cheatsheet pipeline.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Select template: ","type":"text"},{"text":"cheatsheet.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (general, 3-col landscape), ","type":"text"},{"text":"cheatsheet-exam.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (exam formula, 2-col portrait), or ","type":"text"},{"text":"cheatsheet-code.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (programming, 4-col landscape).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Follow the guide's workflow steps, then return to main workflow step 5.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Mail Merge (Batch Personalized Documents)","type":"text"}]},{"type":"paragraph","content":[{"text":"Generate N personalized documents from a LaTeX template + CSV/JSON data source using ","type":"text"},{"text":"scripts/mail_merge.py","type":"text","marks":[{"type":"code_inline"}]},{"text":". Template syntax: ","type":"text"},{"text":"{{variable}}","type":"text","marks":[{"type":"code_inline"}]},{"text":" for simple substitution, Jinja2 (","type":"text"},{"text":"\u003c\u003c >>","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\u003c% %>","type":"text","marks":[{"type":"code_inline"}]},{"text":") for conditionals/loops. See ","type":"text"},{"text":"assets/templates/mail-merge-letter.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" for an example. Full guide: ","type":"text"},{"text":"references/interactive-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/interactive-features.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Version Diffing (latexdiff)","type":"text"}]},{"type":"paragraph","content":[{"text":"Generate highlighted change-tracked PDFs using ","type":"text"},{"text":"scripts/latex_diff.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":". Supports file-to-file diff, git revision diff, multi-file flatten, and custom markup styles. Full guide: ","type":"text"},{"text":"references/interactive-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/interactive-features.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Convert Document Formats","type":"text"}]},{"type":"paragraph","content":[{"text":"Convert between Markdown, DOCX, HTML, and LaTeX using ","type":"text"},{"text":"scripts/convert_document.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":". Full guide: ","type":"text"},{"text":"references/format-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/format-conversion.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Convert PDF to LaTeX","type":"text"}]},{"type":"paragraph","content":[{"text":"Convert existing PDFs (handwritten notes, printed reports, legal docs) to LaTeX. Full pipeline: ","type":"text"},{"text":"references/pdf-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-conversion.md","title":null}}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Quick steps","type":"text","marks":[{"type":"strong"}]},{"text":": Split PDF into page images (","type":"text"},{"text":"scripts/pdf_to_images.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":"), select a conversion profile, create shared preamble, apply scaling strategy, validate with ","type":"text"},{"text":"scripts/validate_latex.py","type":"text","marks":[{"type":"code_inline"}]},{"text":", concatenate, compile.","type":"text"}]},{"type":"paragraph","content":[{"text":"Scaling strategy","type":"text","marks":[{"type":"strong"}]},{"text":": 1-10 pages = single agent; 11-20 pages = split in half (2 agents); 21+ pages = batch-7 pipeline (ceil(N/7) agents with ","type":"text"},{"text":"run_in_background: true","type":"text","marks":[{"type":"code_inline"}]},{"text":").","type":"text"}]},{"type":"paragraph","content":[{"text":"Conversion profiles","type":"text","marks":[{"type":"strong"}]},{"text":" (in ","type":"text"},{"text":"references/profiles/","type":"text","marks":[{"type":"code_inline"}]},{"text":"): ","type":"text"},{"text":"math-notes.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (equations, theorems -- has beautiful mode), ","type":"text"},{"text":"business-document.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (reports, memos), ","type":"text"},{"text":"legal-document.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (contracts, statutes), ","type":"text"},{"text":"general-notes.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" (handwritten, mixed content).","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Fill PDF Forms","type":"text"}]},{"type":"paragraph","content":[{"text":"Fill existing PDF forms -- both fillable (with form fields) and non-fillable (image-based). Full guide: ","type":"text"},{"text":"references/pdf-operations.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-operations.md","title":null}}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"Step 1: Check form type:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 \u003cskill_path>/scripts/pdf_check_form.py form.pdf","type":"text"}]},{"type":"paragraph","content":[{"text":"If fillable","type":"text","marks":[{"type":"strong"}]},{"text":" (has form fields):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Extract field metadata\npython3 \u003cskill_path>/scripts/pdf_extract_fields.py form.pdf field_info.json\n# Create field_values.json with values for each field, then fill\npython3 \u003cskill_path>/scripts/pdf_fill_form.py form.pdf field_values.json output.pdf","type":"text"}]},{"type":"paragraph","content":[{"text":"If non-fillable","type":"text","marks":[{"type":"strong"}]},{"text":" (no form fields):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Convert to images for visual analysis\nbash \u003cskill_path>/scripts/pdf_to_images.sh form.pdf ./tmp/pages\n# Visually identify fields, create fields.json with bounding boxes\n# Validate bounding boxes (+ optional validation image)\npython3 \u003cskill_path>/scripts/pdf_validate_boxes.py fields.json --image page_1.png --output validation.png --page 1\n# Fill with text annotations\npython3 \u003cskill_path>/scripts/pdf_fill_annotations.py form.pdf fields.json output.pdf","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflow: Advanced PDF Operations","type":"text"}]},{"type":"paragraph","content":[{"text":"For text/table extraction (pdfplumber), OCR (pytesseract), programmatic PDF creation (reportlab), watermarking, page rotation/cropping, metadata extraction, JavaScript libraries (pdf-lib, pdfjs-dist), and batch processing, see ","type":"text"},{"text":"references/pdf-operations.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-operations.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Compile Script","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Basic compile (auto-detects engine)\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex\n\n# Compile + generate PNG previews\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --preview\n\n# Compile + PNG in specific directory\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --preview --preview-dir ./outputs\n\n# Force a specific engine\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --engine xelatex\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --engine lualatex\n\n# Use latexmk for automatic multi-pass (recommended for complex documents)\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --use-latexmk --preview\n\n# PDF/A output for thesis submissions and archival compliance\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --pdfa\n\n# Verbose output for debugging compilation issues\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --verbose\n\n# Quiet mode for batch/CI jobs (only errors shown)\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --quiet\n\n# Clean auxiliary files only (no compilation)\nbash \u003cskill_path>/scripts/compile_latex.sh document.tex --clean","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Compilation Flags","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flag","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Description","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--preview","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Generate PNG previews of each page after compilation","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--preview-dir DIR","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Directory for PNG output (default: same as .tex file)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--engine ENGINE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Force engine: ","type":"text"},{"text":"pdflatex","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"xelatex","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"lualatex","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--use-latexmk","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"latexmk","type":"text","marks":[{"type":"code_inline"}]},{"text":" as compilation backend (auto multi-pass, bibliography, index)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--verbose","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Show full compilation output (all engine logs)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--quiet","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Suppress all non-error output","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--clean","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Remove auxiliary files (.aux, .log, .bbl, .fdb_latexmk, etc.) and exit","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--pdfa","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Produce PDF/A-2b compliant output (auto-injects ","type":"text"},{"text":"pdfx","type":"text","marks":[{"type":"code_inline"}]},{"text":" package)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--auto-fix","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Auto-fix common compilation errors (float placement, encoding)","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Compilation Backends","type":"text"}]},{"type":"paragraph","content":[{"text":"Manual multi-pass (default):","type":"text","marks":[{"type":"strong"}]},{"text":" Runs the engine multiple times with bibliography/index/glossary passes as needed. This is the traditional approach and works without ","type":"text"},{"text":"latexmk","type":"text","marks":[{"type":"code_inline"}]},{"text":" installed.","type":"text"}]},{"type":"paragraph","content":[{"text":"latexmk (","type":"text","marks":[{"type":"strong"}]},{"text":"--use-latexmk","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":"):","type":"text","marks":[{"type":"strong"}]},{"text":" Uses ","type":"text"},{"text":"latexmk","type":"text","marks":[{"type":"code_inline"}]},{"text":" for automatic dependency-driven compilation. Recommended for complex documents with bibliographies, indexes, glossaries, or cross-references -- latexmk determines the correct number of passes automatically. Requires ","type":"text"},{"text":"latexmk","type":"text","marks":[{"type":"code_inline"}]},{"text":" (included with TeX Live).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Log Filtering (texfot)","type":"text"}]},{"type":"paragraph","content":[{"text":"When ","type":"text"},{"text":"texfot","type":"text","marks":[{"type":"code_inline"}]},{"text":" is installed (included with TeX Live), compilation output is automatically filtered to show only relevant warnings and errors, suppressing noisy package loading messages. This applies in the default verbosity mode. Use ","type":"text"},{"text":"--verbose","type":"text","marks":[{"type":"code_inline"}]},{"text":" to see unfiltered output, or ","type":"text"},{"text":"--quiet","type":"text","marks":[{"type":"code_inline"}]},{"text":" to suppress all non-error output.","type":"text"}]},{"type":"paragraph","content":[{"text":"Engine auto-detection","type":"text","marks":[{"type":"strong"}]},{"text":": If the .tex file uses ","type":"text"},{"text":"fontspec","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"xeCJK","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"polyglossia","type":"text","marks":[{"type":"code_inline"}]},{"text":", the script automatically uses ","type":"text"},{"text":"xelatex","type":"text","marks":[{"type":"code_inline"}]},{"text":". If it uses ","type":"text"},{"text":"luacode","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"luatextra","type":"text","marks":[{"type":"code_inline"}]},{"text":", it uses ","type":"text"},{"text":"lualatex","type":"text","marks":[{"type":"code_inline"}]},{"text":". Otherwise defaults to ","type":"text"},{"text":"pdflatex","type":"text","marks":[{"type":"code_inline"}]},{"text":". Override with ","type":"text"},{"text":"--engine","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"paragraph","content":[{"text":"The script auto-installs ","type":"text"},{"text":"texlive","type":"text","marks":[{"type":"code_inline"}]},{"text":" (including ","type":"text"},{"text":"texlive-science","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"texlive-xetex","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"texlive-luatex","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"biber","type":"text","marks":[{"type":"code_inline"}]},{"text":") and ","type":"text"},{"text":"poppler-utils","type":"text","marks":[{"type":"code_inline"}]},{"text":" if missing. It auto-detects ","type":"text"},{"text":"\\bibliography{}","type":"text","marks":[{"type":"code_inline"}]},{"text":" (runs bibtex), ","type":"text"},{"text":"\\addbibresource{}","type":"text","marks":[{"type":"code_inline"}]},{"text":" (runs biber), ","type":"text"},{"text":"\\makeindex","type":"text","marks":[{"type":"code_inline"}]},{"text":" (runs makeindex), ","type":"text"},{"text":"\\makeglossaries","type":"text","marks":[{"type":"code_inline"}]},{"text":" (runs makeglossaries), runs the correct number of passes, generates PNG previews with ","type":"text"},{"text":"pdftoppm","type":"text","marks":[{"type":"code_inline"}]},{"text":", and cleans auxiliary files.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Script & Tool Reference","type":"text"}]},{"type":"paragraph","content":[{"text":"For PDF utilities (encrypt, merge, optimize, extract pages, pdf-to-images), LaTeX quality tools (lint, word count, analysis, package check, citations), compilation auto-fix, bibliography fetching, and diagram scripts (Mermaid, Graphviz, PlantUML), see ","type":"text"},{"text":"references/script-tools.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/script-tools.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Templates","type":"text"}]},{"type":"paragraph","content":[{"text":"Copy from ","type":"text"},{"text":"assets/templates/","type":"text","marks":[{"type":"code_inline"}]},{"text":" and customize.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Resume Templates (5 ATS-Compatible Options)","type":"text"}]},{"type":"paragraph","content":[{"text":"Select based on experience level, industry, and ATS requirements. See ","type":"text"},{"text":"references/resume-ats-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/resume-ats-guide.md","title":null}}]},{"text":" for full ATS guidance.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Template","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Best For","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Key Feature","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ATS Score","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-classic-ats.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Finance, law, government, any ATS portal","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Zero graphics, plain text only, maximum parse safety","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"10/10","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-modern-professional.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tech, corporate, general professional","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Subtle color accents, clean design, good ATS + human appeal","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9/10","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-executive.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"VP, Director, C-suite (5-15+ years)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Two-page, executive summary, board roles, P&L focus","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9/10","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-technical.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Software, data, engineering roles","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skills-first hybrid, projects section, tech stack emphasis","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9/10","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-entry-level.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"New graduates, career starters","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Education-first, one page, coursework, activities","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"9/10","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"All 5 templates follow ATS rules: single-column, no graphics/images, no tables for layout, standard section headings, contact info in body (not header/footer).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"STEM Student Templates","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"homework.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Homework/assignment submission template (","type":"text"},{"text":"article","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, 11pt) with toggle-able solutions (","type":"text"},{"text":"\\showsolutionstrue","type":"text","marks":[{"type":"code_inline"}]},{"text":"/","type":"text"},{"text":"\\showsolutionsfalse","type":"text","marks":[{"type":"code_inline"}]},{"text":"), custom problem/solution environments, honor code section, ","type":"text"},{"text":"fancyhdr","type":"text","marks":[{"type":"code_inline"}]},{"text":" headers, ","type":"text"},{"text":"amsmath","type":"text","marks":[{"type":"code_inline"}]},{"text":"+","type":"text"},{"text":"amssymb","type":"text","marks":[{"type":"code_inline"}]},{"text":"+","type":"text"},{"text":"amsthm","type":"text","marks":[{"type":"code_inline"}]},{"text":" math, ","type":"text"},{"text":"listings","type":"text","marks":[{"type":"code_inline"}]},{"text":" code highlighting (Python, Java, C++, Matlab styles), ","type":"text"},{"text":"enumitem","type":"text","marks":[{"type":"code_inline"}]},{"text":" for (a), (b), (c) sub-parts, ","type":"text"},{"text":"hyperref","type":"text","marks":[{"type":"code_inline"}]},{"text":". Customization via ","type":"text"},{"text":"\\coursename","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\assignmentnumber","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\studentname","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\studentid","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\duedate","type":"text","marks":[{"type":"code_inline"}]},{"text":". Example problems: calculus, proof by induction, Python coding, matrix algebra, kinematics, Java OOP.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"lab-report.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- STEM lab report template (","type":"text"},{"text":"article","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, 11pt) with ","type":"text"},{"text":"siunitx","type":"text","marks":[{"type":"code_inline"}]},{"text":" for uncertainties and SI units, ","type":"text"},{"text":"pgfplots","type":"text","marks":[{"type":"code_inline"}]},{"text":" for data visualization, ","type":"text"},{"text":"booktabs","type":"text","marks":[{"type":"code_inline"}]},{"text":" for professional tables, ","type":"text"},{"text":"amsmath","type":"text","marks":[{"type":"code_inline"}]},{"text":" for equations, ","type":"text"},{"text":"fancyhdr","type":"text","marks":[{"type":"code_inline"}]},{"text":" headers, ","type":"text"},{"text":"caption","type":"text","marks":[{"type":"code_inline"}]},{"text":"+","type":"text"},{"text":"subcaption","type":"text","marks":[{"type":"code_inline"}]},{"text":" for figures. Structured sections: abstract, theory, procedure, data/results (with uncertainty tables), analysis (pgfplots graphs), discussion (error analysis), conclusion, references, appendix. Example: pendulum period measurement with error propagation.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Other Templates","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"lecture-notes.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Beautiful lecture notes (","type":"text"},{"text":"scrartcl","type":"text","marks":[{"type":"code_inline"}]},{"text":" KOMA-Script class) with Palatino font, ","type":"text"},{"text":"microtype","type":"text","marks":[{"type":"code_inline"}]},{"text":" typography, color-coded ","type":"text"},{"text":"tcolorbox","type":"text","marks":[{"type":"code_inline"}]},{"text":" theorem environments (blue theorems, green definitions, orange examples, purple remarks), TikZ graph theory diagram styles and macros (","type":"text"},{"text":"\\CompleteGraph","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\CycleGraph","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\PathGraph","type":"text","marks":[{"type":"code_inline"}]},{"text":"), styled section headings with ","type":"text"},{"text":"titlesec","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"fancyhdr","type":"text","marks":[{"type":"code_inline"}]},{"text":" headers, ","type":"text"},{"text":"hyperref","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"cleveref","type":"text","marks":[{"type":"code_inline"}]},{"text":" navigation. Ideal for converting handwritten math/science notes to beautiful PDFs. Includes graph theory custom commands (","type":"text"},{"text":"\\V","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\E","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\deg","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\chr","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Used by the math-notes conversion profile in beautiful mode.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"thesis.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Thesis/dissertation (","type":"text"},{"text":"book","type":"text","marks":[{"type":"code_inline"}]},{"text":" class) with title page, declaration, abstract, acknowledgments, TOC, list of figures/tables, chapters, appendices, bibliography. Front matter uses roman numerals, main matter uses arabic. Includes theorem environments.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"academic-cv.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Multi-page academic CV with publications (journal/conference/preprint sections), grants and funding, teaching, advising (current/graduated students), awards, professional service, invited talks. ORCID and Google Scholar links.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"book.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Full book (","type":"text"},{"text":"book","type":"text","marks":[{"type":"code_inline"}]},{"text":" class) with half-title, title page, copyright page, dedication, preface, acknowledgments, TOC, list of figures/tables, parts, chapters, appendix, bibliography, index. Custom chapter headings, epigraphs, fancyhdr, microtype.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"poster.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Conference poster (","type":"text"},{"text":"tikzposter","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, A0 portrait) with 2-column layout, QR code, 5 color schemes, tikzfigure charts, tables, coloredbox highlights. Includes commented ","type":"text"},{"text":"#BetterPoster","type":"text","marks":[{"type":"strong"}]},{"text":" layout variant (central billboard + sidebars). Portrait is standard for most conferences. See poster design guide for conference size presets.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"poster-landscape.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Landscape conference poster (","type":"text"},{"text":"tikzposter","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, A0 landscape) with 3-column (30/40/30) layout, QR code, tech purple color scheme. For CS/ML conferences (NeurIPS, ICML, CVPR, ICLR). Includes commented ","type":"text"},{"text":"\\geometry{}","type":"text","marks":[{"type":"code_inline"}]},{"text":" presets for CVPR/NeurIPS custom sizes.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cheatsheet.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- General reference card (","type":"text"},{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, landscape A4, 7pt base font) with 3-column ","type":"text"},{"text":"multicols","type":"text","marks":[{"type":"code_inline"}]},{"text":" layout, ","type":"text"},{"text":"tcolorbox","type":"text","marks":[{"type":"code_inline"}]},{"text":" colored section boxes, tight spacing. For command references, concept summaries, quick-reference guides. Supports front+back printing.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cheatsheet-exam.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Exam formula sheet (","type":"text"},{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, portrait A4, 6pt base font) with 2-column layout, maximum content density, black-and-white printer-safe. For university exam \"allowed cheat sheets\" with formulas, theorems, definitions. Optimized for single-sided printing.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cheatsheet-code.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Programming reference card (","type":"text"},{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]},{"text":" class, landscape A4, 7pt base font) with 4-column layout, ","type":"text"},{"text":"minted","type":"text","marks":[{"type":"code_inline"}]},{"text":" syntax highlighting, monospace font emphasis. For language syntax, API reference, CLI commands, keyboard shortcuts.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"letter.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Formal business letter with colored letterhead bar, TikZ logo placeholder, company info, recipient block, date, subject line, signature. Professional corporate appearance.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"exam.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Exam/quiz (","type":"text"},{"text":"exam","type":"text","marks":[{"type":"code_inline"}]},{"text":" class) with grading table, multiple question types (multiple choice, true/false, fill-in-blank, matching, short answer, essay), point values, solution toggle via ","type":"text"},{"text":"\\printanswers","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"report.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Business report with TOC, headers/footers, data tables, bar chart (pgfplots), process flowchart (TikZ), recommendations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"cover-letter.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Professional cover letter with sender/recipient blocks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"invoice.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Invoice with company header, line items table, subtotal/tax/total","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"academic-paper.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Research paper with abstract, sections, bibliography, figures. Includes example ","type":"text"},{"text":".bib","type":"text","marks":[{"type":"code_inline"}]},{"text":" file (","type":"text"},{"text":"references.bib","type":"text","marks":[{"type":"code_inline"}]},{"text":") for BibTeX citations.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"examples/ieee-twocolumn-sample.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- IEEE Transactions / journal example using ","type":"text"},{"text":"\\documentclass[journal,10pt]{IEEEtran}","type":"text","marks":[{"type":"code_inline"}]},{"text":" with abstract, keywords, single-column figure, single-column table, full-width table, and numeric bibliography. Use with ","type":"text"},{"text":"references/ieee-journal-twocolumn-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ieee-journal-twocolumn-guide.md","title":null}}]},{"text":". Preview PNGs: ","type":"text"},{"text":"examples/ieee-twocolumn.png","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"examples/ieee-twocolumn-p1.png","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"examples/ieee-twocolumn-p2.png","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"presentation.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Beamer presentation with title slide, content frames, columns","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"fillable-form.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Fillable PDF form (","type":"text"},{"text":"article","type":"text","marks":[{"type":"code_inline"}]},{"text":" class) with hyperref form fields: text inputs, checkboxes, radio buttons, dropdowns, push buttons. Two-column layout with ","type":"text"},{"text":"tabularx","type":"text","marks":[{"type":"code_inline"}]},{"text":". Custom ","type":"text"},{"text":"\\FormField","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\FormCheck","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\\FormDropdown","type":"text","marks":[{"type":"code_inline"}]},{"text":" helper commands. Requires Adobe Reader for full form support (browser PDF viewers have limited form capabilities).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"conditional-document.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Configurable document (","type":"text"},{"text":"article","type":"text","marks":[{"type":"code_inline"}]},{"text":" class) with etoolbox toggle system: show/hide TOC, appendix, watermark, draft mode, confidential marking, abstract. Template variables via ","type":"text"},{"text":"\\providecommand","type":"text","marks":[{"type":"code_inline"}]},{"text":" (title, author, org, version). Three visual profiles (corporate, academic, minimal). Supports command-line variable passing for CI/CD.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"mail-merge-letter.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Mail merge letter template with ","type":"text"},{"text":"{{variable}}","type":"text","marks":[{"type":"code_inline"}]},{"text":" placeholders for use with ","type":"text"},{"text":"scripts/mail_merge.py","type":"text","marks":[{"type":"code_inline"}]},{"text":". Company-branded letterhead, recipient address block, body text with data-driven personalization. Pair with CSV/JSON data source.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"resume.tex","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" -- Legacy resume template (has photo area and tables -- not ATS-optimized)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Usage:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"cp \u003cskill_path>/assets/templates/resume-classic-ats.tex ./outputs/my_resume.tex\n# Edit content, then compile\nbash \u003cskill_path>/scripts/compile_latex.sh ./outputs/my_resume.tex --preview --preview-dir ./outputs","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Document Type Selection","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"User Request","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Template","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Document Class","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume, CV (ATS-safe)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-classic-ats.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume (modern look)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-modern-professional.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume (senior/executive)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-executive.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume (technical/engineering)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-technical.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume (new graduate)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-entry-level.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Homework, assignment, problem set","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"homework.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lab report, experiment writeup","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"lab-report.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Lecture notes, math notes (beautiful)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"lecture-notes.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"scrartcl","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Thesis, dissertation","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"thesis.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"book","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Academic CV (publications, grants)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"academic-cv.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Report, analysis","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"report.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cover letter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cover-letter.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Invoice","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"invoice.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Academic paper","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"academic-paper.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"references.bib","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IEEE journal, IEEE Transactions, IEEE two-column paper","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"examples/ieee-twocolumn-sample.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"ieee-journal-twocolumn-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ieee-journal-twocolumn-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IEEEtran","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Book","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"book.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"book","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Scientific poster (portrait)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"poster.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tikzposter","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Scientific poster (landscape)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"poster-landscape.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tikzposter","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cheat sheet, reference card","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cheatsheet.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exam formula sheet, crib sheet","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cheatsheet-exam.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Programming reference card","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cheatsheet-code.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"extarticle","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Formal business letter","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"letter.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exam, quiz, test","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"exam.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"exam","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Slides, presentation","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"presentation.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"beamer","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fillable PDF form","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fillable-form.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Conditional/configurable document","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"conditional-document.tex","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mail merge, batch letters","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mail-merge-letter.tex","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"scripts/mail_merge.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"article","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Version diff (latexdiff)","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"scripts/latex_diff.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" + see ","type":"text"},{"text":"interactive-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/interactive-features.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"varies","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Convert PDF to LaTeX","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Select profile + see ","type":"text"},{"text":"pdf-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-conversion.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"varies","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Convert formats","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"scripts/convert_document.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" + see ","type":"text"},{"text":"format-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/format-conversion.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"varies","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mail merge from CSV/JSON","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"scripts/mail_merge.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" + see ","type":"text"},{"text":"interactive-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/interactive-features.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"varies","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Key LaTeX Patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Escaping Special Characters","type":"text"}]},{"type":"paragraph","content":[{"text":"Always escape: ","type":"text"},{"text":"%","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"\\%","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"$","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"\\$","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"&","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"\\&","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"#","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"\\#","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"_","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"\\_","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Angle brackets in text mode:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"\u003c","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":">","type":"text","marks":[{"type":"code_inline"}]},{"text":" are NOT valid in LaTeX text mode with T1 encoding. They render as inverted question marks (¡ or ¿). Always use math mode or text commands:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003c5%","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"$\u003c$5\\%","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"\\textless 5\\%","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":">50","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"$>$50","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"\\textgreater 50","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"\u003c$300","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"$\u003c$\\$300","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":">=","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"$\\geq$","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"\u003c=","type":"text","marks":[{"type":"code_inline"}]},{"text":" → ","type":"text"},{"text":"$\\leq$","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"paragraph","content":[{"text":"This is one of the most common silent errors in generated LaTeX — the document compiles without errors but the PDF shows garbage characters.","type":"text"}]},{"type":"paragraph","content":[{"text":"Date ranges use en-dash: ","type":"text"},{"text":"2019--2025","type":"text","marks":[{"type":"code_inline"}]},{"text":" (double hyphen).","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Standard Preamble","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"latex"},"content":[{"text":"\\documentclass[11pt,a4paper]{article}\n\\usepackage[utf8]{inputenc}\n\\usepackage[T1]{fontenc}\n\\usepackage{geometry}\n\\usepackage{hyperref}\n\\usepackage{xcolor}\n\\usepackage{graphicx}\n\\usepackage{tabularx}\n\\usepackage{colortbl}\n\\usepackage{enumitem}\n\\usepackage{titlesec}","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Code Patterns (load as needed)","type":"text"}]},{"type":"paragraph","content":[{"text":"For ready-to-use LaTeX code snippets (tables, charts, flowcharts, bibliography, watermarks, landscape pages, multi-language, images, Mermaid diagrams, matplotlib charts, CSV tables, AI images, fillable forms, conditional content, mail merge, version diff), read ","type":"text"},{"text":"references/code-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/code-patterns.md","title":null}}]},{"text":".","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Visual Elements in Reports","type":"text"}]},{"type":"paragraph","content":[{"text":"When creating reports, use the enrichment elements the user selected in step 4. For the quick reference table of visual element tools (charts, flowcharts, AI images, tables, timelines) and sizing guidelines, see ","type":"text"},{"text":"references/advanced-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/advanced-features.md","title":null}}]},{"text":". Use ","type":"text"},{"text":"\\begin{figure}[H]","type":"text","marks":[{"type":"code_inline"}]},{"text":" (from ","type":"text"},{"text":"float","type":"text","marks":[{"type":"code_inline"}]},{"text":" package) to prevent figures from floating. Size TikZ diagrams with ","type":"text"},{"text":"width=0.8\\textwidth","type":"text","marks":[{"type":"code_inline"}]},{"text":" or smaller.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Reference Guides (load as needed)","type":"text"}]},{"type":"paragraph","content":[{"text":"When uncertain about LaTeX patterns, compilation issues, or document quality, consult this table and load relevant files.","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Topic","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"File","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"When to Read","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Long-Form Best Practices","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"long-form-best-practices.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/long-form-best-practices.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"MUST READ for 5+ page documents","type":"text","marks":[{"type":"strong"}]},{"text":": 9 anti-patterns, report preamble, content generation checklist","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Code Patterns (LaTeX snippets)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"code-patterns.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/code-patterns.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Ready-to-use LaTeX code: tables, charts, flowcharts, bibliography, watermarks, landscape, multi-lang, images, forms, mail merge, diffs","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Script & Tool Reference","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"script-tools.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/script-tools.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PDF utilities (encrypt, merge, optimize, extract), LaTeX quality tools (lint, wordcount, analysis), compilation auto-fix, bibliography, diagrams","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bibliography/Citations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"bibliography-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/bibliography-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"BibTeX/biblatex, citation styles, .bib format","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Advanced Features & Visual Elements","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"advanced-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/advanced-features.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Watermarks, landscape, multi-lang, code, algorithms, tcolorbox, siunitx, advanced charts, AI images, visual elements reference table","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mermaid Diagrams","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"mermaid-diagrams.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/mermaid-diagrams.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flowcharts, sequence, class, ER, Gantt, pie, mindmap","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Python Charts (matplotlib)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"python-charts.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/python-charts.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bar, line, scatter, pie, heatmap, box, histogram, area, radar","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Format Conversion (Pandoc)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"format-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/format-conversion.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Markdown/DOCX/HTML to/from LaTeX","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tables and Images","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"tables-and-images.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/tables-and-images.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Colored rows, multi-row/column, booktabs, long tables, images, TikZ","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Charts and Graphs (pgfplots)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"charts-and-graphs.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/charts-and-graphs.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Line plots, bar charts, scatter plots, pie charts in pgfplots","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IEEE Journal Two-Column Typography","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ieee-journal-twocolumn-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/ieee-journal-twocolumn-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"IEEEtran journal layout, float rules, XeLaTeX vs. pdfLaTeX, bibliography, Markdown-to-IEEE workflow, sample PNGs in ","type":"text"},{"text":"examples/ieee-twocolumn*.png","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LaTeX Packages","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"packages.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/packages.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Common packages reference","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Poster Design Guide","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"poster-design-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/poster-design-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Conference size presets, typography, color schemes, layout archetypes, content guidelines","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resume ATS Guide","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"resume-ats-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/resume-ats-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ATS rules, LaTeX pitfalls, keywords","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PDF-to-LaTeX Pipeline","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pdf-conversion.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-conversion.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Full conversion pipeline, scaling strategy, worker agents, validation","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Interactive Features","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"interactive-features.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/interactive-features.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Fillable PDF forms, conditional content, mail merge from CSV/JSON, latexdiff version tracking","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Cheat Sheet Design","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"cheatsheet-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/cheatsheet-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Template selection, typography, density optimization, PDF-to-cheatsheet pipeline","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PDF-to-Cheatsheet Prompts","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pdf-extraction-prompts.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-extraction-prompts.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"LLM prompts for extraction stages: structure analysis, subject-specific extraction, compression, formatting","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Visual Packages (TikZ)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"visual-packages.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/visual-packages.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"24 installed TikZ/visualization packages with working examples","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Graphviz & PlantUML","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"graphviz-plantuml.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/graphviz-plantuml.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":".dot to PDF/PNG, .puml to PDF/PNG, LaTeX integration","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Debugging & Errors","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"debugging-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/debugging-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Reading LaTeX errors, 20 common errors, .log analysis, silent failures","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Accessibility & PDF/A","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"accessibility-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/accessibility-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PDF/A for thesis, PDF/UA for screen readers, tagged PDFs, alt text","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Beamer Presentations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"beamer-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/beamer-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Themes, overlays/animations, code slides, handouts, presenter notes","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Font Selection","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"font-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/font-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Font families, fontspec, mathematical fonts, fontawesome5, microtype, CJK","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Collaboration & CI/CD","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"collaboration-guide.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/collaboration-guide.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Git for LaTeX, GitHub Actions, Docker, multi-author workflows","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"PDF Operations","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pdf-operations.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/pdf-operations.md","title":null}}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Form filling (fillable + non-fillable), text/table extraction (pdfplumber), OCR (pytesseract), programmatic PDF creation (reportlab), watermarking, rotation/cropping, metadata, JavaScript (pdf-lib, pdfjs-dist), batch processing, performance tips","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Critical Notes and Common Mistakes","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Compile & Output","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run compile script from the directory containing the .tex file, or use absolute paths","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Place output .tex files in ","type":"text"},{"text":"./outputs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" for user visibility","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"After compilation, read the PNG preview files to show the user how the document looks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"PNG previews require ","type":"text"},{"text":"poppler-utils","type":"text","marks":[{"type":"code_inline"}]},{"text":" (auto-installed by script)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Package Dependency Errors (MUST READ)","type":"text"}]},{"type":"paragraph","content":[{"text":"These cause ","type":"text"},{"text":"Undefined control sequence","type":"text","marks":[{"type":"code_inline"}]},{"text":" -- always include the required package:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"If you use...","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"You MUST include","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error without it","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\rowcolor{}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\usepackage{colortbl}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Undefined control sequence ","type":"text"},{"text":"\\rowcolor","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\url{}","type":"text","marks":[{"type":"code_inline"}]},{"text":" in .bib with natbib","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\usepackage{url}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Undefined control sequence ","type":"text"},{"text":"\\url","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\checkmark","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\usepackage{amssymb}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Undefined control sequence ","type":"text"},{"text":"\\checkmark","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\begin{figure}[H]","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\usepackage{float}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Unknown float option ","type":"text"},{"text":"H","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\rowcolors{}{}{}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\\usepackage[table]{xcolor}","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"\\usepackage{colortbl}","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Undefined control sequence","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"hyperref Package","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"hyperref","type":"text","marks":[{"type":"code_inline"}]},{"text":" is fine for normal documents (most templates use it).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Only avoid it in ","type":"text"},{"text":"PDF-to-LaTeX converted documents","type":"text","marks":[{"type":"strong"}]},{"text":" with theorem environments, where it causes ","type":"text"},{"text":"\\set@color","type":"text","marks":[{"type":"code_inline"}]},{"text":" errors.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Compilation Environment","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"If texlive is not installed, the compile script auto-installs it. Do NOT run multiple compile commands in parallel before texlive is installed -- they will all try to install simultaneously, causing dpkg lock contention. Install once first or run compiles sequentially.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"The compile script uses ","type":"text"},{"text":"-interaction=nonstopmode","type":"text","marks":[{"type":"code_inline"}]},{"text":" (not ","type":"text"},{"text":"-halt-on-error","type":"text","marks":[{"type":"code_inline"}]},{"text":") to ensure PDFs are produced even with warnings. This is intentional -- many documents produce warnings on first pass that resolve on subsequent passes.","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"latexmk","type":"text","marks":[{"type":"strong"}]},{"text":" and ","type":"text"},{"text":"texfot","type":"text","marks":[{"type":"strong"}]},{"text":" are included with TeX Live. The setup script (","type":"text"},{"text":"setup.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":") verifies their availability. latexmk is used when ","type":"text"},{"text":"--use-latexmk","type":"text","marks":[{"type":"code_inline"}]},{"text":" is passed; texfot is used automatically when available (default verbosity mode).","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"A ","type":"text"},{"text":".chktexrc","type":"text","marks":[{"type":"code_inline"}]},{"text":" configuration file is included at the skill root to suppress common false positives when linting generated LaTeX documents. The ","type":"text"},{"text":"latex_lint.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":" script uses it automatically.","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Long-Form Document Anti-Patterns","type":"text"}]},{"type":"paragraph","content":[{"text":"For documents 5+ pages (reports, theses, books), read ","type":"text"},{"text":"references/long-form-best-practices.md","type":"text","marks":[{"type":"link","attrs":{"href":"references/long-form-best-practices.md","title":null}}]},{"text":" for 9 critical anti-patterns, the report preamble best practices, and the content generation checklist. ","type":"text"},{"text":"This is MUST-READ material before generating any long document.","type":"text","marks":[{"type":"strong"}]}]}]},"metadata":{"date":"2026-11-02","name":"latex-document-skill","author":"@skillopedia","source":{"stars":812,"repo_name":"latex-document-skill","origin_url":"https://github.com/ndpvt-web/latex-document-skill/blob/HEAD/SKILL.md","repo_owner":"ndpvt-web","body_sha256":"6dfa2a5e52c8c02a3bfdcf885d8f1a6bab2bb5c6d31b85c65ed4ad242fa991fb","cluster_key":"9457ba197cb31396822587e5f1816497dc33759b31b9c7563041aad277267be1","clean_bundle":{"format":"clean-skill-bundle-v1","source":"ndpvt-web/latex-document-skill/SKILL.md","text_bytes":858965,"source_commit":"e96fea30469964b2906f74fc6a1fda3a2700d3bd","skills_sh_rank":18145,"attachment_count":58,"text_attachments":58,"attachment_storage":"skill_attachments","binary_attachments":0},"cluster_size":1,"skill_md_path":"SKILL.md","import_metadata":{"date":"2026-11-02","author":"@skillopedia","version":"v1","category":"documents-office","category_label":"Documents"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"documents-office","import_tag":"skills-sh-top20k-2026-11","description":"Universal LaTeX document skill: create, compile, and convert any document to professional PDF with PNG previews. Supports resumes, reports, cover letters, invoices, academic papers, theses/dissertations, academic CVs, presentations (Beamer), scientific posters, formal letters, exams/quizzes, books, cheat sheets, reference cards, exam formula sheets, fillable PDF forms (hyperref form fields), conditional content (etoolbox toggles), mail merge from CSV/JSON (Jinja2 templates), version diffing (latexdiff), charts (pgfplots + matplotlib), tables (booktabs + CSV import), images (TikZ), Mermaid diagrams, AI-generated images, watermarks, landscape pages, bibliography/citations (BibTeX/biblatex), multi-language/CJK (auto XeLaTeX), algorithms/pseudocode, colored boxes (tcolorbox), SI units (siunitx), Pandoc format conversion (Markdown/DOCX/HTML ↔ LaTeX), and PDF-to-LaTeX conversion of handwritten or printed documents (math, business, legal, general). Compile script supports pdflatex, xelatex, lualatex with auto-detection, latexmk backend, texfot log filtering, PDF/A output, and verbosity control (--verbose/--quiet). Empirically optimized scaling: single agent 1-10 pages, split 11-20, batch-7 pipeline 21+. Use when user asks to: (1) create a resume/CV/cover letter, (2) write a LaTeX document, (3) create PDF with tables/charts/images, (4) compile a .tex file, (5) make a report/invoice/presentation, (6) anything involving LaTeX or pdflatex, (7) convert/OCR a PDF to LaTeX, (8) convert handwritten notes, (9) create charts/graphs/diagrams, (10) create slides, (11) write a thesis or dissertation, (12) create an academic CV, (13) create a poster, (14) create an exam/quiz, (15) create a book, (16) convert between document formats (Markdown, DOCX, HTML to/from LaTeX), (17) generate Mermaid diagrams for LaTeX, (18) create a formal business letter, (19) create a cheat sheet or reference card, (20) create an exam formula sheet or crib sheet, (21) condense lecture notes/PDFs into a cheat sheet, (22) create a fillable PDF form with text fields/checkboxes/dropdowns, (23) create a document with conditional content/toggles (show/hide sections), (24) generate batch/mail-merge documents from CSV/JSON data, (25) create a version diff PDF (latexdiff) highlighting changes between documents, (26) create a homework or assignment submission with problems and solutions, (27) create a lab report with data tables, graphs, and error analysis, (28) encrypt or password-protect a PDF, (29) merge multiple PDFs into one, (30) optimize/compress a PDF for web or email, (31) lint or check a LaTeX document for common issues, (32) count words in a LaTeX document, (33) analyze document statistics (figures, tables, citations), (34) fetch BibTeX from a DOI, (35) convert a Graphviz .dot file to PDF/PNG, (36) convert a PlantUML .puml file to PDF/PNG, (37) create a one-pager/fact sheet/executive summary, (38) create a datasheet or product specification sheet, (39) extract pages from a PDF (page ranges, odd/even), (40) check LaTeX package availability before compiling, (41) analyze citations and cross-reference with .bib files, (42) debug LaTeX compilation errors, (43) make a document accessible (PDF/A, tagged PDF), (44) create lecture notes or course handouts, (45) fill an existing PDF form (fillable fields or non-fillable with annotations), (46) extract text or tables from a PDF (pdfplumber, pypdf), (47) OCR a scanned PDF to text (pytesseract), (48) create a PDF programmatically with reportlab (Canvas, Platypus), (49) rotate or crop PDF pages (pypdf), (50) add a watermark to an existing PDF, (51) extract metadata from a PDF (title, author, subject).\n"}},"renderedAt":1793666100262}

LaTeX Document Skill Create any LaTeX document, compile to PDF, and generate PNG previews. Convert PDFs of any type to LaTeX. Workflow: Create Documents 1. Determine document type (resume, report, letter, invoice, article, thesis, academic CV, presentation, poster, exam, book, cheat sheet) 2. If the target is an IEEE journal / Transactions / IEEE two-column paper: Read references/ieee-journal-twocolumn-guide.md before choosing a template. Start from for a working IEEEtran baseline and use / / as visual references. 3. If poster: Run the poster sub-workflow (see Poster Sub-Workflow below), then…