rinohtype is a Python-based batch-mode document processor that renders structured documents to PDF based on document templates and style sheets. It's designed with a focus on user-friendly document layout and style customization.
License: AGPL-3.0-only (Affero GPL 3.0)
Author: Brecht Machiels brecht@opqode.com
Repository: https://github.com/brechtm/rinohtype
Documentation: http://www.mos6581.org/rinohtype/master/
Key Features:
- Powerful page layout system with columns, running headers/footers, floatable elements, and footnotes
- Support for figures and tables (including sideways rendering)
- Automatic table of contents and index generation
- Automatic numbering and cross-referencing
- CSS-inspired style sheet system
- reStructuredText and CommonMark frontends
- Sphinx builder (drop-in replacement for LaTeX builder)
- OpenType, TrueType, and Type1 font support
- Built-in support for 1000+ Google Fonts
- PDF, PNG, and JPEG image embedding
- Language: Python (3.10+)
- Package Manager: Poetry
- Task Runner: Nox (with nox-poetry)
- Test Framework: pytest (with pytest-xdist, pytest-cov, pytest-assume)
- Dependencies: docutils, myst-parser, packaging, various typeface packages
- Optional: ziamath, cairosvg (for math rendering)
src/
└── rinoh/ # Main source code
├── backend/ # PDF rendering backend
├── frontend/ # Input format parsers (reStructuredText, CommonMark, Sphinx)
├── font/ # Font handling
├── fonts/ # Font definitions (Adobe 14, Google Fonts)
├── language/ # Language-specific processing
├── stylesheets/ # Built-in style sheets
├── templates/ # Document templates (article, book)
└── [core modules] # document.py, layout.py, paragraph.py, table.py, etc.
doc/ # Documentation source
tests/ # Unit tests
tests_regression/ # Regression/integration tests
examples/ # Example documents
poetry installsource .venv/bin/activate# Render reStructuredText to PDF
rinoh input.rst
# Render with specific template
rinoh -t book input.rst
# Help
rinoh --helpsphinx-build -b rinoh . _build/rinoh# Run all default checks and tests
nox
# Run specific sessions
nox --session unit # Unit tests only
nox --session regression # Regression tests only
nox --session check # Poetry validation
nox --session check_docs # Documentation checks
nox --session build_docs # Build documentation (HTML + PDF)
# Run on specific Python version
nox -e unit-3.11
nox -e regression-3.11During development, run pytest directly. These Nox sessions are automatically run as part of CI.
- Unit tests: Quick tests focusing on individual components
- Regression tests: Render tiny documents and compare PDF output against known-good references
- test_rst.py and test_sphinx.py are the primary regression tests
- test_rinoh.py tests the CLI interface
- all of these tests are parameterized; each .rst file in the respective
tests_regression/subdirectories (rst/,sphinx/,rinoh/) is rendered and compared against a reference PDF (stored in the*_output/directories) - Requires: Graphviz, ImageMagick, and MuPDF's
mutoolor poppler'spdftoppm
- Tests run against multiple Python versions (3.10, 3.11, 3.12, 3.13, 3.14, 3.15) and PyPy
After making changes, first run the unit tests to verify functionality, then run the regression tests to ensure there are no unintended changes in PDF output. To speed up the loop, instruct pytest to abort on the first failure. When fixing a bug, run only the failing regression test while debugging. Add new regression tests for any new features or bug fixes.
If a regression test times out, the rendering process may be stuck in an infinite loop. In that case, kill the running test before continuing.
Regression tests verify that rendered PDF output matches reference PDFs. Tests are organized by input format:
tests_regression/
├── helpers/
│ ├── regression.py # Core rendering and verification logic
│ ├── diffpdf.py # PDF comparison utilities
│ ├── pdf_linkchecker.py # Link and outline verification
│ └── util.py # Utility functions
├── rst/ # reStructuredText test sources (.rst, .rts, .rtt)
├── rst_output/ # Generated output (created during test runs)
├── sphinx/ # Sphinx test roots (test-* directories)
├── sphinx_output/ # Sphinx-generated output
├── rinoh/ # Direct rinoh CLI test sources
├── rinoh_output/ # CLI test output
├── images/ # Test image assets
├── conftest.py # Pytest configuration and fixtures
├── test_rst.py # reStructuredText frontend tests
├── test_sphinx.py # Sphinx builder tests
└── test_rinoh.py # CLI interface tests
Test file conventions:
.rst- Input reStructuredText source files.rts- Style sheet overrides (optional, same basename as .rst).rtt- Template configuration files (optional, same basename as .rst).pdf- Reference PDFs inreference/or alongside source files.pxml- PseudoXML output (generated for debugging doctree structure).stylelog- Expected style warnings (optional)
How regression tests work:
- Parse input file (reStructuredText, CommonMark, or Sphinx) into a doctree
- Render doctree to PDF using rinohtype
- Compare generated PDF against reference PDF using
diff_pdf() - Verify PDF links, anchors, and outlines match expected values
- Check for expected warnings in
.stylelogfiles
Adding a regression test:
- Create a minimal
.rstfile intests_regression/rst/that demonstrates the feature/bug - Add optional
.rtsstyle sheet or.rtttemplate config if needed - Run the test to generate output in
tests_regression/rst_output/ - Inspect the generated PDF to ensure it's correct
- Copy the generated PDF to the
rst/directory as the new reference - Commit the
.rst, reference.pdf, and any.rts/.rttfiles
Sphinx tests: Use test-* directory structure in tests_regression/sphinx/ with conf.py and index.rst files.
For comprehensive details on development workflows, Nox sessions, testing across Python versions, continuous integration, and release processes, see DEVELOPING.rst.
- Follow PEP 8
- 80-column line wrapping
- 4 spaces indentation (no tabs)
- Descriptive variable/function/class names
- Organize imports: standard library → external packages → rinohtype modules
- Minimize external dependencies
- Configuration in
setup.cfgfor pytest and doc8
- Use pytest for all tests
- Unit tests focus on component functionality
- Regression tests compare PDF output against reference PDFs
- Tests parameterized across multiple Python versions and dependency versions
.python-versionfile specifies target versions for pyenvpyenv_setup.pyscript installs required Python versions- Tests run across supported Python versions via CI
- Code follows existing conventions
- Run
noxto verify tests pass locally - Add regression tests for new features/bug fixes when appropriate
- Add an entry to the changelog (
CHANGES.rst) for significant changes - Update documentation if needed
pyproject.toml- Poetry configuration, dependencies, entry pointsnoxfile.py- Nox session definitionsnoxutil.py- Nox utility functionssetup.cfg- pytest and doc8 configurationpoetry.lock- Locked dependency versions.coveragerc- Coverage configurationpyenv_setup.py- Python version management scriptrun_tests.py- Test runner script
src/rinoh/__init__.py- Package initialization with version/release infosrc/rinoh/__main__.py- CLI entry point (rinohcommand)src/rinoh/annotation.py- Document annotationssrc/rinoh/attribute.py- Attribute handlingsrc/rinoh/color.py- Color handlingsrc/rinoh/csl_formatter.py- CSL citation/bibliography formattingsrc/rinoh/dimension.py- Dimension and measurement typessrc/rinoh/document.py- Document modelsrc/rinoh/draw.py- Drawing primitivessrc/rinoh/element.py- Document elementssrc/rinoh/flowable.py- Flowable page elementssrc/rinoh/glossary.py- Glossary generationsrc/rinoh/highlight.py- Syntax/code highlightingsrc/rinoh/hyphenator.py- Text hyphenationsrc/rinoh/image.py- Image handling and embeddingsrc/rinoh/index.py- Index generationsrc/rinoh/inline.py- Inline text elementssrc/rinoh/layout.py- Page layout systemsrc/rinoh/math.py- Math formula renderingsrc/rinoh/number.py- Numbering systemssrc/rinoh/paper.py- Paper sizes and page dimensionssrc/rinoh/paragraph.py- Paragraph formatting and layoutsrc/rinoh/reference.py- Cross-referencessrc/rinoh/resource.py- Resource managementsrc/rinoh/strings.py- String utilities and localizationsrc/rinoh/structure.py- Document structuresrc/rinoh/style.py- Style systemsrc/rinoh/styleds.py- Styled document elementssrc/rinoh/styles.py- Style managementsrc/rinoh/table.py- Table renderingsrc/rinoh/template.py- Document templatessrc/rinoh/text.py- Text rendering and formattingsrc/rinoh/util.py- General utility functionssrc/rinoh/warnings.py- Warning system
src/rinoh/backend/- PDF rendering backendsrc/rinoh/data/- Data files and resourcessrc/rinoh/font/- Font handlingsrc/rinoh/fonts/- Font definitions (Adobe 14, Google Fonts)src/rinoh/frontend/- Input format parsers (reStructuredText, CommonMark, Sphinx)src/rinoh/language/- Language-specific processingsrc/rinoh/stylesheets/- Built-in style sheetssrc/rinoh/templates/- Document templates (article, book)
README.rst- Project overview and quick startDEVELOPING.rst- Detailed development workflows and CI processesCONTRIBUTING.rst- Contribution guidelinesCHANGES.rst- ChangelogLICENSE- AGPL-3.0 license text.github/- GitHub Actions workflows
- Symlinks in repository require special Windows Git configuration
- CI uses GitHub Actions across Linux, macOS, and Windows
- Use the
ghcommand-line tool to query the GitHub API for issues, CI status and test results - Regression test artifacts (PDFs, images) are available in CI for debugging test failures