Metadata-Version: 2.4
Name: reportsmith
Version: 0.6.0
Summary: A small, dependency-free library for building reports and exporting them to Markdown, HTML, LaTeX and PDF
Author: Michal Stojke
License-Expression: MIT
Project-URL: Homepage, https://github.com/mstojke/reportsmith
Project-URL: Documentation, https://reportsmith.readthedocs.io/en/latest/index.html
Project-URL: Changelog, https://github.com/mstojke/reportsmith/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/mstojke/reportsmith/issues
Keywords: report,markdown,html,latex,pdf,export,document
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Typing :: Typed
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Topic :: Text Processing :: Markup :: HTML
Classifier: Topic :: Text Processing :: Markup :: LaTeX
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: pdf
Requires-Dist: fpdf2>=2.8.4; extra == "pdf"
Provides-Extra: highlight
Requires-Dist: pygments; extra == "highlight"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: fpdf2>=2.8.4; extra == "dev"
Requires-Dist: pandas; extra == "dev"
Requires-Dist: matplotlib; extra == "dev"
Requires-Dist: pygments; extra == "dev"
Requires-Dist: pypdf; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Provides-Extra: docs
Requires-Dist: sphinx; extra == "docs"
Requires-Dist: myst-parser; extra == "docs"
Requires-Dist: sphinx-rtd-theme; extra == "docs"
Dynamic: license-file

# reportsmith

[![Tests](https://github.com/mstojke/reportsmith/actions/workflows/tests.yml/badge.svg)](https://github.com/mstojke/reportsmith/actions/workflows/tests.yml)
[![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/mstojke/reportsmith/badges/coverage.json)](https://github.com/mstojke/reportsmith/actions/workflows/tests.yml)

A small, dependency-free Python library for building reports programmatically and exporting them to **Markdown**, a **standalone styled HTML** document, **LaTeX**, or (optionally) **PDF**.

## Features

- Fluent builder API with chainable methods and nested sections (`with report.section(...)`)
- Table of contents in every format: linked lists in Markdown/HTML, `\tableofcontents` in LaTeX, clickable entries with page numbers in PDF
- Tables straight from data: lists of dicts, CSV files, or pandas DataFrames, with number formatting, missing-value placeholders, and automatic right-alignment of numeric columns
- Elements: headings, paragraphs, tables (with alignment and captions), bullet/numbered lists (nestable), definition lists, task lists, page breaks, code blocks, block quotes, images, horizontal rules, and format-specific raw passthrough
- Inline formatting helpers: `bold()`, `italic()`, `code()`, `link()`, `strike()`, `sub()`, `sup()`, and numbered `footnote()`s — rendered natively in every format
- Figures from image files, image bytes, or matplotlib plots, with numbered captions ("Figure 1", "Table 2") and `ref()` cross-references
- Callouts (note, tip, important, warning, caution): GitHub alerts in Markdown, coloured boxes in HTML, LaTeX and PDF
- Correct escaping everywhere: HTML entities, Markdown table pipes, code fences that widen when the source contains ` ``` `
- HTML export ships with a clean embedded stylesheet — automatic, light, or dark theme, plus a print stylesheet — that you can extend or replace with your own CSS
- Optional syntax highlighting of code blocks in HTML, LaTeX, and PDF (`pip install reportsmith[highlight]`, via Pygments)
- Document metadata (author, description, keywords, language) in HTML `<meta>` tags, PDF properties, LaTeX PDF fields, and optional Markdown front matter
- Reusable content: build sections on their own and `add()` them anywhere, or `extend()` one report with another — heading levels adapt, and `label_prefix` keeps cross-references working
- LaTeX export: a compilable document (pdfLaTeX/XeLaTeX/LuaLaTeX) with booktabs tables, framed code blocks, hyperlinks, and PDF bookmarks — or a body fragment to `\input` into your own document
- Optional PDF export (`pip install reportsmith[pdf]`, via fpdf2): matching styling, PDF bookmarks from sections, clickable links, auto-detected Unicode system fonts
- No required dependencies; Python 3.9+

## Installation

```bash
pip install -e .
```

Or just copy the `reportsmith/` package into your project — it has no dependencies.

## Quick start

```python
from reportsmith import Report, bold, link

report = Report("Q3 Sales Report", author="Jane Doe", subtitle="Quarterly summary")
report.toc()                         # table of contents

with report.section("Overview") as s:
    s.paragraph(["Revenue was ", bold("up 12%"), " quarter over quarter."])
    s.table(
        ["Region", "Revenue"],
        [["EMEA", "$1.2M"], ["APAC", "$0.9M"]],
        caption="Revenue by region",
        align=["left", "right"],
    )

with report.section("Next steps") as s:
    s.numbered_list([
        "Expand APAC sales team",
        ["Review ", link("pricing proposal", "https://example.com/pricing")],
    ])

print(report.to_markdown())          # Markdown string
print(report.to_html())              # standalone HTML page
report.save_markdown("report.md")
report.save_html("report.html")
report.save_latex("report.tex")    # compile with pdflatex/xelatex/lualatex
report.save("report.pdf")          # any format, chosen by the file extension
```

Run `python example.py` for a fuller demo that writes `example_report.md`, `example_report.html`, and `example_report.tex`.

## Documentation

- **[User Guide](https://github.com/mstojke/reportsmith/blob/main/docs/user-guide.md)** — a walkthrough of every feature with examples: sections, inline formatting, tables, lists, raw passthrough, HTML customization, and escaping behavior.
- **[API Reference](https://github.com/mstojke/reportsmith/blob/main/docs/api-reference.rst)** — signatures, parameters, and exceptions for every public class and function (reStructuredText, Sphinx-ready).

The docs are also a buildable Sphinx site:

```bash
pip install -e .[docs]
```

```bash
python -m sphinx -b html docs docs/_build/html
```

Then open `docs/_build/html/index.html`.

## API overview

### `Report(title, author="", date=None, subtitle="")`

`date` accepts a string, `datetime.date`, or `datetime.datetime`; it defaults to today.

Builder methods (all chainable, also available on sections):

| Method | Adds |
| --- | --- |
| `section(title)` | Nested section; heading level tracks nesting depth. Usable as a context manager. |
| `heading(text, level=None)` | Explicit heading (level defaults to the container's depth + 1) |
| `paragraph(content)` | Paragraph |
| `quote(content)` | Block quote |
| `code(source, language="")` | Fenced/`<pre>` code block |
| `bullet_list(items)` / `numbered_list(items)` | List; items may be text or a nested `ListElement` |
| `definition_list(items)` | `(term, definition)` pairs or a mapping |
| `task_list(items)` | Checklist of `(done, text)` pairs |
| `page_break()` | New page in PDF/LaTeX, and when printing HTML |
| `table(headers, rows, caption="", align=None, label="")` | Table; `align` entries are `"left"`, `"center"`, `"right"`; captioned tables are numbered |
| `table_from_records(records)` / `table_from_csv(source)` / `table_from_dataframe(df)` | Table built from data; options `columns`, `headers`, `formats`, `missing`, `align`, `caption` |
| `figure(source, caption="", alt="", label="", width=None)` | Figure from an image path, image bytes, or a plot; captioned figures are numbered |
| `image(src, alt="", title="")` | Image (unnumbered; may be a remote URL) |
| `horizontal_rule()` | Rule |
| `raw(content, format="both")` | Verbatim content for `"markdown"`, `"html"`, `"latex"`, or `"both"` (Markdown + HTML) |
| `toc(title="Contents", depth=3)` | Table of contents for the whole report; `depth` 1–5 sets how many heading levels are listed |
| `callout(kind="note", content=None, title="")` | Callout box (`"note"`, `"tip"`, `"important"`, `"warning"`, `"caution"`); returns the callout, usable as a context manager |
| `add(element)` | Any pre-built element; a standalone `Section` or `Callout` is re-levelled to fit |
| `extend(source, label_prefix="")` | Copies of another report's / section's content (or a list of elements), re-levelled; `label_prefix` renames labels and their `ref()`s |

Anywhere text is accepted you may pass a plain string or a list mixing strings with `bold()`, `italic()`, `code()`, and `link(text, href)` spans.

### Export

- `report.to_markdown(front_matter=False)` → GitHub-flavored Markdown string; `front_matter=True` adds a YAML metadata block
- `report.to_html(full_document=True, css=None, theme="auto", highlight=False)` → HTML string; `full_document=False` returns just the body fragment, `css=` replaces the default stylesheet, `theme=` is `"auto"`, `"light"`, or `"dark"`
- `report.to_latex(full_document=True, document_class="article", class_options="11pt,a4paper", preamble="", numbered=False)` → LaTeX source; `full_document=False` returns just the body, `preamble=` is appended to the built-in preamble
- `report.to_pdf(fonts=None, mono_fonts=None, highlight=False)` → PDF bytes (requires the `pdf` extra); pass TTF path quadruples to control typefaces
- `highlight=True` on the HTML, LaTeX, and PDF exports colours code blocks (requires the `highlight` extra)
- `report.save_markdown(path)` / `report.save_html(path, ...)` / `report.save_latex(path, ...)` / `report.save_pdf(path, ...)` → write to a file, return the `Path`
- `report.save(path, **options)` → the same, with the format chosen by the extension (`.md`, `.html`, `.tex`, `.pdf`)

## Running tests

Install the development dependencies (pytest, coverage, the optional fpdf2, pandas, matplotlib and Pygments integrations, pypdf for checking PDF output, ruff and mypy):

```bash
pip install -e .[dev]
```

The test suite lives in `tests/`. Tests for optional integrations are skipped when their package isn't installed.

```bash
python -m pytest
```

With a coverage report:

```bash
python -m pytest --cov=reportsmith --cov-report=term-missing
```

Lint and type-check:

```bash
ruff check .
```

```bash
mypy
```

CI runs all of these on Python 3.9–3.14, runs the suite once more with no optional dependencies installed, and compiles the LaTeX output of every example with pdfLaTeX, XeLaTeX, and LuaLaTeX.

## Changelog

See [CHANGELOG.md](https://github.com/mstojke/reportsmith/blob/main/CHANGELOG.md) — the format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## License

MIT
