Skip to content

Changelog

Unreleased

Changed

  • One footer for every format. HTML, EPUB, and ODT now honor footer.include_tag, include_commit, include_date, include_branch, and repo_url, and use the same layout as PDF and DOCX (parts joined by -, ending with Made with LeafPress · leafpress.dev). Previously they ignored those settings and showed the full version string. See Branding → Footer
  • EPUB now includes the logo on its cover page; it used to be dropped
  • Logos are embedded everywhere. A remote logo_path is downloaded once (public hosts only, 10 MB cap) and embedded in HTML, PDF, DOCX, ODT, and EPUB, so a remote logo now works in ODT too, and HTML output no longer loads it from the web when opened. A logo that can't be fetched is skipped with a warning instead of failing a DOCX build
  • The desktop app's log now shows the pipeline's own output (detected config, extensions, skipped pages, missing images, files written) instead of only "Converting…" and "Done!"
  • A crash inside any output renderer is now reported with a format-specific explanation. PDF and Markdown export previously surfaced it as an "Unexpected error"

Internal

  • LaTeX importer: macro conversion is a dispatch table instead of a 120-line if chain. Macro/environment tables moved to importer/tex_spec.py and node/tabular helpers to importer/tex_nodes.py. Output is unchanged, checked against every LaTeX input in the test suite
  • pipeline.py: one table of output formats replaces six copy-pasted blocks, single-project and monorepo mode share one page-render loop, and convert() is split into small steps. convert() takes an optional console
  • Renderer error messages come from one rule table in render_errors.py instead of five near-identical functions

0.8.3 — 2026-09-27

Security

  • docx.template_path from a cloned repo's leafpress.yml is now confined to the repository (a template's body is kept, so it could pull one of your local Word documents into the output). Relative template paths now resolve from leafpress.yml, as documented, instead of the current directory
  • HTML/EPUB footer injection: footer.custom_text and the git branch name were joined into the HTML and EPUB footers without escaping, so a cloned repo's leafpress.yml could inject <script> even with --sanitize-html. Each part is now escaped. (Found by ruff's bandit-style S704 rule.)
  • pom.xml / .csproj version detection parses with defusedxml, since these manifests can come from an untrusted cloned repository
  • Fixes from the pre-release code review:
    • A cloned repo's leafpress.yml could name any readable file as logo_path and have it embedded in HTML/PDF output. Local logos from an untrusted repo config must now be inside the repo, and only real images are ever allowlisted.
    • Only real image files are embedded from disk (HTML/EPUB) or fetched by the PDF renderer, so page content can't pull in e.g. a CI workspace's .env via <img> or rel="attachment".
    • Downloads forwarded Authorization/Cookie headers across redirects to other hosts (e.g. the Lucidchart token following a redirect to a storage bucket); they are now dropped when the origin changes.
    • A cloned repo's mermaid.server must be a public host; an operator-set LEAFPRESS_MERMAID_SERVER is still trusted.
    • The internal-host check now unwraps IPv4 addresses tunnelled in IPv6 (NAT64, 6to4, Teredo, IPv4-mapped). DNS rebinding is documented as a known limitation.
    • The PDF fetcher now uses the shared requests-based download helper instead of reimplementing redirects and size caps with urllib.
    • Monorepo projects[].url must be a git URL. A local path there skipped the containment check that path: gets. For cloned repos, the URL's host must also be public, and root: is confined.
    • A local project's .env settings are removed again after each conversion, so in the long-running desktop UI they no longer carry over into later runs. Previously they could switch off the untrusted-repo guards for a later git URL conversion.
    • The internal-host check also unwraps IPv4-compatible (::a.b.c.d) and SIIT (::ffff:0:a.b.c.d) addresses.
  • Upgraded all locked dependencies to clear known advisories (pip-audit now reports none), including GitPython 3.1.62 (option-smuggling / config-injection RCEs during clone), pymdown-extensions 12.1 (snippets path traversal, ReDoS), WeasyPrint 70.0 (url_fetcher bypass), lxml 6.1 (XXE via default entity resolution), Pillow 12.3 (image parser memory corruption), urllib3 2.8 / requests 2.34, soupsieve, idna, and pygments
  • Raised minimum dependency versions in pyproject.toml so fresh installs can't resolve to vulnerable releases: gitpython>=3.1.60, pymdown-extensions>=11.0.1, lxml>=6.1, requests>=2.33, pygments>=2.20, weasyprint>=70.0
  • Untrusted repository hardening. Converting a repository you don't control (a git URL, monorepo projects[].url, or a CI checkout) can no longer read local files or reach internal hosts. See Remote Sources
    • .env is not loaded from cloned repositories. Only LEAFPRESS_* keys are read from local .env files, so a .env can no longer set GIT_SSH_COMMAND or GIT_CONFIG_*
    • PDF rendering uses a restricted WeasyPrint URL fetcher: file:// is limited to the project, and private, loopback, and link-local hosts are blocked, including on redirects. This closes local file disclosure via <a rel="attachment" href="file:///..."> and SSRF via <img>
    • Pages must resolve inside docs_dir, and docs_dir must be inside the project. .. and absolute nav entries are dropped, and pages that symlink outside docs_dir are skipped
    • Images in PDF, DOCX, and ODT output must resolve inside the project, which blocks ../ traversal, raw file:// URIs, and symlinks. ODT previously embedded any file's bytes
    • pymdownx.snippets and pymdownx.b64 are confined to the project directory, and url_download is disabled
    • module:ClassName extension references must name a Markdown Extension subclass
    • Monorepo projects[].path in a cloned repository's leafpress.yml must stay inside that repository
    • PDF header and footer text is now correctly escaped in CSS, since a trailing backslash could previously break out of the string. watermark.color is now validated as a hex color
  • Supply chain & CI
    • The GitHub Action now passes inputs through environment variables instead of interpolating ${{ inputs.* }} into its shell script, which closes a script-injection route. It also installs leafpress from the action's own ref rather than whatever is newest on PyPI
    • All workflow actions are pinned by commit SHA, checkouts no longer persist credentials, and the release job disables caching. CI runs with contents: read and now runs pip-audit
    • Added Dependabot for GitHub Actions, uv, and Docker, with a 7-day cooldown
    • Docker: base images are pinned by digest, mounted repos are marked git safe.directory (version info now works under any --user), and the image includes an unprivileged leafpress user. The docs recommend --user "$(id -u):$(id -g)"
  • Downloads (diagrams, Lucidchart, mermaid.ink, remote DOCX logos, import from URL) go through one helper
    • http(s) only, streamed with size caps, and every redirect hop is re-validated
    • Remote DOCX logos refuse private or internal hosts, matching the PDF fetcher
  • fetch-diagrams: dest must stay inside the project directory, which closes arbitrary file writes such as dest: ../../.bashrc. Lucidchart document IDs are validated
  • Credentials in git URLs (https://user:TOKEN@…) are redacted from clone messages, errors, and monorepo chapter cover pages
  • TeX import: \includegraphics paths outside the .tex file's directory are skipped
  • Windows "open file" no longer runs through cmd.exe (shell=True). It now uses os.startfile

Improvements

  • Desktop UI convert window gains Git branch, Watermark, Mermaid diagrams (from config / render / keep as code), and Sanitize HTML (auto / on / off), matching the CLI flags
  • Experimental Zensical support. zensical.toml projects convert like MkDocs ones.
    • Reads site_name, docs_dir, nav, and markdown_extensions from [project].
    • Dotted extension tables are flattened back to extension names.
    • TOML 1.1 syntax is supported via tomli, a new dependency.
    • When both files exist, mkdocs.yml still wins; --mkdocs-config zensical.toml overrides.
    • See Zensical Projects.
  • External-link entries in nav (e.g. Book: https://…) are skipped instead of producing a "File not found" warning
  • LaTeX import overhaul, clearing every item in the LaTeX TODO list:
    • Multi-file projects (\input, \include, \subfile, \import) are inlined, confined to the document directory, with cycle detection
    • Theorem-like environments and \newtheorem (shared counters, starred forms) render as numbered blockquotes; proof ends with ∎
    • Accents and symbols convert to Unicode, and --- / -- / '' ` /~` become typographic characters
    • \multicolumn cell content is kept, and table cells are converted instead of left as raw LaTeX
    • Sub-figures render with (a)/(b) captions
    • siunitx quantities convert: \SI{3e8}{\metre\per\second} → 3 × 10⁸ m·s⁻¹
    • Equations get \tag{n}, with \label/\nonumber removed and align* wrapped in aligned
    • \ref/\eqref/\autoref/\cref/\nameref resolve to real numbers, including forward references
    • Beamer frames become headings with their content, and overlays are flattened. Frames were previously dropped entirely
  • LEAFPRESS_LOG_LEVEL env var (DEBUG/INFO/WARNING/ERROR/CRITICAL) sets console log verbosity without --verbose, which is useful in CI. Console log lines are now styled by level
  • HTML sanitizing. Uses nh3 to strip scripts, event handlers, javascript: / data: links, iframes, forms, and resource-loading CSS from page HTML, while keeping normal MkDocs/Material markup.
    • Automatic for git URL sources and monorepo url: projects, and a cloned repo's leafpress.yml can't disable it.
    • Opt in for any source with --sanitize-html, LEAFPRESS_SANITIZE_HTML, or sanitize_html: true.
  • Task-list checkboxes are now converted to ☑/☐ for plain pymdownx.tasklist output too (previously only with custom_checkbox: true), and conversion no longer depends on exact attribute formatting
  • Mermaid privacy controls. New mermaid: config (enabled, server), LEAFPRESS_MERMAID_ENABLED / LEAFPRESS_MERMAID_SERVER, and --mermaid/--no-mermaid. These let you point at a self-hosted mermaid.ink or keep diagrams as code so nothing is sent to a third party

Fixes

  • Monorepo Markdown export (-f markdown) silently dropped every page; it now includes each project's pages
  • LEAFPRESS_LOCAL_TIME was documented but never read; it now works like --local-time
  • The "missing extension" hint suggested the wrong package (pip install pymdownx); it now names the PyPI package (pymdown-extensions, mkdocs-material, …)
  • DOCX skips a logo that isn't a real image instead of failing; the PDF error message linked to the wrong issue tracker
  • leafpress init now includes the mermaid: and sanitize_html sections; markdown added to format lists in --help and the GitHub Action
  • Images from monorepo url: projects were lost because the clones were deleted before rendering; clones now live until output is written
  • Images elsewhere in a local source (e.g. a monorepo page using ../../shared/logo.png) were blanked by the new confinement; the folder being converted is now an allowed root
  • SVG images are embedded in ODT again, sized from their viewBox, and so are SVG logos on the ODT cover. Units in viewBox no longer crash, and stroke-width is no longer mistaken for width
  • Image detection hardened:
    • Images are detected by content: anything Pillow can open (TIFF, ICO, extensionless files, …) or an SVG, with up to 1 MB of prolog.
    • Decompression bombs are rejected instead of crashing the conversion.
    • Results are cached, so -f all checks each file once.
  • The desktop UI's import window no longer hangs if opening the result fails (e.g. no xdg-open)
  • A failed clone or missing source path left a duplicate console log handler attached (repeated warnings in the desktop UI)
  • Desktop UI import:
    • A failing file no longer aborts the rest of the batch.
    • Same-named files can no longer overwrite each other's output.
    • The result dialog lists every failure.
    • The UI and leafpress import now share one importer dispatch, leafpress.importer.dispatch.import_document.
  • ui.md corrected:
    • the convert window doesn't cover every CLI option;
    • the import output folder defaults to next to the source files;
    • the local-timezone option and keyboard shortcuts are now documented.
  • LaTeX import data loss:
    • Accented letters and \&, \% were silently dropped ("Schön" → "Schon", "100\%" → "100").
    • ~, --, --- and TeX quotes vanished.
    • \paragraph produced an empty heading.
    • \caption was never parsed, so figure captions leaked out as loose text instead of becoming alt text.
    • Beamer slides were discarded.
  • DOCX watermark font was written as &amp;quot;Calibri&amp;quot; (double-escaped), so Word didn't get the intended font
  • Batch import:
    • A failed file no longer aborts the batch, and errors now name the file that failed.
    • A per-file summary table is shown after multi-file imports.
    • Two inputs with the same name no longer silently overwrite each other's output.
    • URL imports without -o are written to the current directory. They were previously written into the download's temp directory and deleted.
  • convert --fetch-diagrams silently did nothing unless -c was passed. It now auto-detects leafpress.yml in the source directory, and it warns when there is nothing to fetch or the source is a git URL
  • fetch-diagrams:
    • Downloads run in parallel (up to 4 at a time).
    • All failures are reported together instead of stopping at the first.
    • Duplicate dest paths and a missing Lucidchart token are caught before any request is made.
  • HTML output is now actually self-contained. Local images and mermaid diagrams are embedded as data: URIs. Previously they were file:// links that only worked on the machine that built the file
  • EPUB images now display. They are packaged inside the EPUB instead of linked with file://, which e-readers can't open. Chapter titles are now escaped
  • ODT now embeds images. Images inside paragraphs (all normal Markdown images) were silently dropped. Images now also keep their aspect ratio instead of being forced to 4×2 inches
  • The mermaid temp directory (leafpress-mermaid-*) is now deleted after each conversion, including when a conversion fails. The console log handler is also detached on failure
  • Image file:// URIs containing percent-encoded characters (e.g. spaces) now embed correctly in DOCX
  • Relative pymdownx.snippets base_path entries now resolve from the project directory, as MkDocs does, instead of the current working directory

Documentation

  • Corrections from a full docs review:
    • CI and quick-start examples install leafpress[pdf] before generating PDFs.
    • Footer format, version-string format, copyright_text (EPUB metadata only), ODT SVG support, clone depth, --branch (no commit SHAs) and page_size (any CSS size) are now described accurately.
    • Which env vars exist and the full precedence order (CLI flags first) are spelled out.
    • The untrusted-repository page now separates protections for all sources from those for cloned repos only.
  • README:
    • adds Zensical, LaTeX and URL import, the untrusted-repo protections, the GitHub Action (pinned) and Docker;
    • corrects the mermaid description (images via mermaid.ink or a self-hosted server, not inline SVG) and the desktop UI's option coverage;
    • updates development commands and links CONTRIBUTING and SECURITY.
  • Architecture page: new Security Layer section; covers Zensical parsing, the CLI package, shared import dispatch, image embedding, and the LaTeX pipeline; the module map and dependency tables are complete, now including pylatexenc, nh3, tomli and Pillow.
  • Other pages:
    • landing page cards for untrusted-repo safety, mermaid and Zensical;
    • CLI reference covers batch import behavior, parallel diagram fetching and zensical.toml auto-detection;
    • the CI env-var table is complete;
    • workflow examples use current action versions.

Tooling

  • Pre-commit hook (make setup-hooks): gitleaks on staged changes, ruff check (now including the bandit-style S security rules), ruff format --check, and ty at the CI-pinned version
  • CI: new secrets job runs a checksum-verified gitleaks over the full git history
  • make lint/format cover the whole repo, make typecheck uses the pinned ty, and a new make secrets target runs a full-history gitleaks scan
  • Test coverage raised to ~95% of lines and ~88% of branches (1,060+ tests):
    • New end-to-end integration suite: a malicious repository converted to every format leaks nothing; images and mermaid are embedded in every format; CLI flags reach the output; a multi-file LaTeX import runs through the CLI.
    • Docker tests cover running as the host user with git version detection.
    • Security helpers' edge cases (redirect loops, size caps, unresolvable and multicast hosts, include depth) are now at 97–100%.
    • Desktop UI tests (87% of ui/app.py) now run in CI in a new ui job.
  • pillow is now a declared dependency (ODT image sizing imports it directly; it was previously only installed transitively via python-pptx)
  • Cross-format watermark tests check that the text appears (and is escaped) in PDF, DOCX, HTML, ODT, and EPUB
  • src/leafpress/cli.py (~700 lines) is split into a leafpress.cli package with one module per subcommand. The leafpress.cli:cli entry point and --help output are unchanged, and new tests cover the CLI error paths
  • Added SECURITY.md (private vulnerability reporting) and expanded CONTRIBUTING.md with the test layout, fixtures, security-test expectations, and how to add renderers and importers
  • CIButler integration tests read their location from LEAFPRESS_CIBUTLER_DOCS instead of a hardcoded path, and the skip reason says how to enable them
  • .gitignore and ruff excludes for pytest-of-* / leafpress-mermaid-* are anchored to the repo root
  • uv_build range widened to <0.13 (uv 0.12.x); ruff now targets Python 3.13 (matching requires-python); removed the unused mypy config/dependency in favor of ty, which now reports zero diagnostics

Upgrade notes

  • pymdown-extensions 12 rewrote BetterEm/Tilde/Caret/Mark emphasis parsing to be CommonMark compliant — mid-word ~~, ^^, and == are now allowed by default, and edge cases of nested emphasis may render slightly differently
  • docs_dir outside the directory containing mkdocs.yml is now an error, and image references outside the project are dropped with a warning (see Security above)

0.8.2 — 2026-04-25

Tests

  • New unit tests for importer/image_handler.py — covers save_image (file writes, counter+hash naming, asset directory creation, full MIME→extension table, default fallback), handle_image mammoth callback, content_type_for_extension (including .jpeg alias), and saved_images copy semantics
  • New unit tests for importer/markdown_converter.py — covers ATX heading / dash bullet / asterisk emphasis options, convert_pre fenced output (with and without language-* class), and convert_table pipe-table generation (header separator, ragged-row padding, min column width, empty table, embedded newlines)
  • 779 total tests (up from 738), 91% overall coverage; image_handler and markdown_converter now at 100% / 98%

Fixes

  • Loosened hard-coded page-count assertions in test_cibutler_integration.py (== 14 → >= 14) so the suite tolerates new pages being added to the upstream cibutler docs site

0.8.1 — 2026-04-09

Improvements

  • PPTX converter — warnings are now aggregated by type instead of one per shape, producing cleaner output on decks with many unsupported objects
  • PPTX alt text — image shapes now use the shape name as alt text in generated Markdown
  • PPTX hyperlinks — bold/italic formatting on linked text is now preserved through the conversion

Fixes

  • Type annotations corrected in source.py and several test helpers
  • Import sorting and unused-variable lint errors fixed across the test suite
  • ty.toml added to suppress false positives from third-party stubs
  • Release workflow fixed; integration test path corrected
  • Dict-unpacking test helpers replaced with explicit constructions

0.8.0 — 2026-04-04

Features

  • LaTeX import — new leafpress import paper.tex converter using pylatexenc AST walker, supporting sections, formatting, math passthrough, lists, tables, figures, code blocks, links, footnotes, and image extraction. 14 known limitations documented.
  • URL import — leafpress import https://example.com/report.docx downloads and converts in one step, with Content-Type fallback for extensionless URLs and automatic temp cleanup. Works for all four formats.
  • PPTX warnings — charts, embedded OLE objects, media, and linked objects now produce warnings identifying the slide and shape name instead of being silently skipped
  • XLSX warnings — merged cells (with region count), embedded images, embedded charts, and blank workbooks now produce warnings instead of silent data loss
  • Improved warning display — import CLI now shows up to 10 warnings with ⚠ prefix and a "… and N more" truncation indicator

Refactor

  • Shared importer base — extracted ImportResult, resolve_output_path, postprocess_markdown, and rows_to_pipe_table from the DOCX converter into importer/base.py, eliminating cross-converter import dependencies
  • Shared test helper — consolidated 4 duplicate _make_png() implementations into tests/helpers.py
  • Fixed tabular* regex — environments with multiple brace arguments now parse correctly

Docs

  • Import — full LaTeX section with features table, 14-item limitations table, URL import section, and updated batch import examples
  • CLI — updated argument description, added URL and LaTeX examples
  • Architecture — added LaTeX import section, updated pipeline diagram and module map
  • About, Home, UI — updated to reflect LaTeX and URL support

Tests

  • 713 total tests (up from 644), 93% importer coverage
  • Comprehensive programmatic fixtures for DOCX, PPTX, XLSX, and LaTeX
  • Academic paper fixture (academic_paper.tex) with 29 assertions
  • 8 URL import tests with mocked HTTP
  • Edge case tests for LaTeX macros, environments, images, and error paths

0.7.0 — 2026-03-31

Features

  • Asset validation warnings — missing image references are now detected during rendering and reported as warnings with the page name and path, instead of silently producing blank spots in output
  • Consistent error messages — DOCX, HTML, ODT, and EPUB rendering failures now show format-specific actionable guidance following the "what happened → why → how to fix" pattern (matching the existing PDF error messages)
  • Louder extension load failures — when a Markdown extension fails to load, the error message is now displayed along with an install suggestion (e.g. pip install pymdownx) for missing packages
  • Mermaid cache integrity — cached mermaid diagram PNGs are now validated by checking PNG magic bytes; corrupted files (truncated writes, disk errors) are automatically re-rendered instead of silently producing broken images
  • Mermaid sanitization refactor — the mermaid source sanitization pipeline is now split into three named, independently testable helpers: _unescape_html_entities, _replace_literal_backslash_n, and _replace_newlines_in_quoted_labels

Docs

  • Configuration — added "How navigation levels work" and "Troubleshooting monorepo builds" sections explaining heading level bumping and common error scenarios
  • Architecture — added "Monorepo Pipeline" section describing per-project processing, nav level bumping, and chapter cover generation
  • Extensions — added "Troubleshooting extension failures" section with common fixes
  • CLI — updated verbose output description to reflect new warning details
  • Diagrams — added "Mermaid diagram caching" section explaining content-addressed caching and integrity validation

Tests

  • 27 new tests: asset validation tracking (4), extension error message capture (2), error formatter tests for DOCX (2), HTML (3), ODT (2), EPUB (3), PNG validation (4), cache integrity (2), sanitization helpers (6)
  • 571 total tests

0.6.2 — 2026-03-28

Refactor

  • BaseRenderer protocol and shared helpers — extracted replace_checkboxes(), make_anchor_id(), and resolve_logo_uri() from PDF, HTML, and EPUB renderers into a new base_renderer.py module, eliminating ~90 lines of duplicated code across renderers
  • Normalized checkbox CSS classes — PDF renderer now uses .task-checkbox.checked class naming consistent with HTML and EPUB renderers

Docs

  • Architecture — added BaseRenderer protocol and shared helpers section, updated module map and "Adding a New Output Format" guide

0.5.1 — 2026-03-13

Fixes

  • DOCX watermark — Google Workspace compatibility — v:shapetype definition is now emitted before the v:shape that references it; without it the OOXML was technically invalid and Google Docs rejected the file entirely. Affects users with watermark.text set in leafpress.yml
  • macOS PDF — WeasyPrint system library detection — leafpress doctor now checks each required library (cairo, pango, gdk-pixbuf, libffi) individually and reports the resolved path or a targeted install hint; Apple Silicon users also get a DYLD_LIBRARY_PATH hint when libraries are installed but not found
  • macOS PDF — clearer error messages — ImportError (WeasyPrint not installed) and OSError (system libs missing) are now handled separately with distinct, actionable messages; the OSError path explicitly warns that brew install weasyprint is the wrong command

Docs

  • Installation — replaced brew install pango with full macOS instructions (Apple Silicon / Intel tabs, DYLD_LIBRARY_PATH tip, warning against brew install weasyprint)
  • PDF — added macOS callout with correct brew packages and leafpress doctor pointer
  • DOCX — added Google Workspace compatibility note

0.5.0 — 2026-03-11

Features

  • Footer render date — new include_render_date option appends the document generation date to the footer across all output formats; configurable via leafpress.yml, --footer-date / --no-footer-date CLI flags, or LEAFPRESS_FOOTER_INCLUDE_RENDER_DATE env var
  • SVG logo validation — DOCX and ODT renderers now detect SVG logos and skip them with a clear warning instead of crashing; PDF and HTML continue to support SVG natively
  • Actionable PDF error messages — rendering failures (e.g. UnrecognizedImageError) now show specific troubleshooting steps: install librsvg, convert SVG to PNG, or run leafpress doctor
  • Pipeline warnings surfaced to console — logger.warning() calls from renderers (SVG logo skip, extension load failures, image embed errors) are now automatically displayed in CLI output as yellow ⚠ messages; --verbose additionally surfaces DEBUG-level detail
  • Mermaid diagram progress — each page with mermaid diagrams now reports a rendered count (e.g. "Rendered 3 mermaid diagram(s) in overview.md") with failure details if any diagrams fail

Fixes

  • Mermaid \n rendering — literal \n text in mermaid diagram labels is now automatically converted to <br/> line breaks; actual newlines inside quoted labels are also handled
  • DOCX image embed warnings — warnings.warn() calls in the DOCX HTML converter are now routed through the standard logger so they appear in CLI output

Tests

  • 26 new tests: _format_pdf_error error message branches (3), _is_svg detection for DOCX (7) and ODT (5), SVG logo skip integration for DOCX (1) and ODT (1), PDF RenderError wrapping (1), _ConsoleWarningHandler (3), pipeline verbose param (1), mermaid diagram count summary (4)
  • 526 total tests

Docs

  • Configuration updated with include_render_date field, env var, and SVG logo compatibility note
  • Branding updated with SVG logo warning, render date footer option, and CLI override
  • CLI reference updated with --footer-date / --no-footer-date flag, and --verbose description
  • PDF page updated with new Troubleshooting section for image errors
  • DOCX and ODT pages updated with SVG limitations
  • Extensions updated with mermaid line break tip

0.4.0 — 2026-03-11

Features

  • Monorepo support — list multiple MkDocs projects in leafpress.yml under projects; each project renders as a chapter of a single combined document with one cover page and unified TOC; per-project metadata overrides (author, document_owner, review_cycle, subtitle); supports git URL projects with optional branch
  • PowerPoint import — leafpress import deck.pptx converts presentations to Markdown; slide titles become H2 headings, speaker notes render as blockquotes, tables and images are extracted; --notes/--no-notes flag to toggle speaker notes
  • Multi-file import — leafpress import *.docx *.pptx processes multiple files in one command with mixed format support and partial failure handling
  • review_cycle config field — new optional field displayed on cover page of all output formats; configurable via LEAFPRESS_REVIEW_CYCLE env var

Tests

  • 19 new PPTX import tests (slides, formatting, tables, images, notes, CLI integration)
  • 17 new monorepo tests (page collection, chapter headings, nav bumping, per-project metadata, config normalization)
  • 5 new multi-file import CLI tests (multiple DOCX, mixed formats, output validation, partial failure, backwards compat)
  • 3 new dotenv loading tests
  • 2 new bump_nav_levels tests
  • 3 new review_cycle config tests
  • 444 total tests

Docs

  • New Document Import page with supported/unsupported feature tables for Word and PowerPoint
  • New Architecture page with pipeline flowcharts, module map, and key dependencies
  • Configuration updated with monorepo support section and review_cycle field
  • CLI reference updated with multi-file import, PPTX support, monorepo example, and --notes flag
  • About updated with source control migration messaging

0.3.0 — 2026-03-10

Features

  • Project auto-detection — leafpress convert and leafpress info now auto-detect the MkDocs project directory when no source argument is given; searches git root, docs/ subdirectory, CWD, and CWD/docs/ in order
  • document_owner config field — new optional field in leafpress.yml displayed on the cover page of all output formats (PDF, HTML, EPUB, DOCX, ODT); also configurable via LEAFPRESS_DOCUMENT_OWNER env var
  • Mermaid diagram rendering — fenced mermaid code blocks are rendered as inline SVG diagrams in all output formats
  • Annotation support — Material for MkDocs-style annotations ((1), (2), etc.) are rendered as numbered footnotes
  • --debug flag on leafpress doctor for detailed diagnostic output

Tests

  • 18 new project auto-detection tests (git root, docs subdir, CWD fallback, yaml extension, error cases)
  • 3 new document_owner config tests (YAML loading, env override, env-over-YAML precedence)
  • 390 total tests

Docs

  • New Markdown Extensions page documenting mermaid, annotations, admonitions, tabs, and task lists
  • CLI reference updated with auto-detection behavior, search order, and examples
  • Configuration updated with document_owner field and LEAFPRESS_DOCUMENT_OWNER env var

0.2.2 — 2026-03-10

Features

  • leafpress doctor command — diagnose your environment with a single command; checks Python version, WeasyPrint (package + system libs), PyQt6, and pyobjc; shows ✓/✗ status, versions, and suggested fixes for any missing dependencies
  • --verbose flag on doctor to also check all 18 core dependencies

Fixes

  • Properly fixed Rich markup swallowing [pdf]/[ui] in error messages — all console.print() error sites now use rich.markup.escape() instead of embedding Rich-specific escapes in exception messages
  • Error messages for missing WeasyPrint now suggest running leafpress doctor to diagnose
  • GitHub Releases now auto-created when tags are pushed — release.yml updated with gh release create step and contents: write permission

Tests

  • 25 new doctor command tests (dataclasses, check functions, orchestrator, CLI integration, Rich escape regression)

Docs

  • New doctor section in CLI reference with checks table, exit codes, and examples

0.2.1 — 2026-03-10

Fixes

  • Fixed [pdf] being swallowed by Rich markup in the WeasyPrint missing error message — users now correctly see pip install 'leafpress[pdf]'

0.2.0 — 2026-03-10

Features

  • EPUB output format — new leafpress convert -f epub produces reflowable e-books via ebooklib, with cover page, table of contents, branding CSS, and watermark support
  • DOCX → Markdown import — new leafpress import command converts Word documents to Markdown using mammoth + markdownify, with image extraction, custom code-style mapping, and pipe tables
  • Optional PDF extras — WeasyPrint moved from base dependency to leafpress[pdf]; base install (pip install leafpress) no longer requires system libraries
  • leafpress[pdf] — adds PDF output (WeasyPrint)
  • leafpress[ui] — adds desktop UI (PyQt6)
  • leafpress[all] — everything

Improvements

  • Lazy renderer imports in pipeline — leafpress --help and non-PDF commands work without WeasyPrint system libraries installed
  • Friendly error message when PDF output is requested without leafpress[pdf]
  • convert -f all now generates 5 formats (PDF, DOCX, HTML, ODT, EPUB)

Tests

  • 21 new EPUB renderer tests (cover page, TOC, chapter splitting, branding, watermarks, metadata)
  • 23 new DOCX import tests (headings, formatting, lists, tables, images, code blocks, pipe tables, CLI integration)
  • 291 total tests, 91% coverage

Docs

  • New EPUB documentation page with format details and examples
  • Installation restructured with extras: base, [pdf], [ui], [all]
  • CLI, CI/CD, and homepage updated to include EPUB format
  • Dockerfile updated with --extra pdf for optional dependency
  • GitHub Action updated to install leafpress[pdf]

0.1.3 — 2026-03-10

Features

  • leafpress fetch-diagrams command to pull diagrams from URLs and Lucidchart API
  • --fetch-diagrams flag on convert command to fetch diagrams as a pre-step
  • diagrams config section in leafpress.yml with caching, Lucidchart token, and source list
  • LEAFPRESS_LUCIDCHART_TOKEN environment variable for secure token configuration

Tests

  • 17 new DOCX HTML converter tests (strikethrough, superscript, subscript, highlight, line break, task lists, nested lists, images, emoji) — coverage from 90% to 99%
  • 30 new diagram tests (config models, cache staleness, URL/Lucidchart fetch, CLI commands)
  • Fixed internal link checker to skip fenced code blocks

Docs

  • New Diagrams documentation page with configuration, CLI usage, Lucidchart setup, caching, and CI/CD examples
  • Diagram Fetching feature card on homepage
  • CLI reference updated with fetch-diagrams command and --fetch-diagrams flag
  • Configuration page updated with diagrams section and field reference
  • CI/CD page updated with diagram fetching examples and LEAFPRESS_LUCIDCHART_TOKEN

0.1.2 — 2026-03-10

Features

  • Docker support with multi-stage build (Dockerfile, .dockerignore, docs page)
  • --version flag documented in CLI reference

Fixes

  • Fixed DOCX watermark rendering (VML namespace registration)

Tests

  • Added 36 new tests bringing coverage from 87% to 91%
  • Added optional Docker integration tests (pytest -m docker)
  • New test files: test_main.py, test_init.py
  • Expanded: test_source.py, test_cli.py, test_git_info.py, test_docx_renderer.py, test_odt_renderer.py

Docs

  • Added Docker documentation page and feature card on homepage
  • Added Global Options section to CLI reference

0.1.1 — 2026-03-10

Features

  • HTML single-file output format
  • ODT (OpenDocument Text) output format
  • --local-time CLI flag to use local timezone for cover page dates (default: UTC)
  • leafpress convert -f all generates all four formats in one run
  • Improved leafpress ui error message with install commands for uv, pip, and pipx
  • Watermark overlay support (--watermark CLI flag or watermark config section)

Improvements

  • Single-source version via importlib.metadata (only edit pyproject.toml to bump)
  • GitHub Action updated with html, odt, and all format options and local_time input
  • Desktop UI includes "Use local timezone for dates" checkbox

Tests

  • Added 68 new tests (pipeline, DOCX converter, PDF/HTML/DOCX styles, security)
  • YAML deserialization safety tests (safe_load enforcement, tag neutralization)
  • Path traversal tests for logo_path and template_path

Docs

  • All documentation pages updated for HTML and ODT support
  • CLI reference updated with --local-time flag and new format options
  • CI page updated with new action inputs and environment variables
  • Fixed tab rendering in docs (added pymdownx.tabbed extension)

0.1.0 — 2026-03-09

Initial release.

Features

  • Convert MkDocs sites to PDF (WeasyPrint) and DOCX (python-docx)
  • Branded cover page, table of contents, and footer
  • Git version info embedded in output (tag, commit, date, branch)
  • leafpress.yml branding config
  • LEAFPRESS_* environment variable overrides with .env support
  • Remote git URL sources
  • Desktop UI (PyQt6 menu bar / system tray app)
  • Composite GitHub Action (uses: hutchins/leafpress@main)
  • "Made with LeafPress" attribution in all rendered footers