WeasyPrint Documentation

repository·main·Indexed 27 days ago

https://github.com/kozea/weasyprint

A Python-based visual rendering engine that converts HTML and CSS into high-quality PDF documents. It provides a command-line API and a Python library featuring classes like HTML, CSS, and Attachment for document generation. WeasyPrint supports advanced printing standards including PDF/A, PDF/UA, and PDF/X, as well as specialized formats like Factur-X/ZUGFeRD electronic invoices. Key features include support for CSS page selectors, named strings for headers/footers, automatic hyphenation, and PDF interactive elements like hyperlinks and forms.

Tokens
9.5K
Snippets
35
Records
68
Agent score
93%

What's inside WeasyPrint

  1. Overview of WeasyPrint

    main
    WeasyPrint is a visual rendering engine for HTML and CSS that exports to PDF. It is designed to support web standards for printing and is particularly useful for turning HTML pages into documents like statistical reports, invoices, and tickets. Unlike other engines, it does not use WebKit or Gecko; instead, it uses a CSS layout engine written in Python specifically designed for pagination.
  2. Understand the WeasyPrint rendering pipeline

    main

    WeasyPrint follows a multi-step process to transform HTML and CSS into a PDF document, similar to how web browsers work:

    1. HTML Parsing: The HTML document is fetched and parsed into an element tree (similar to the DOM).
    2. CSS Parsing: CSS stylesheets are fetched and parsed.
    3. Style Application: Stylesheets are applied to the element tree.
    4. Formatting Structure: The styled tree is transformed into a formatting structure consisting of rectangular boxes.
    5. Layout: Boxes are laid out with fixed dimensions and positions onto pages (handling line breaks and page breaks).
    6. Stacking & Drawing: Boxes are re-ordered according to stacking rules (like z-index) and drawn onto PDF pages.
    7. Metadata: Document information, attachments, hyperlinks, and PDF trim/bleed boxes are added.
  3. Quickstart with the WeasyPrint Python Library

    main

    You can quickly render a URL to a PDF or apply inline stylesheets using the HTML and CSS classes.

    Security Warning: Using WeasyPrint with untrusted HTML or untrusted CSS may lead to security problems.

    from weasyprint import HTML
    HTML('https://weasyprint.org/').write_pdf('/tmp/weasyprint-website.pdf')
  4. Get professional support for WeasyPrint

    main
    If you require rapid bug fixes, new feature development, or team training, you can access professional support from CourtBouillon. They offer direct contact via email or chat, as well as long-term consulting packages for priority support.
  5. Secure WeasyPrint when using untrusted HTML or CSS

    main

    When processing HTML, CSS, or SVG from untrusted sources, WeasyPrint is susceptible to security risks including high memory consumption, infinite rendering loops, and local file leaks.

    To mitigate these risks, follow these best practices:

    General Process Security

    • Do not launch the service as root.
    • Launch the process as a user with limited access to the filesystem, network, and memory.
    • Use a container to isolate the rendering environment.

    Mitigating Long Renderings and Infinite Loops

    Specially crafted documents can cause high CPU/memory usage or infinite loops. To prevent this:

    • Limit rendering time and memory use at the process level (e.g., using evil-reload-on-as and harakiri in uWSGI, or ulimit on Linux).
    • Automatically kill processes that exceed memory or time thresholds.
    • Truncate and sanitize HTML and CSS input to limit document size and prevent access to external URLs.

    Mitigating Infinite Network Requests

    WeasyPrint can reach network resources via https:// or ftp:// URIs. While there is a default 10-second timeout for these protocols, they can still cause issues.

    • Use a custom URL fetcher to control network access.
    • Note that the 10-second timeout does not apply to file:// URIs.

    Mitigating Local File Access Leaks

    WeasyPrint can access local files using file:// URIs (e.g., in <img> or <embed> tags), which can be exploited to leak sensitive files or cause infinite rendering (e.g., via /dev/urandom).

    • Restrict process access to trusted files using sandboxing.
    • Use a custom URL fetcher that explicitly disallows file:// URLs or filters access based on allowed paths.

    Mitigating System Information Leaks

    WeasyPrint and its dependencies (Pango, etc.) may leak information about installed fonts, network configuration, or library versions. Use the isolation methods above to minimize the impact of such leaks.

  6. Build WeasyPrint documentation with Sphinx

    main

    Documentation is managed with Sphinx and is located in the docs folder. To build the documentation locally, run:

    venv/bin/sphinx-build docs docs/_build

    Once built, you can view the documentation by opening docs/_build/index.html in your web browser.

  7. Optimize images and use caching

    main

    To control image size and quality in the generated PDF, use the following parameters:

    • optimize_images: Enables size optimization (may increase rendering time).
    • jpeg_quality: Sets JPEG quality from 0 (smallest size) to 95 (best quality).
    • dpi: Sets the resolution in dots per inch to reduce raster image size.
    • cache: Allows sharing an image cache between documents to save network and CPU time. You can pass a dictionary for in-memory caching or a string representing a folder path for disk-based caching (via --cache-folder CLI).
    # Optimized lower-quality images, slightly slower but smaller PDF
    HTML('https://weasyprint.org/').write_pdf(
        'weasyprint.pdf', optimize_images=True, jpeg_quality=60, dpi=150
    )
    
    # Using a shared cache between multiple documents
    cache = {}
    for i in range(10):
        HTML(f'https://weasyprint.org/').write_pdf(
            f'example-{i}.pdf', cache=cache
        )
  8. Attach files to a PDF

    main

    You can attach files to a PDF using three different methods:

    1. HTML Anchor: Use <a rel="attachment" href="filename.ext"> for links that open the file.
    2. HTML Link Tag: Use <link rel="attachment" href="filename.ext"> in the <head> to attach a file globally to the document.
    3. CLI/Python: Use the --attachment CLI flag (can be used multiple times) or the weasyprint.Attachment class in Python.
    <!-- Method 1: Anchor -->
    <a rel="attachment" href="note.txt">view attached note</a>
    
    <!-- Method 2: Global Link -->
    <link rel="attachment" href="note.txt">
    $ weasyprint document.html --attachment note.txt --attachment photo.jpg document.pdf
    from weasyprint import Attachment, HTML
    attachments = [Attachment("note.txt"), Attachment("photo.jpg")]
    HTML(string="<p>PDF with attachments</p>").write_pdf("recipe.pdf", attachments=attachments)
  9. Install WeasyPrint on Alpine Linux

    main

    To install WeasyPrint using the system package manager:

    apk add weasyprint

    To install inside a virtualenv using wheels, you need these dependencies:

    apk add py3-pip so:libgobject-2.0.so.0 so:libpango-1.0.so.0 so:libharfbuzz.so.0 so:libharfbuzz-subset.so.0 so:libfontconfig.so.1 so:libpangoft2-1.0.so.0

    To install inside a virtualenv without using wheels (building from source), you need these dependencies:

    apk add py3-pip so:libgobject-2.0.so.0 so:libpango-1.0.so.0 so:libharfbuzz.so.0 so:libharfbuzz-subset.so.0 so:libfontconfig.so.1 so:libpangoft2-1.0.so.0
    apk add gcc musl-dev python3-dev zlib-dev jpeg-dev openjpeg-dev libwebp-dev g++ libffi-dev
    apk add weasyprint
  10. Generate specialized PDF variants (PDF/A, PDF/UA, PDF/X)

    main

    WeasyPrint can generate specialized PDF variants using the --pdf-variant CLI option or the pdf_variant parameter in the HTML.write_pdf method. Supported variants can be listed via weasyprint --help.

    Important Note: To ensure a valid document, your HTML and CSS must comply with the specific limitations of the chosen standard. Even if WeasyPrint attempts to generate a valid document, compliance is not guaranteed if the source content violates the specification.

    from weasyprint import HTML
    HTML(string="<p>document</p>").write_pdf("document.pdf", pdf_variant="pdf/a-3u")