PeachPDF Documentation
repository·main·Indexed 19 days ago
https://github.com/jhaygood86/peachpdfA pure .NET 8+ library for rendering HTML, MHTML, and local files into PDF documents without external dependencies like headless browsers. It features support for Flexbox, CSS Math, SVG vector rendering, and Tagged PDF (PDF/UA) output. The library is trimming-safe, Native AOT compatible, and includes a standalone command-line tool and a Blazor WebAssembly demo for client-side rendering.
What's inside PeachPDF
- PeachPDF.PdfSharpCore is a .NET Standard partial port of PdfSharp.Xamarin. It includes a port of MigraDoc (version 1.32) and implements image support using StbImageSharp. It is designed for use in .NET environments requiring PDF generation capabilities.
PeachPDF Compatibility and Features
mainPeachPDF is a pure .NET library (requires .NET 8+) that renders HTML to PDF without external processes like Puppeteer or wkhtmltopdf.
Key Features:
- CSS Support: Flexbox, Multi-column, CSS Math (
calc,min,max,clamp), 2D/3D transforms, Gradients, and CSS Custom Properties. - Paged Media:
@pagerules, named pages, margin boxes, and running headers/footers viastring-set/string(). - SVG: Native vector rendering (never rasterized).
- PDF Output: Supports optional Tagged PDF (PDF/UA) via
PdfGenerateConfig.EnableTaggedPdfand automatic metadata extraction from<title>and<meta>. - Deployment: Trimming-safe and Native AOT compatible.
- CSS Support: Flexbox, Multi-column, CSS Math (
Understand the PeachPDF testing strategy
mainPeachPDF uses a multi-layered testing approach to ensure rendering accuracy, as PDF token presence does not always guarantee visual correctness. The strategy includes:
- Automated xUnit Suite: Over 3,000 tests covering the HTML parser, CSS cascade, layout engines (block, inline, flex, table, multi-column), painting, SVG, fonts, and PDF output.
- Continuous Integration (CI): Runs on Windows, Ubuntu, and macOS to catch platform-specific font and text metric issues.
- Coverage Gates: Enforces a 90% diff-coverage requirement for new code.
- Visual Verification: A manual recommendation to use rasterization-based checks for graphics-state features (masks, gradients, transparency).
- Showcase Harness: A tool to visually exercise new capabilities and generate feature showcases.
- Benchmarks: Performance regression testing using BenchmarkDotNet.
Identify third-party component licenses in PeachPDF
mainPeachPDF is licensed under the BSD 3-Clause license. However, it embeds and adapts several third-party components directly within its source tree. If you are redistributing PeachPDF or its components, you must comply with the specific licenses of these embedded parts:
- PdfSharpCore (embedded fork): MIT License. Located at
src/PeachPDF/PdfSharpCore/. - ExCSS (CSS parser, adapted in-tree): MIT License. Located at
src/PeachPDF/CSS/. - Unicode Character Database (bidi data tables): Unicode License v3. Used for bidirectional text support via Brotli-compressed resources in
src/PeachPDF/Text/Resources/Bidi/. - Bundled font assets: Licenses vary per font (typically SIL OFL 1.1 or 3-Clause BSD). Note that these fonts are not shipped in the PeachPDF library or NuGet package; they are used for tests and demos.
- PdfSharpCore (embedded fork): MIT License. Located at
Overview of the PDF Rendering Pipeline
mainThe rendering process follows these stages:
- Configuration:
PdfGeneratorinitializes aPdfDocumentusing settings fromPdfGenerateConfig(page size, orientation, etc.). - Style Resolution:
@pagemargin overrides are resolved from the stylesheet. - Pipeline Execution: The engine runs the HTML $\rightarrow$ DOM $\rightarrow$ CSS $\rightarrow$ Layout $\rightarrow$ Paint pipeline.
- Graphics Translation: The
XGraphicsPdfRenderertranslates drawing calls into PDF content stream operators, handling the coordinate flip from CSS top-left to PDF bottom-left. - Output: The completed
PdfDocumentis returned and can be saved to anyStream.
- Configuration:
Understand CSS integration in SVG rendering
mainPeachPDF supports a full CSS selector engine for styling SVG elements. Styling follows the standard CSS cascade rules with the following precedence (from highest to lowest):
- Inline
style=attributes:style="fill: red;"on an element. <style>element rules: Rules defined within a<style>block, matched via selectors.- Presentation attributes: Plain XML attributes like
fill="red".
CSS Selector Engine Capabilities
The engine supports a wide range of selectors:
- Type selectors: e.g.,
rect - Class and ID selectors: e.g.,
.foo,#foo(Note: SVG selectors are case-sensitive). - Compound selectors: e.g.,
rect.foo - Combinators: Descendant (
g rect), child (.wrap > circle), and sibling combinators. - Attribute selectors: e.g.,
[gradientUnits="userSpaceOnUse"],[data-x^="a"]. - Structural pseudo-classes:
:first-child,:nth-of-type(),:only-of-type,:not(),:empty(where:emptymatches elements with no children other than whitespace), and:only-of-type.
Advanced CSS Features
- Specificity & Importance: Standard specificity applies, and
!importantoverrides normal declarations. - Calculations & Variables:
var()custom properties,calc(),min(),max(), andclamp()are fully resolved. - @property registrations: Custom properties registered via
@propertyare honored, includinginitial-value,inheritsflags, andsyntaxvalidation. - CSS-wide keywords:
initial,inherit,unset, andrevertare supported on SVG paint/geometry properties.
Inline vs. Standalone SVG Cascading
- Inline
<svg>: Participates in the host document's cascade. Rules in the HTML document's<style>or<link>tags will apply to the SVG shapes. - Standalone SVG (e.g.,
<img src="x.svg">ordata:image/svg+xml): Acts as an independent document. It is only styled by its own internal<style>rules; host-document CSS cannot reach it.
- Inline
Trimming and Native AOT compatibility
mainPeachPDF is designed for modern .NET deployment patterns:
- Trimming-safe: It sets
IsTrimmableto ensure it works with the .NET trimmer. - Native AOT-compatible: It sets
IsAotCompatibleand uses source-generatedLibraryImportmarshalling instead of reflection-basedDllImport. This allows you to publish fully native, self-contained executables usingPublishTrimmedorPublishAotwithout additional configuration.
- Trimming-safe: It sets
Understand CSS parsing and rule types
mainPeachPDF uses a custom fork of
ExCSSintegrated directly into the source tree to allow the engine full access to parsed token and rule structures. This enables efficient selector resolution and immediate support for new CSS properties.Supported Rule Types
Parsed stylesheets contain a collection of the following rule types:
StyleRule: Regular selector + declaration blockMediaRule:@media(wraps child rules)FontFaceRule:@font-faceImportRule:@importContainerRule:@containerKeyframesRule:@keyframes(parsed but not animated)ViewportRule:@viewportDocumentRule:@document
Understand limitations of spanning cells in multi-column layouts
mainWhen using a table inside a multi-column container, there are specific behaviors for spanning cells:
- No Splitting: A spanning cell is not split across columns; instead, the table's rows are left to the table's own grid rather than being moved against the column flow.
- Vertical Alignment: The
vertical-alignproperty of a spanning cell resolves against the specific fragment on the page where the cell began, rather than against the entire height of the cell. For example,vertical-align: middlewill center content within that specific page fragment.
Thread safety in PeachPDF
mainPeachPDF is designed for thread safety by using an instance-scoped model.
- Rule: Do not share a single
PdfGeneratorinstance across multiple threads. - Best Practice: Use one
PdfGeneratorper thread.
While
PdfGeneratoris not thread-safe, the underlying process-wide state is protected:- System Font Discovery: Scans OS directories once and stores results in immutable structures. Custom fonts registered on one instance cannot mutate the shared system-font data.
- Global Caches: Process-wide caches (like
GlyphTypefaceCache) are guarded by a reentrant monitor (Lock.EnterFontFactory()) to allow concurrent resolution from different generator instances.
- Rule: Do not share a single
Use Multi-column Layouts with CSS
mainPeachPDF supports CSS multi-column layouts. You can control the number of columns, their width, and how content is distributed.
Key behaviors:
- Column Spanning: Use
column-span: allon a direct child of the multi-column container to break the flow. The element will render at the full width of the container, splitting the columns before and after it. Note that this only works on direct children; it has no effect on deeper descendants. - Column Filling:
column-fill: balance(default): Distributes content evenly across columns using a binary search for minimum height.column-fill: auto: Fills each column to capacity before starting the next.
- Unbreakable Content: Elements that cannot be fragmented (like
<table>or other layout engine containers) will be placed in a column whole. If the element is taller than the column height, the column will grow to accommodate it rather than clipping the overflow. - Column Rules: Use
column-rule(shorthand forwidth,style, andcolor) to render vertical lines between columns.
.container { column-count: 3; column-gap: 1em; column-rule: 1px solid black; column-fill: balance; } .spanning-header { column-span: all; }- Column Spanning: Use
Understand forced break propagation and container behavior
mainWhen using
break-before(or legacypage-break-before) orbreak-after(or legacypage-break-after), the break property propagates outward to the container.- Container Movement: If a break is applied to a container's first in-flow child, the break point is treated as being before the container itself. The entire container—including its background, border, padding, and margin—moves to the new page.
- Propagation Limits: Break propagation stops at the fragmentation context itself or at any box whose children are positioned by a unique layout engine (e.g., flex items, grid items, or table cells).
- No Empty Fragments: A forced break declared on the very first element of a document will not create a blank page at the start.