Scroll to navigation

WEASYPRINT(1) WeasyPrint WEASYPRINT(1)

NAME

weasyprint - WeasyPrint Documentation

The Awesome Document Factory

WeasyPrint is a smart solution helping web developers to create PDF documents. It turns simple HTML pages into gorgeous statistical reports, invoices, tickets…

From a technical point of view, WeasyPrint is a visual rendering engine for HTML and CSS that can export to PDF. It aims to support web standards for printing. WeasyPrint is free software made available under a BSD license.

It is based on various libraries but not on a full rendering engine like WebKit or Gecko. The CSS layout engine is written in Python, designed for pagination, and meant to be easy to hack on.


WeasyPrint has been created and developed by Kozea (https://kozea.fr/). Professional support, maintenance and community management is provided by CourtBouillon (https://www.courtbouillon.org/).

Copyrights are retained by their contributors, no copyright assignment is required to contribute to WeasyPrint. Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion is licensed under the BSD 3-clause license, without any additional terms or conditions. For full authorship information, see the version control history.

FIRST STEPS

Installation

WeasyPrint 54.1 depends on:

  • Python ≥ 3.6.0
  • Pango ≥ 1.44.0
  • pydyf ≥ 0.0.3
  • CFFI ≥ 0.6
  • html5lib ≥ 1.1
  • tinycss2 ≥ 1.0.0
  • cssselect2 ≥ 0.1
  • Pyphen ≥ 0.9.1
  • Pillow ≥ 4.0.0
  • fontTools ≥ 4.0.0

There are many ways to install WeasyPrint, depending on the system you use.

Linux

The easiest way to install WeasyPrint on Linux is to use the package manager of your distribution. WeasyPrint is packaged for recent versions of Debian, Ubuntu, Fedora, Archlinux, Gentoo

If WeasyPrint is not available on your distribution, or if you want to use a more recent version of WeasyPrint, you have to be sure that Python (at least version 3.6.0) and Pango (at least version 1.44.0) are installed on your system. You can verify this by launching:

python3 --version
pango-view --version


If the version of Pango provided by your distribution is too old, you can use version 52.5 of WeasyPrint which does not need recent Pango features.

When everything is OK, you can install WeasyPrint directly on your system or in a virtual environment using pip:

python3 -m venv venv
source venv/bin/activate
pip install weasyprint
weasyprint --info


Alpine ≥ 3.12

To install WeasyPrint without a virtualenv, you need the following packages:

apk add py3-pip py3-pillow py3-cffi py3-brotli gcc musl-dev python3-dev pango


To install WeasyPrint inside a virtualenv using wheels (if possible), you need the following packages:

apk add py3-pip gcc musl-dev python3-dev pango zlib-dev jpeg-dev openjpeg-dev g++ libffi-dev


To install WeasyPrint inside a virtualenv without using wheels, you need the following packages:

apk add py3-pip gcc musl-dev python3-dev pango zlib-dev jpeg-dev openjpeg-dev g++ libffi-dev


Archlinux

To install WeasyPrint without a virtualenv, you need the following packages:

pacman -S python-pip pango python-cffi python-pillow python-brotli python-zopfli


To install WeasyPrint inside a virtualenv using wheels (if possible), you need the following packages:

pacman -S python-pip pango


To install WeasyPrint inside a virtualenv without using wheels, you need the following packages:

pacman -S python-pip pango gcc libjpeg-turbo openjpeg2


Debian ≥ 11

To install WeasyPrint without a virtualenv, you need the following packages:

apt install python3-pip python3-cffi python3-brotli libpango-1.0-0 libpangoft2-1.0-0


To install WeasyPrint inside a virtualenv using wheels (if possible), you need the following packages:

apt install python3-pip libpango-1.0-0 libpangoft2-1.0-0


To install WeasyPrint inside a virtualenv without using wheels, you need the following packages:

apt install python3-pip libpango-1.0-0 libpangoft2-1.0-0 libjpeg-dev libopenjp2-7-dev libffi-dev


Fedora ≥ 34

To install WeasyPrint without a virtualenv, you need the following packages:

yum install python-pip python-pillow python-cffi python3-brotli pango


To install WeasyPrint inside a virtualenv using wheels (if possible), you need the following packages:

yum install python-pip pango


To install WeasyPrint inside a virtualenv without using wheels, you need the following packages:

yum install python-pip pango gcc python3-devel gcc-c++ zlib-devel libjpeg-devel openjpeg2-devel libffi-devel


Ubuntu ≥ 20.04

To install WeasyPrint without a virtualenv, you need the following packages:

apt install python3-pip python3-cffi python3-brotli libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0


To install WeasyPrint inside a virtualenv using wheels (if possible), you need the following packages:

apt install python3-pip libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0


To install WeasyPrint inside a virtualenv without using wheels, you need the following packages:

apt install python3-pip libpango-1.0-0 libharfbuzz0b libpangoft2-1.0-0 libffi-dev libjpeg-dev libopenjp2-7-dev


macOS

The easiest way to install WeasyPrint on macOS is to use Homebrew.

When Homebrew is installed, install Python, Pango and libffi:

brew install python pango libffi


You can then install WeasyPrint in a virtual environment using pip:

python3 -m venv venv
source venv/bin/activate
pip install weasyprint
weasyprint --info


Windows

Installing WeasyPrint on Windows requires to follow a few steps that may not be easy. Please read this chapter carefully.

Only Windows 10 64-bit is supported. You can find this information in the Control Panel → System and Security → System.

The first step is to install the latest version of Python from the Microsoft Store.

When Python is installed, you have to install GTK. Download the latest GTK3 installer and launch it. If you don’t know what some options mean, you can safely keep the default options selected.

When everything is OK, you can launch a command prompt by clicking on the Start menu, typing "cmd" and clicking the "Command Prompt" icon. You can then install WeasyPrint in a virtual environment using pip:

python3 -m venv venv
venv\Scripts\activate.bat
python3 -m pip install weasyprint
python3 -m weasyprint --info


Other Solutions

Other solutions are available to install WeasyPrint. These solutions are not tested but they are known to work for some use cases on specific platforms.

Macports

On macOS, you can install WeasyPrint’s dependencies with Macports:

sudo port install py-pip pango libffi


You can then install WeasyPrint in a virtual environment using pip:

python3 -m venv venv
source venv/bin/activate
pip install weasyprint
weasyprint --info


Conda

On Linux and macOS, WeasyPrint is available on Conda, with a WeasyPrint package on Conda Forge.

WSL

On Windows, you can also use WSL and install WeasyPrint the same way it has to be installed on Linux.

.NET Wrapper

On Windows, Bader Albarrak maintains a .NET wrapper.

AWS

Kotify maintains an AWS Lambda layer, see issue #1003 for more information.

Troubleshooting

Most of the installation problems have already been met, and some issues on GitHub could help you to solve them.

Missing Library

On Windows, most of the problems come from unreachable libraries. If you get an error like cannot load library 'xxx': error xxx, it means that WeasyPrint can’t find this library.

You can set the WEASYPRINT_DLL_DIRECTORIES environment variable to list the folders where the libraries can be found. For example, in cmd.exe:

> set WEASYPRINT_DLL_DIRECTORIES=C:\GTK3\bin;D:\GTK3\bin


You can find more about this issue in #589, #721 or #1240.

Missing Fonts

If no character is drawn in the generated PDF, or if you get squares instead of letters, you have to install fonts and make them available to WeasyPrint. Following the standard way to install fonts on your system should be enough. You can also use @font-face rules to explicitly reference fonts using URLs.

Command-Line

Using the WeasyPrint command line interface can be as simple as this:

weasyprint http://weasyprint.org /tmp/weasyprint-website.pdf


You may see warnings on the standard error output about unsupported CSS properties. See Command-line API for the details of all available options.

In particular, the -s option can add a filename for a user stylesheet. For quick experimentation however, you may not want to create a file. In bash or zsh, you can use the shell’s redirection instead:

weasyprint http://weasyprint.org /tmp/weasyprint-website.pdf \

-s <(echo 'body { font-family: serif !important }')


If you have many documents to convert you may prefer using the Python API in long-lived processes to avoid paying the start-up costs every time.

Python Library

ATTENTION:

Using WeasyPrint with untrusted HTML or untrusted CSS may lead to various security problems.


Quickstart

The Python version of the above example goes like this:


… or with the inline stylesheet:

from weasyprint import HTML, CSS
HTML('http://weasyprint.org/').write_pdf('/tmp/weasyprint-website.pdf',

stylesheets=[CSS(string='body { font-family: serif !important }')])


Instantiating HTML and CSS Objects

If you have a file name, an absolute URL or a readable file object, you can just pass it to HTML or CSS to create an instance. Alternatively, use a named argument so that no guessing is involved:

from weasyprint import HTML
HTML('../foo.html')  # Same as …
HTML(filename='../foo.html')
HTML('http://weasyprint.org')  # Same as …
HTML(url='http://weasyprint.org')
HTML(sys.stdin)  # Same as …
HTML(file_obj=sys.stdin)


If you have a byte string or Unicode string already in memory you can also pass that, although the argument must be named:

from weasyprint import HTML, CSS
# HTML('<h1>foo') would be filename
HTML(string='''

<h1>The title</h1>
<p>Content goes here ''') CSS(string='@page { size: A3; margin: 1cm }')


If you have @font-face rules in your CSS, you have to create a FontConfiguration object:

from weasyprint import HTML, CSS
from weasyprint.text.fonts import FontConfiguration
font_config = FontConfiguration()
html = HTML(string='<h1>The title</h1>')
css = CSS(string='''

@font-face {
font-family: Gentium;
src: url(http://example.com/fonts/Gentium.otf);
}
h1 { font-family: Gentium }''', font_config=font_config) html.write_pdf(
'/tmp/example.pdf', stylesheets=[css],
font_config=font_config)


Rendering to a Single File

Once you have a HTML object, call its HTML.write_pdf() method to get the rendered document in a single PDF file.

Without arguments, this method returns a byte string in memory. If you pass a file name or a writable file object, they will write there directly instead. (Warning: with a filename, these methods will overwrite existing files silently.)

Individual Pages & Meta-Data

If you want more than a single PDF, the HTML.render() method gives you a document.Document object with access to individual document.Page objects. Thus you can get the number of pages, their size[1], the details of hyperlinks and bookmarks, etc. Documents also have a document.Document.write_pdf() method, and you can get a subset of the pages with document.Document.copy(). Finally, for ultimate control, document.Page.paint() individual pages anywhere on any pydyf.Stream.

[1]
Pages in the same document do not always have the same size.

See the Python API for details. A few random examples:

# Write odd and even pages separately:
#   Lists count from 0 but page numbers usually from 1
#   [::2] is a slice of even list indexes but odd-numbered pages.
document.copy(document.pages[::2]).write_pdf('odd_pages.pdf')
document.copy(document.pages[1::2]).write_pdf('even_pages.pdf')


# Print the outline of the document.
# Output on http://www.w3.org/TR/CSS21/intro.html
#     1. Introduction to CSS 2.1 (page 2)
#       1. A brief CSS 2.1 tutorial for HTML (page 2)
#       2. A brief CSS 2.1 tutorial for XML (page 5)
#       3. The CSS 2.1 processing model (page 6)
#         1. The canvas (page 7)
#         2. CSS 2.1 addressing model (page 7)
#       4. CSS design principles (page 8)
def print_outline(bookmarks, indent=0):

for i, bookmark in enumerate(bookmarks, 1):
page = bookmark.destination[0]
print('%s%d. %s (page %d)' % (
' ' * indent, i, bookmark.label.lstrip('0123456789. '), page))
print_outline(bookmark.children, indent + 2) print_outline(document.make_bookmark_tree())


URL Fetchers

WeasyPrint goes through a URL fetcher to fetch external resources such as images or CSS stylesheets. The default fetcher can natively open file and HTTP URLs, but the HTTP client does not support advanced features like cookies or authentication. This can be worked-around by passing a custom url_fetcher callable to the HTML or CSS classes. It must have the same signature as default_url_fetcher().

Custom fetchers can choose to handle some URLs and defer others to the default fetcher:

from weasyprint import default_url_fetcher, HTML
def my_fetcher(url):

if url.startswith('graph:'):
graph_data = map(float, url[6:].split(','))
return dict(string=generate_graph(graph_data),
mime_type='image/png')
return default_url_fetcher(url) source = '<img src="graph:42,10.3,87">' HTML(string=source, url_fetcher=my_fetcher).write_pdf('out.pdf')


Flask-WeasyPrint for Flask and Django-Weasyprint for Django both make use of a custom URL fetcher to integrate WeasyPrint and use the filesystem instead of a network call for static and media files.

A custom fetcher should be returning a dict with

  • One of string (a bytestring) or file_obj (a file object).
  • Optionally: mime_type, a MIME type extracted e.g. from a Content-Type header. If not provided, the type is guessed from the file extension in the URL.
  • Optionally: encoding, a character encoding extracted e.g. from a charset parameter in a Content-Type header
  • Optionally: redirected_url, the actual URL of the resource if there were e.g. HTTP redirects.
  • Optionally: filename, the filename of the resource. Usually derived from the filename parameter in a Content-Disposition header

If a file_obj is given, the resource will be closed automatically by the function internally used by WeasyPrint to retreive data.

Image Cache and Optimization

WeasyPrint provides two options to deal with images: optimize_size and image_cache.

optimize_size can enable size optimization for images, but also for fonts. When enabled, the generated PDF will include smaller images and fonts, but the rendering time may be slightly increased.

# No size optimization, faster, but generated PDF is larger
HTML('http://example.org/').write_pdf(

'example.pdf', optimize_size=()) # Full size optimization, slower, but generated PDF is smaller HTML('http://example.org/').write_pdf(
'example.pdf', optimize_size=('fonts', 'images'))


image_cache gives the possibility to use a cache for images, avoiding to download, parse and optimize them each time they are used.

By default, the cache is used document by document, but you can share it between documents if needed. This feature can save a lot of network and CPU time when you render a lot of documents that use the same images.

cache = {}
for i in range(10):

HTML(f'http://example.org/?id={i}').write_pdf(
f'example-{i}.pdf', image_cache=cache)


Logging

Most errors (unsupported CSS property, missing image, ...) are not fatal and will not prevent a document from being rendered.

WeasyPrint uses the logging module from the Python standard library to log these errors and let you know about them. When WeasyPrint is launched in a terminal, logged messaged will go to stderr by default. You can change that by configuring the weasyprint logger object:

import logging
logger = logging.getLogger('weasyprint')
logger.addHandler(logging.FileHandler('/path/to/weasyprint.log'))


The weasyprint.progress logger is used to report the rendering progress. It is useful to get feedback when WeasyPrint is launched in a terminal (using the --verbose or --debug option), or to give this feedback to end users when used as a library.

See the documentation of the logging module for details.

Security

When used with untrusted HTML or untrusted CSS, WeasyPrint can meet security problems. You will need extra configuration in your Python application to avoid high memory use, endless renderings or local files leaks.

This section has been added thanks to the very useful reports and advice from Raz Becker.

Long Renderings

WeasyPrint is pretty slow and can take a long time to render long documents or specially crafted HTML pages.

When WeasyPrint used on a server with HTML or CSS files from untrusted sources, this problem can lead to very long time renderings, with processes with high CPU and memory use. Even small documents may lead to really long rendering times, restricting HTML document size is not enough.

If you use WeasyPrint on a server with HTML or CSS samples coming from untrusted users, you should:

  • limit rendering time and memory use of your process, for example using evil-reload-on-as and harakiri options if you use uWSGI,
  • limit memory use at the OS level, for example with ulimit on Linux,
  • automatically kill the process when it uses too much memory or when the rendering time is too high, by regularly launching a script to do so if no better option is available,
  • truncate and sanitize HTML and CSS input to avoid very long documents and access to external URLs.

Infinite Requests

WeasyPrint can reach files on the network, for example using http:// URIs. For various reasons, HTTP requests may take a long time and lead to problems similar to Long Renderings.

WeasyPrint has a default timeout of 10 seconds for HTTP, HTTPS and FTP resources. This timeout has no effect with other protocols, including access to file:// URIs.

If you use WeasyPrint on a server with HTML or CSS samples coming from untrusted users, or need to reach network resources, you should:

  • use a custom URL fetcher,
  • follow solutions listed in Long Renderings.

Infinite Loops

WeasyPrint has been hit by a large number of bugs, including infinite loops. Specially crafted HTML and CSS files can quite easily lead to infinite loops and infinite rendering times.

If you use WeasyPrint on a server with HTML or CSS samples coming from untrusted users, you should:

follow solutions listed in Long Renderings.

Huge Values

WeasyPrint doesn't restrict integer and float values used in CSS. Using huge values for some properties (page sizes, font sizes, block sizes) can lead to various problems, including infinite rendering times, huge PDF files, high memory use and crashes.

This problem is really hard to avoid. Even parsing CSS stylesheets and searching for huge values is not enough, as it is quite easy to trick CSS pre-processors using relative units (em and % for example).

If you use WeasyPrint on a server with HTML or CSS samples coming from untrusted users, you should:

follow solutions listed in Long Renderings.

Access to Local Files

As any web renderer, WeasyPrint can reach files on the local filesystem using file:// URIs. These files can be shown in img or embed tags for example.

When WeasyPrint used on a server with HTML or CSS files from untrusted sources, this feature may be used to know if files are present on the server filesystem, and to embed them in generated documents.

Unix-like systems also have special local files with infinite size, like /dev/urandom. Referencing these files in HTML or CSS files obviously lead to infinite time renderings.

If you use WeasyPrint on a server with HTML or CSS samples coming from untrusted users, you should:

  • restrict your process access to trusted files using sandboxing solutions,
  • use a custom URL fetcher that doesn't allow file:// URLs or filters access depending on given paths.
  • follow solutions listed in Long Renderings.

System Information Leaks

WeasyPrint relies on many libraries that can leak hardware and software information. Even when this information looks useless, it can be used by attackers to exploit other security breaches.

Leaks can include (but are not restricted to):

  • locally installed fonts (using font-family and @font-face),
  • network configuration (IPv4 and IPv6 support, IP addressing, firewall configuration, using http:// URIs and tracking time used to render documents),
  • Python, Pango and other libraries versions (implementation details lead to different renderings).

SVG Images

Rendering SVG images more or less suffers from the same problems as the ones listed here for WeasyPrint.

Security advices apply for untrusted SVG files as they apply for untrusted HTML and CSS documents.

Note that WeasyPrint’s URL fetcher is used to render SVG files.

COMMON USE CASES

Include in Web Applications

Using WeasyPrint in web applications sometimes requires attention on some details.

Security Problems

First of all, rendering untrusted HTML and CSS files can lead to security problems. Please be sure to carefully follow the different proposed solutions if you allow your users to modify the source of the rendered documents in any way.

Rights Management

Another problem is rights management: you often need to render templates that can only be accessed by authenticated users, and WeasyPrint installed on the server doesn’t send the same cookies as the ones sent by the users. Extensions such as Flask-WeasyPrint (for Flask) or Django-WeasyPrint (for Django) solve this issue with a small amount of code. If you use another framework, you can read these extensions and probably find an equivalent workaround.

Server Side Requests & Self-Signed SSL Certificates

If your server is requesting data from itself, you may encounter a self-signed certificate error, even if you have a valid certificate.

You need to add yourself as a Certificate Authority, so that your self-signed SSL certificates can be requested.

# If you have not yet created a certificate.
sudo openssl req -x509 \

-sha256 \
-nodes \
-newkey rsa:4096 \
-days 365 \
-keyout localhost.key \
-out localhost.crt # Follow the prompts about your certificate and the domain name. openssl x509 -text -noout -in localhost.crt


Add your new self-signed SSL certificate to your nginx.conf, below the line server_name 123.123.123.123;:

ssl_certificate /etc/ssl/certs/localhost.crt;
ssl_certificate_key /etc/ssl/private/localhost.key;


The SSL certificate will be valid when accessing your website from the internet. However, images will not render when requesting files from the same server.

You will need to add your new self-signed certificates as trusted:

sudo cp /etc/ssl/certs/localhost.crt /usr/local/share/ca-certificates/localhost.crt
sudo cp /etc/ssl/private/localhost.key /usr/local/share/ca-certificates/localhost.key
# Update the certificate authority trusted certificates.
sudo update-ca-certificates
# Export your newly updated Certificate Authority Bundle file.
# If using Django, it will use the newly signed certificate authority as
# valid and images will load properly.
sudo tee -a /etc/environment <<< 'export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt'


Adjust Document Dimensions

WeasyPrint does not provide support for adjusting page size or document margins via command-line flags. This is best accomplished with the CSS @page at-rule. Consider the following example:

@page {

size: Letter; /* Change from the default size of A4 */
margin: 3cm; /* Set margin on each page */ }


There is much more which can be achieved with the @page at-rule, such as page numbers, headers, etc. Read more about the page at-rule.

Improve Rendering Speed and Memory Use

WeasyPrint is often slower than other web engines. Python is the usual suspect, but it’s not the main culprit here. Optimization is not the main goal of WeasyPrint and it may lead to unbearable long rendering times.

First of all: WeasyPrint’s performance gets generally better with time. You can check WeasyPerf to compare time and memory needed across versions.

Some tips may help you to get better results.

  • A high number of CSS properties with a high number of HTML tags can lead to a huge amount of time spent for the cascade. Avoiding large CSS frameworks can drastically reduce the rendering time.
  • Tables are known to be slow, especially when they are rendered on multiple pages. When possible, using a common block layout instead gives much faster layouts.
  • Optimizing images and fonts can reduce the PDF size, but increase the rendering time. Moreover, caching images gives the possibility to read and optimize images only once, and thus to save time when the same image is used multiple times. See Image Cache and Optimization.

API REFERENCE

This page is for WeasyPrint 54.1. See changelog for older versions.

API Stability

Everything described here is considered “public”: this is what you can rely on. We will try to maintain backward-compatibility, and we really often do, but there is no hard promise.

Anything else should not be used outside of WeasyPrint itself. We reserve the right to change it or remove it at any point. Use it at your own risk, or have dependency to a specific WeasyPrint version.

Versioning

WeasyPrint provides frequent major releases, and minor releases with only bug fixes. Versioning is close to what many browsers do, including Firefox and Chrome: big major numbers, small minor numbers.

Even if each version does not break the API, each version does break the way documents are rendered, which is what really matters at the end. Providing minor versions would give the illusion that developers can just update WeasyPrint without checking that everything works.

Unfortunately, we have the same problem as the other browsers: when a new version is released, most of the user's websites are rendered exactly the same, but a small part is not. And the only ways to know that, for web developers, are to read the changelog and to check that their pages are correctly rendered.

More about this choice can be found in issue #900.

Command-line API

The weasyprint program takes at least two arguments:

weasyprint [options] <input> <output>


The input is a filename or URL to an HTML document, or - to read HTML from stdin. The output is a filename, or - to write to stdout.

Options can be mixed anywhere before, between, or after the input and output.

Force the input character encoding (e.g. -e utf8).

Filename or URL of a user cascading stylesheet (see Stylesheet Origins) to add to the document (e.g. -s print.css). Multiple stylesheets are allowed.

Set the media type to use for @media. Defaults to print.

Set the base for relative URLs in the HTML input. Defaults to the input’s own URL, or the current directory for stdin.

Adds an attachment to the document. The attachment is included in the PDF output. This option can be used multiple times.

Follow HTML presentational hints.

Optimize the size of generated documents. Supported types are images, fonts, all and none. This option can be used multiple times, all adds all allowed values, none removes all previously set values.

Show warnings and information messages.

Show debugging messages.

Hide logging messages.

Show the version number. Other options and arguments are ignored.

Show the command-line usage. Other options and arguments are ignored.


Python API

HTML document parsed by html5lib.

You can just create an instance with a positional argument: doc = HTML(something) The class will try to guess if the input is a filename, an absolute URL, or a file object.

Alternatively, use one named argument so that no guessing is involved:

  • filename (str or pathlib.Path) -- A filename, relative to the current directory, or absolute.
  • url (str) -- An absolute, fully qualified URL.
  • file_obj (file object) -- Any object with a read method.
  • string (str) -- A string of HTML source.


Specifying multiple inputs is an error: HTML(filename="foo.html", url="localhost://bar.html") will raise a TypeError.

You can also pass optional named arguments:

  • encoding (str) -- Force the source character encoding.
  • base_url (str) -- The base used to resolve relative URLs (e.g. in <img src="../foo.png">). If not provided, try to use the input filename, URL, or name attribute of file objects.
  • url_fetcher (function) -- A function or other callable with the same signature as default_url_fetcher() called to fetch external resources such as stylesheets and images. (See URL Fetchers.)
  • media_type (str) -- The media type to use for @media. Defaults to 'print'. Note: In some cases like HTML(string=foo) relative URLs will be invalid if base_url is not provided.


Lay out and paginate the document, but do not (yet) export it.

This returns a document.Document object which provides access to individual pages and various meta-data. See write_pdf() to get a PDF directly.

New in version 0.15.

  • stylesheets (list) -- An optional list of user stylesheets. List elements are CSS objects, filenames, URLs, or file objects. (See Stylesheet Origins.)
  • presentational_hints (bool) -- Whether HTML presentational hints are followed.
  • optimize_size (tuple) -- Optimize size of generated PDF. Can contain "images" and "fonts".
  • font_config (text.fonts.FontConfiguration) -- A font configuration handling @font-face rules.
  • counter_style (css.counters.CounterStyle) -- A dictionary storing @counter-style rules.
  • image_cache (dict) -- A dictionary used to cache images.

A document.Document object.


Render the document to a PDF file.

This is a shortcut for calling render(), then Document.write_pdf().

  • target (str, pathlib.Path or file object) -- A filename where the PDF file is generated, a file object, or None.
  • stylesheets (list) -- An optional list of user stylesheets. The list's elements are CSS objects, filenames, URLs, or file-like objects. (See Stylesheet Origins.)
  • zoom (float) -- The zoom factor in PDF units per CSS units. Warning: All CSS units are affected, including physical units like cm and named sizes like A4. For values other than 1, the physical CSS units will thus be "wrong".
  • attachments (list) -- A list of additional file attachments for the generated PDF document or None. The list's elements are Attachment objects, filenames, URLs or file-like objects.
  • finisher -- A finisher function, that accepts the document and a pydyf.PDF object as parameters, can be passed to perform post-processing on the PDF right before the trailer is written.
  • presentational_hints (bool) -- Whether HTML presentational hints are followed.
  • optimize_size (tuple) -- Optimize size of generated PDF. Can contain "images" and "fonts".
  • font_config (text.fonts.FontConfiguration) -- A font configuration handling @font-face rules.
  • counter_style (css.counters.CounterStyle) -- A dictionary storing @counter-style rules.
  • image_cache (dict) -- A dictionary used to cache images.

The PDF as bytes if target is not provided or None, otherwise None (the PDF is written to target).



CSS stylesheet parsed by tinycss2.

An instance is created in the same way as HTML, with the same arguments.

An additional argument called font_config must be provided to handle @font-face rules. The same text.fonts.FontConfiguration object must be used for different CSS objects applied to the same document.

CSS objects have no public attributes or methods. They are only meant to be used in the HTML.write_pdf() and HTML.render() methods of HTML objects.


File attachment for a PDF document.

New in version 0.22.

An instance is created in the same way as HTML, except that the HTML specific arguments (encoding and media_type) are not supported. An optional description can be provided with the description argument.

description -- A description of the attachment to be included in the PDF document. May be None.


Fetch an external resource such as an image or stylesheet.

Another callable with the same signature can be given as the url_fetcher argument to HTML or CSS. (See URL Fetchers.)

  • url (str) -- The URL of the resource to fetch.
  • timeout (int) -- The number of seconds before HTTP requests are dropped.
  • ssl_context (ssl.SSLContext) -- An SSL context used for HTTP requests.

An exception indicating failure, e.g. ValueError on syntactically invalid URL.
A dict with the following keys:
  • One of string (a bytestring) or file_obj (a file object).
  • Optionally: mime_type, a MIME type extracted e.g. from a Content-Type header. If not provided, the type is guessed from the file extension in the URL.
  • Optionally: encoding, a character encoding extracted e.g. from a charset parameter in a Content-Type header
  • Optionally: redirected_url, the actual URL of the resource if there were e.g. HTTP redirects.
  • Optionally: filename, the filename of the resource. Usually derived from the filename parameter in a Content-Disposition header

If a file_obj key is given, it is the caller’s responsibility to call file_obj.close(). The default function used internally to fetch data in WeasyPrint tries to close the file object after retreiving; but if this URL fetcher is used elsewhere, the file object has to be closed manually.



A rendered document ready to be painted in a pydyf stream.

Typically obtained from HTML.render(), but can also be instantiated directly with a list of pages, a set of metadata, a url_fetcher function, and a font_config.

Take a subset of the pages.

New in version 0.15.

pages (iterable) -- An iterable of Page objects from pages.
A new Document object.

Examples:

Write two PDF files for odd-numbered and even-numbered pages:

# Python lists count from 0 but pages are numbered from 1.
# [::2] is a slice of even list indexes but odd-numbered pages.
document.copy(document.pages[::2]).write_pdf('odd_pages.pdf')
document.copy(document.pages[1::2]).write_pdf('even_pages.pdf')


Combine multiple documents into one PDF file, using metadata from the first:

all_pages = [p for doc in documents for p in doc.pages]
documents[0].copy(all_pages).write_pdf('combined.pdf')



A dict of fonts used by the document. Keys are hashes used to identify fonts, values are Font objects.

Make a tree of all bookmarks in the document.

New in version 0.15.

A list of bookmark subtrees. A subtree is (label, target, children, state). label is a string, target is (page_number, x, y) like in resolve_links(), and children is a list of child subtrees.


A DocumentMetadata object. Contains information that does not belong to a specific page but to the whole document.

A list of Page objects.

A function or other callable with the same signature as weasyprint.default_url_fetcher() called to fetch external resources such as stylesheets and images. (See URL Fetchers.)

Paint the pages in a PDF file, with metadata.
  • target (str, pathlib.Path or file object) -- A filename where the PDF file is generated, a file object, or None.
  • zoom (float) -- The zoom factor in PDF units per CSS units. Warning: All CSS units are affected, including physical units like cm and named sizes like A4. For values other than 1, the physical CSS units will thus be "wrong".
  • attachments (list) -- A list of additional file attachments for the generated PDF document or None. The list's elements are weasyprint.Attachment objects, filenames, URLs or file-like objects.
  • finisher -- A finisher function, that accepts the document and a pydyf.PDF object as parameters, can be passed to perform post-processing on the PDF right before the trailer is written.

The PDF as bytes if target is not provided or None, otherwise None (the PDF is written to target).



Meta-information belonging to a whole Document.

New in version 0.20.

New attributes may be added in future versions of WeasyPrint.

File attachments, as a list of tuples of URL and a description or None. (Defaults to the empty list.) Extracted from the <link rel=attachment> elements in HTML and written to the /EmbeddedFiles dictionary in PDF.

New in version 0.22.


The authors of the document, as a list of strings. (Defaults to the empty list.) Extracted from the <meta name=author> elements in HTML and written to the /Author info field in PDF.

The creation date of the document, as a string or None. Dates are in one of the six formats specified in W3C’s profile of ISO 8601. Extracted from the <meta name=dcterms.created> element in HTML and written to the /CreationDate info field in PDF.

The description of the document, as a string or None. Extracted from the <meta name=description> element in HTML and written to the /Subject info field in PDF.

The name of one of the software packages used to generate the document, as a string or None. Extracted from the <meta name=generator> element in HTML and written to the /Creator info field in PDF.

Keywords associated with the document, as a list of strings. (Defaults to the empty list.) Extracted from <meta name=keywords> elements in HTML and written to the /Keywords info field in PDF.

The modification date of the document, as a string or None. Dates are in one of the six formats specified in W3C’s profile of ISO 8601. Extracted from the <meta name=dcterms.modified> element in HTML and written to the /ModDate info field in PDF.

The title of the document, as a string or None. Extracted from the <title> element in HTML and written to the /Title info field in PDF.


Represents a single rendered page.

New in version 0.15.

Should be obtained from Document.pages but not instantiated directly.

The dict mapping each anchor name to its target, an (x, y) point in CSS pixels from the top-left of the page.

The page bleed widths as a dict with 'top', 'right', 'bottom' and 'left' as keys, and values in CSS pixels.

The list of (bookmark_level, bookmark_label, target) tuples. bookmark_level and bookmark_label are respectively an int and a string, based on the CSS properties of the same names. target is an (x, y) point in CSS pixels from the top-left of the page.

The page height, including margins, in CSS pixels.

The list of (link_type, target, rectangle) tuples. A rectangle is (x, y, width, height), in CSS pixels from the top-left of the page. link_type is one of three strings:
  • 'external': target is an absolute URL
  • 'internal': target is an anchor name (see Page.anchors). The anchor might be defined in another page, in multiple pages (in which case the first occurence is used), or not at all.
  • 'attachment': target is an absolute URL and points to a resource to attach to the document.


Paint the page into the PDF file.
  • stream (document.Stream) -- A document stream.
  • left_x (float) -- X coordinate of the left of the page, in PDF points.
  • top_y (float) -- Y coordinate of the top of the page, in PDF points.
  • scale (float) -- Zoom scale.
  • clip (bool) -- Whether to clip/cut content outside the page. If false or not provided, content can overflow.



The page width, including margins, in CSS pixels.


A FreeType font configuration.

New in version 0.32.

Keep a list of fonts, including fonts installed on the system, fonts installed for the current user, and fonts referenced by cascading stylesheets.

When created, an instance of this class gathers available fonts. It can then be given to weasyprint.HTML methods or to weasyprint.CSS to find fonts in @font-face rules.


Counter styles dictionary.

New in version 0.52.

Keep a list of counter styles defined by @counter-style rules, indexed by their names.

See https://www.w3.org/TR/css-counter-styles-3/.


Supported Features

URLs

WeasyPrint can read normal files, HTTP, FTP and data URIs. It will follow HTTP redirects but more advanced features like cookies and authentication are currently not supported, although a custom URL fetcher can help.

HTML

Supported HTML Tags

Many HTML elements are implemented in CSS through the HTML5 User-Agent stylesheet.

Some elements need special treatment:

  • The <base> element, if present, determines the base for relative URLs.
  • CSS stylesheets can be embedded in <style> elements or linked by <link rel=stylesheet> elements.
  • <img>, <embed> or <object> elements accept images either in raster formats supported by Pillow (including PNG, JPEG, GIF, ...) or in SVG. SVG images are not rasterized but rendered as vectors in the PDF output.

HTML presentational hints are not supported by default, but most of them can be supported:

  • by using the --presentational-hints CLI parameter, or
  • by setting the presentational_hints parameter of the HTML.render or HTML.write_* methods to True.

Presentational hints include a wide array of attributes that direct styling in HTML, including font color and size, list attributes like type and start, various table alignment attributes, and others. If the document generated by WeasyPrint is missing some of the features you expect from the HTML, try to enable this option.

Stylesheet Origins

HTML documents are rendered with stylesheets from three origins:

  • The HTML5 user agent stylesheet (defines the default appearance of HTML elements);
  • Author stylesheets embedded in the document in <style> elements or linked by <link rel=stylesheet> elements;
  • User stylesheets provided in the API.

Keep in mind that user stylesheets have a lower priority than author stylesheets in the cascade, unless you use !important in declarations to raise their priority.

PDF

In addition to text, raster and vector graphics, WeasyPrint’s PDF files can contain hyperlinks, bookmarks and attachments.

Hyperlinks will be clickable in PDF viewers that support them. They can be either internal, to another part of the same document (eg. <a href="#pdf">) or external, to an URL. External links are resolved to absolute URLs: <a href="/news/"> on the WeasyPrint website would always point to http://weasyprint.org/news/ in PDF files.

PDF bookmarks are also called outlines and are generally shown in a sidebar. Clicking on an entry scrolls the matching part of the document into view. By default all <h1> to <h6> titles generate bookmarks, but this can be controlled with PDF bookmarks.)

Attachments are related files, embedded in the PDF itself. They can be specified through <link rel=attachment> elements to add resources globally or through regular links with <a rel=attachment> to attach a resource that can be saved by clicking on said link. The title attribute can be used as description of the attachment.

Fonts

WeasyPrint can use any font that Pango can find installed on the system. Fonts are automatically embedded in PDF files.

Pango always uses fontconfig to access fonts, even on Windows and macOS. You can list the available fonts thanks to the fc-list command, and know which font is matched by a given pattern thanks to fc-match. Copying a font file into the ~/.local/share/fonts or ~/.fonts directory is generally enough to install a new font. WeasyPrint should support any font format handled by FreeType.

CSS

WeasyPrint supports many of the CSS specifications written by the W3C. You will find in this chapter a comprehensive list of the specifications or drafts with at least one feature implemented in WeasyPrint.

The results of some of the test suites provided by the W3C are also available at test.weasyprint.org. This website uses a tool called WeasySuite that can be useful if you want to implement new features in WeasyPrint.

CSS Level 2 Revision 1

The CSS Level 2 Revision 1 specification, best known as CSS 2.1, is pretty well supported by WeasyPrint. Since version 0.11, it passes the famous Acid2 Test.

The CSS 2.1 features listed here are not supported:

  • The ::first-line pseudo-element.
  • On tables: visibility: collapse.
  • Minimum and maximum height on table-related boxes.
  • Minimum and maximum width and height on page-margin boxes.
  • Conforming font matching algorithm. Currently font-family is passed as-is to Pango.
  • Right-to-left or bi-directional text.
  • System colors and system fonts. The former are deprecated in CSS Color Module Level 3.

To the best of our knowledge, everything else that applies to the print media is supported. Please report a bug if you find this list incomplete.

Selectors Level 3

With the exceptions noted here, all Selectors Level 3 are supported.

PDF is generally not interactive. The :hover, :active, :focus, :target and :visited pseudo-classes are accepted as valid but never match anything.

CSS Text Module Level 3 / 4

The CSS Text Module Level 3 and CSS Text Module Level 4 are working drafts defining "properties for text manipulation" and covering "line breaking, justification and alignment, white space handling, and text transformation".

Among their features, some are already included in CSS 2.1, sometimes with missing or different values (text-indent, text-align, letter-spacing, word-spacing, text-transform, white-space).

New properties defined in Level 3 are supported:

  • the overflow-wrap property replacing word-wrap;
  • the full-width value of the text-transform property; and
  • the tab-size property.

Experimental properties controling hyphenation are supported by WeasyPrint:

  • hyphens,
  • hyphenate-character,
  • hyphenate-limit-chars, and
  • hyphenate-limit-zone.

To get automatic hyphenation, you to set it to auto and have the lang HTML attribute set to one of the languages supported by Pyphen.

<!doctype html>
<html lang=en>
<style>

html { hyphens: auto } </style> …


Automatic hyphenation can be disabled again with the manual value:

html { hyphens: auto }
a[href]::after { content: ' [' attr(href) ']'; hyphens: manual }


The other features provided by CSS Text Module Level 3 are not supported:

  • the line-break and word-break properties;
  • the start, end, match-parent and start end values of the text-align property;
  • the text-align-last and text-justify properties; and
  • the text-indent and hanging-punctuation properties.

The other features provided by CSS Text Module Level 4 are not supported:

  • the text-space-collapse and text-space-trim properties;
  • the text-wrap, wrap-before, wrap-after and wrap-inside properties;
  • the text-align property with an alignment character;
  • the pre-wrap-auto value of the white-space property; and
  • the text-spacing property.

CSS Fonts Module Level 3

The CSS Fonts Module Level 3 is a candidate recommendation describing "how font properties are specified and how font resources are loaded dynamically".

WeasyPrint supports the font-size, font-stretch, font-style and font-weight properties, coming from CSS 2.1.

WeasyPrint also supports the following font features added in Level 3: - font-kerning, - font-variant-ligatures, - font-variant-position, - font-variant-caps, - font-variant-numeric, - font-variant-east-asian, - font-feature-settings, and - font-language-override.

font-family is supported. The string is given to Pango that tries to find a matching font in a way different from what is defined in the recommendation, but that should not be a problem for common use.

The shorthand font and font-variant properties are supported.

WeasyPrint supports the @font-face rule, provided that Pango >= 1.38 is installed.

WeasyPrint does not support the @font-feature-values rule and the values of font-variant-alternates other than normal and historical-forms.

The font-variant-caps property is supported but needs the small-caps variant of the font to be installed. WeasyPrint does not simulate missing small-caps fonts.

CSS Paged Media Module Level 3

The CSS Paged Media Module Level 3 is a working draft including features for paged media "describing how:

  • page breaks are created and avoided;
  • the page properties such as size, orientation, margins, border, and padding are specified;
  • headers and footers are established within the page margins;
  • content such as page counters are placed in the headers and footers; and
  • orphans and widows can be controlled."

All the features of this draft are available, including:

  • the @page rule and the :left, :right, :first and :blank selectors;
  • the page margin boxes;
  • the page-based counters (with known limitations #93);
  • the page size, bleed and marks properties;
  • the named pages.

CSS Generated Content for Paged Media Module

The CSS Generated Content for Paged Media Module (GCPM) is a working draft defining "new properties and values, so that authors may bring new techniques (running headers and footers, footnotes, page selection) to paged media".

Page selectors are supported by WeasyPrint. You can select pages according to their position in the document:

@page :nth(3) { background: red } /* Third page */
@page :nth(2n+1) { background: green } /* Odd pages */


You can also use running elements to put HTML boxes into the page margins (but the start parameter of element() is not supported).

Footnotes are supported. You can put a box in the footnote area using the float: footnote property. Footnote markers and footnote calls can be defined using the ::footnote-marker and ::footnote-call pseudo-elements. You can also change the way footnotes are displayed using the footnote-display property (compact is not supported), and influence over the rendering of difficult pages with footnote-policy.

Page groups (:nth(X of pagename) pseudo-class) are not supported.

CSS Generated Content Module Level 3

The CSS Generated Content Module Level 3 is a working draft helping "authors [who] sometimes want user agents to render content that does not come from the document tree. One familiar example of this is numbered headings […]. Similarly, authors may want the user agent to insert the word "Figure" before the caption of a figure […], or replacing elements with images or other multimedia content."

Named strings are supported by WeasyPrint. You can define strings related to the first or last element of a type present on a page, and display these strings in page borders. This feature is really useful to add the title of the current chapter at the top of the pages of a book for example.

The named strings can embed static strings, counters, cross-references, tag contents and tag attributes.

@top-center { content: string(chapter) }
h2 { string-set: chapter "Current chapter: " content() }


Cross-references retrieve counter or content values from targets (anchors or identifiers) in the current document:

a::after { content: ", on page " target-counter(attr(href), page) }
a::after { content: ", see " target-text(attr(href)) }


In particular, target-counter() and target-text() are useful when it comes to tables of contents (see an example).

You can also control PDF bookmarks with WeasyPrint. Using the experimental bookmark-level, bookmark-label and bookmark-state properties, you can add bookmarks that will be available in your PDF reader.

Bookmarks have already been added in the WeasyPrint's user agent stylesheet, so your generated documents will automatically have bookmarks on headers (from <h1> to <h6>). But for example, if you have only one top-level <h1> and do not wish to include it in the bookmarks, add this in your stylesheet:

h1 { bookmark-level: none }


The other features of this module are not implemented:

  • quotes (content: *-quote);
  • leaders (content: leader()).

CSS Color Module Level 3

The CSS Color Module Level 3 is a recommendation defining "CSS properties which allow authors to specify the foreground color and opacity of an element". Its main goal is to specify how colors are defined, including color keywords and the #rgb, #rrggbb, rgb(), rgba(), hsl(), hsla() syntaxes. Opacity and alpha compositing are also defined in this document.

This recommendation is fully implemented in WeasyPrint, except the deprecated System Colors.

CSS Transforms Module Level 1

The CSS Transforms Module Level 1 working draft "describes a coordinate system within each element is positioned. This coordinate space can be modified with the transform property. Using transform, elements can be translated, rotated and scaled in two or three dimensional space."

WeasyPrint supports the transform and transform-origin properties, and all the 2D transformations (matrix, rotate, translate(X|Y)?, scale(X|Y)?, skew(X|Y)?).

WeasyPrint does not support the transform-style, perspective, perspective-origin and backface-visibility properties, and all the 3D transformations (matrix3d, rotate(3d|X|Y|Z), translate(3d|Z), scale(3d|Z)).

CSS Backgrounds and Borders Module Level 3

The CSS Backgrounds and Borders Module Level 3 is a candidate recommendation defining properties dealing "with the decoration of the border area and with the background of the content, padding and border areas".

The border part of this module is supported, as it is already included in the the CSS 2.1 specification.

WeasyPrint supports the background part of this module (allowing multiple background layers per box), including the background, background-color, background-image, background-repeat, background-attachment, background-position, background-clip, background-origin and background-size properties.

WeasyPrint also supports the rounded corners part of this module, including the border-radius property.

WeasyPrint does not support the border images part of this module, including the border-image, border-image-source, border-image-slice, border-image-width, border-image-outset and border-image-repeat properties.

WeasyPrint does not support the box shadow part of this module, including the box-shadow property. This feature has been implemented in a git branch that is not released, as it relies on raster implementation of shadows.

CSS Image Values and Replaced Content Module Level 3 / 4

The Image Values and Replaced Content Module Level 3 is a candidate recommendation introducing "additional ways of representing 2D images, for example as a list of URIs denoting fallbacks, or as a gradient", defining "several properties for manipulating raster images and for sizing or positioning replaced elements" and "generic sizing algorithm for replaced elements".

The Image Values and Replaced Content Module Level 4 is a working draft on the same subject.

The linear-gradient(), radial-gradient() and repeating-radial-gradient() properties are supported as background images.

The the url() notation is supported, but the image() notation is not supported for background images.

The object-fit and object-position properties are supported.

The from-image and snap values of the image-resolution property are not supported, but the resolution value is supported.

The image-rendering property is supported.

The image-orientation property is not supported.

CSS Box Sizing Module Level 3

The CSS Box Sizing Module Level 3 is a candidate recommendation extending "the CSS sizing properties with keywords that represent content-based 'intrinsic' sizes and context-based 'extrinsic' sizes."

The new property defined in this document is implemented in WeasyPrint: box-sizing.

The min-content, max-content and fit-content() sizing values are not supported.

CSS Overflow Module Level 3

The CSS Overflow Module Level 3 is a working draft containing "the features of CSS relating to scrollable overflow handling in visual media."

The overflow property is supported, as defined in CSS2. overflow-x, overflow-y, overflow-clip-margin, overflow-inline and overflow-block are not supported.

The text-overflow, block-ellipsis, line-clamp, max-lines and continue properties are supported.

CSS Values and Units Module Level 3

The CSS Values and Units Module Level 3 defines various units and keywords used in "value definition field of each CSS property".

The initial and inherit CSS-wide keywords are supported, but the unset keyword is not supported.

Quoted strings, URLs and numeric data types are supported.

Font-related lengths (em, ex, ch, rem), absolute lengths (cm, mm, q, in, pt, pc, px), angles (rad, grad, turn, deg), resolutions (dpi, dpcm, dppx) are supported.

The attr() functional notation is allowed in the content and string-set properties.

Viewport-percentage lengths (vw, vh, vmin, vmax) are not supported.

CSS Multi-column Layout Module

The CSS Multi-column Layout Module "describes multi-column layouts in CSS, a style sheet language for the web. Using functionality described in the specification, content can be flowed into multiple columns with a gap and a rule between them."

Simple multi-column layouts are supported in WeasyPrint. Features such as constrained height, spanning columns or column breaks are not supported. Pagination and overflow are not seriously tested.

The column-width and column-count properties, and the columns shorthand property are supported.

The column-gap, column-rule-color, column-rule-style and column-rule-width properties, and the column-rule shorthand property are supported.

The break-before, break-after and break-inside properties are not supported.

The column-span property is supported for direct children of columns.

The column-fill property is supported, with a column balancing algorithm that should be efficient with simple cases.

CSS Fragmentation Module Level 3 / 4

The CSS Fragmentation Module Level 3 "describes the fragmentation model that partitions a flow into pages, columns, or regions. It builds on the Page model module and introduces and defines the fragmentation model. It adds functionality for pagination, breaking variable fragment size and orientation, widows and orphans."

The CSS Fragmentation Module Level 4 is a working draft on the same subject.

The break-before, break-after and break-inside properties are supported for pages, but not for columns and regions. page-break-* aliases as defined in CSS2 are supported too.

The orphans and widows properties are supported.

The box-decoration-break property is supported, but backgrounds are always repeated and not extended through the whole box as it should be with 'slice' value.

The margin-break property is supported.

CSS Custom Properties for Cascading Variables Module Level 1

The CSS Custom Properties for Cascading Variables Module Level 1 "introduces cascading variables as a new primitive value type that is accepted by all CSS properties, and custom properties for defining them."

The custom properties and the var() notation are supported.

CSS Text Decoration Module Level 3

The CSS Text Decoration Module Level 3 "contains the features of CSS relating to text decoration, such as underlines, text shadows, and emphasis marks."

The text-decoration-line, text-decoration-style and text-decoration-color properties are supported, except from the wavy value of text-decoration-style. The text-decoration shorthand is also supported.

The other properties (text-underline-position, text-emphasis-*, text-shadow) are not supported.

CSS Flexible Box Layout Module Level 1

The CSS Flexible Box Layout Module Level 1 "describes a CSS box model optimized for user interface design", also known as "flexbox".

This module works for simple use cases but is not deeply tested.

All the flex-*, align-*, justify-* and order properties are supported. The flex and flex-flow shorthands are supported too.

GOING FURTHER

Why WeasyPrint?

Automatic document generation is a common need of many applications, even if a lot of operations do not require printed paper anymore.

Invoices, tickets, leaflets, diplomas, documentation, books… All these documents are read and used on paper, but also on electronical readers, on smartphones, on computers. PDF is a great format to store and display them in a reliable way, with pagination.

Using HTML and CSS to generate static and paged content can be strange at first glance: browsers display only one page, with variable dimensions, often in a very dynamic way. But paged media layout is actually included in CSS2, which was already a W3C recommendation in 1998.

Other well-known tools can be used to automatically generate PDF documents, like LaTeX and LibreOffice, but they miss many advantages that HTML and CSS offer. HTML and CSS are very widely known, by developers but also by webdesigners. They are specified in a backwards-compatible way, and regularly adapted to please the use of billions of people. They are really easy to write and generate, with a ridiculous amount of tools that are finely adapted to the needs and taste of their users.

However, the web engines that are used for browsers were very limited for pagination when WeasyPrint was created in 2011. Even now, they lack a lot of basic features. That’s why projects such as wkhtmltopdf and PagedJS have been created: they add some of these features to existing browsers.

Other solutions have beed developed, including web engine dedicated to paged media. Prince, Antennahouse or Typeset.sh created original renderers supporting many features related to pagination. These tools are very powerful, but they are not open source.

Building a free and open source web renderer generating high-quality documents is the main goal of WeasyPrint. Do you think that it was a little bit crazy to create such a big project from scratch? Here is what Simon Sapin wrote in WeasyPrint’s documentation one month after the beginning:

Are we crazy? Yes. But not that much. Each modern web browser did take many developers’ many years of work to get where they are now, but WeasyPrint’s scope is much smaller: there is no user-interaction, no JavaScript, no live rendering (the document doesn’t changed after it was first parsed) and no quirks mode (we don’t need to support every broken page of the web.)

We still need however to implement the whole CSS box model and visual rendering. This is a lot of work, but we feel we can get something useful much quicker than “Let’s build a rendering engine!” may seem.



Simon is often right.

Why Python?

Python is a really good language to design a small, OS-agnostic parser. As it is object-oriented, it gives the possibility to follow the specification with high-level classes and a small amount of very simple code.

Speed is not WeasyPrint’s main goal. Web rendering is a very complex task, and following the Zen of Python helped a lot to keep our sanity (both in our code and in our heads): code simplicity, maintainability and flexibility are the most important goals for this library, as they give the ability to stay really close to the specification and to fix bugs easily.

Dive into the Source

This chapter is a high-level overview of WeasyPrint’s source code. For more details, see the various docstrings or even the code itself. When in doubt, feel free to ask!

Much like in web browsers, the rendering of a document in WeasyPrint goes like this:

1.
The HTML document is fetched and parsed into a tree of elements (like DOM).
2.
CSS stylesheets (either found in the HTML or supplied by the user) are fetched and parsed.
3.
The stylesheets are applied to the DOM-like tree.
4.
The DOM-like tree with styles is transformed into a formatting structure made of rectangular boxes.
5.
These boxes are laid-out with fixed dimensions and position onto pages.
6.
For each page, the boxes are re-ordered to observe stacking rules, and are drawn on a PDF page.
7.
Metadata −such as document information, attachments, embedded files, hyperlinks, and PDF trim and bleed boxes− are added to the PDF.

Parsing HTML

Not much to see here. The HTML class handles step 1 and gives a tree of HTML elements. Although the actual API is different, this tree is conceptually the same as what web browsers call the DOM.

Parsing CSS

As with HTML, CSS stylesheets are parsed in the CSS class with an external library, tinycss2.

In addition to the actual parsing, the css and css.validation modules do some pre-processing:

  • Unknown and unsupported declarations are ignored with warnings. Remaining property values are parsed in a property-specific way from raw tinycss2 tokens into a higher-level form.
  • Shorthand properties are expanded. For example, margin becomes margin-top, margin-right, margin-bottom and margin-left.
  • Hyphens in property names are replaced by underscores (margin-top becomes margin_top). This transformation is safe since none of the known (not ignored) properties have an underscore character.
  • Selectors are pre-compiled with cssselect2.

The Cascade

After that and still in the css package, the cascade (that’s the C in CSS!) applies the stylesheets to the element tree. Selectors associate property declarations to elements. In case of conflicting declarations (different values for the same property on the same element), the one with the highest weight wins. Weights are based on the stylesheet’s origin, !important markers, selector specificity and source order. Missing values are filled in through inheritance (from the parent element) or the property’s initial value, so that every element has a specified value for every property.

These specified values are turned into computed values in the css.computed_values module. Keywords and lengths in various units are converted to pixels, etc. At this point the value for some properties can be represented by a single number or string, but some require more complex objects. For example, a Dimension object can be either an absolute length or a percentage.

The final result of the css.get_all_computed_styles function is a big dict where keys are (element, pseudo_element_type) tuples, and keys are style dict objects. Elements are ElementTree elements, while the type of pseudo-element is a string for eg. ::first-line selectors, or None for “normal” elements. Style dict objects are dicts mapping property names to the computed values. (The return value is not the dict itself, but a convenience style_for function for accessing it.)

Formatting Structure

The visual formatting model explains how elements (from the ElementTree tree) generate boxes (in the formatting structure). This is step 4 above. Boxes may have children and thus form a tree, much like elements. This tree is generally close but not identical to the ElementTree tree: some elements generate more than one box or none.

Boxes are of a lot of different kinds. For example you should not confuse block-level boxes and block containers, though block boxes are both. The formatting_structure.boxes module has a whole hierarchy of classes to represent all these boxes. We won’t go into the details here, see the module and class docstrings.

The formatting_structure.build module takes an ElementTree tree with associated computed styles, and builds a formatting structure. It generates the right boxes for each element and ensures they conform to the models rules (eg. an inline box can not contain a block). Each box has a style attribute containing the style dict of computed values.

The main logic is based on the display property, but it can be overridden for some elements by adding a handler in the html module. This is how <img> and <td colspan=3> are currently implemented, for example.

This module is rather short as most of HTML is defined in CSS rather than in Python, in the user agent stylesheet.

The formatting_structure.build.build_formatting_structure function returns the box for the root element (and, through its children attribute, the whole tree).

Layout

Step 5 is the layout. You could say the everything else is glue code and this is where the magic happens.

During the layout the document’s content is, well, laid out on pages. This is when we decide where to do line breaks and page breaks. If a break happens inside of a box, that box is split into two (or more) boxes in the layout result.

According to the box model, each box has rectangular margin, border, padding and content areas: [image: CSS Box Model] [image]

While box.style contains computed values, the used values are set as attributes of the Box object itself during the layout. This include resolving percentages and especially auto values into absolute, pixel lengths. Once the layout done, each box has used values for margins, border width, padding of each four sides, as well as the width and height of the content area. They also have position_x and position_y, the absolute coordinates of the top-left corner of the margin box (not the content box) from the top-left corner of the page.[1]

Boxes also have helpers methods such as content_box_y and margin_width that give other metrics that can be useful in various parts of the code.

The final result of the layout is a list of PageBox objects.

[1]
These are the coordinates if no CSS transform applies. Transforms change the actual location of boxes, but they are applied later during drawing and do not affect layout.

Stacking & Drawing

In step 6, the boxes are reordered by the stacking module to observe stacking rules such as the z-index property. The result is a tree of stacking contexts.

Next, each laid-out page is drawn onto a PDF page. Since each box has absolute coordinates on the page from the layout step, the logic here should be minimal. If you find yourself adding a lot of logic here, maybe it should go in the layout or stacking instead.

The code lives in the draw module.

Metadata

Finally (step 7), the pdf adds metadata to the PDF file: document information, attachments, hyperlinks, embedded files, trim box and bleed box.

CHANGELOG

Version 54.1

Released on 2022-01-31.

Features:

#1547: Handle break-inside: avoid on tr tags

Bug fixes:

  • #1540, #1239: Handle absolute children in running elements
  • #1538: Handle invalid values in text-align
  • #1536: Handle absolute flex boxes

Contirbutors:

  • Guillaume Ayoub
  • Lucie Anglade

Backers and sponsors:

  • H-Net: Humanities and Social Sciences Online
  • Grip Angebotssoftware
  • Manuel Barkhau
  • SimonSoft
  • Menutech
  • KontextWork
  • Crisp BV
  • Maykin Media
  • René Fritz
  • Simon Sapin
  • NCC Group
  • Nathalie Gutton
  • Andreas Zettl
  • Tom Pohl
  • Spacinov
  • Des images et des mots
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla
  • Gábor
  • Piotr Horzycki

Version 54.0

Released on 2022-01-08.

This version also includes the changes from unstable b1 version listed below.

Bug fixes:

  • #1531: Always use absolute paths to get hrefs in SVG
  • #1523: Fix many rendering problems of broken tables
  • e1aee70: Fix support of fonts with SVG emojis

Contirbutors:

Guillaume Ayoub

Backers and sponsors:

  • Grip Angebotssoftware
  • Manuel Barkhau
  • SimonSoft
  • Menutech
  • KontextWork
  • Crisp BV
  • Maykin Media
  • René Fritz
  • Simon Sapin
  • NCC Group
  • Nathalie Gutton
  • Andreas Zettl
  • Tom Pohl
  • Des images et des mots
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla
  • Gábor
  • Piotr Horzycki

Version 54.0b1

Released on 2021-12-13.

This version is experimental, don't use it in production. If you find bugs, please report them!

Dependencies:

html5lib 1.1+ is now needed.

New features:

  • #1509: Support footnotes, with financial support from Code & Co.
  • #36: Handle parallel flows for floats, absolutes, table-cells
  • #1389: Support text-align-last and text-align-all properties
  • #1434: Draw SVG and PNG emojis
  • #1520: Support overflow-wrap: anywhere
  • #1435: Add environment variable to set DLL folder on Windows

Performance:

  • #1439: Cache SVG use tags
  • #1481: Encode non-JPEG images as PNGs instead of JPEG2000s

Bug fixes:

  • #137: Don’t use text-transform text for content-based uses
  • #1443: Don’t serialize and parse again inline SVG files
  • #607: Correctly handle whitespaces in bookmark labels
  • #1094: Fix column height with column-span content
  • #1473: Fix absolutely positioned boxes in duplicated pages
  • #1491: Fix target-counter attribute in flex items
  • #1515, #1508: Don’t draw empty glyphs
  • #1499: Don’t crash when font size is really small

Documentation:

#1519: Fix typo

Packaging:

The source package does not include a setup.py file anymore. You can find more information about this in issue #1410.

Contirbutors:

  • Guillaume Ayoub
  • Lucie Anglade
  • Colin Kinloch
  • aschmitz
  • Pablo González
  • Rian McGuire

Backers and sponsors:

  • Grip Angebotssoftware
  • Manuel Barkhau
  • SimonSoft
  • Menutech
  • KontextWork
  • Crisp BV
  • Maykin Media
  • René Fritz
  • Simon Sapin
  • NCC Group
  • Nathalie Gutton
  • Andreas Zettl
  • Tom Pohl
  • Des images et des mots
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla
  • Gábor
  • Piotr Horzycki

Version 53.4

Released on 2021-11-14.

Bug fixes:

  • #1446: Fix background on pages with a bleed property
  • #1455: Use SVG width/height as inner size when no viewBox is given
  • #1469: Only enable letter- and word-spacing when needed
  • #1471: Don’t display inputs with "hidden" type
  • #1485: Allow quotes in url() syntax for SVG, Use better approximations for font ascent and descent values in SVG
  • #1486: Fix images embedded from multiple pages
  • #1489: Use a better hash for fonts to avoid collisions
  • abd54c4: Set SVG ratio when width and height are 0

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade

Backers and sponsors:

  • Grip Angebotssoftware
  • SimonSoft
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • KontextWork
  • René Fritz
  • Maykin Media
  • NCC Group
  • Crisp BV
  • Des images et des mots
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla
Allard

Gábor

Version 53.3

Released on 2021-09-10.

Bug fixes:

  • #1431, #1440: Fix crashes and malformed PDF files
  • #1430: Handle cx and cy in SVG rotations
  • #1436: Fix marker-start being drawn on mid vertices

Contributors:

  • Guillaume Ayoub
  • Rian McGuire
  • Lucie Anglade

Backers and sponsors:

  • Grip Angebotssoftware
  • SimonSoft
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • KontextWork
  • René Fritz
  • Maykin Media
  • NCC Group
  • Des images et des mots
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla

Version 53.2

Released on 2021-08-27.

New features:

#1428: Re-add the make_bookmark_tree() method

Bug fixes:

#1429: Fix package deployed on PyPI

Contributors:

Guillaume Ayoub

Backers and sponsors:

  • Grip Angebotssoftware
  • PDF Blocks
  • SimonSoft
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • KontextWork
  • René Fritz
  • Maykin Media
  • NCC Group
  • Des images et des mots
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla

Version 53.1

Released on 2021-08-22.

Bug fixes:

  • #1409: Don’t crash when leaders are in floats
  • #1414: Embed images once
  • #1417: Fix crash with SVG intrinsic ratio

Documentation:

#1422: Include weasyprint.tools removal in documentation

Contributors:

Guillaume Ayoub

Backers and sponsors:

  • Grip Angebotssoftware
  • PDF Blocks
  • SimonSoft
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • KontextWork
  • René Fritz
  • Maykin Media
  • NCC Group
  • Des images et des mots
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • Moritz Mahringer
  • Florian Demmer
  • Yanal-Yvez Fargialla

Version 53.0

Released on 2021-07-31.

This version also includes the changes from unstable b1 and b2 versions listed below.

Dependencies:

  • Pango 1.44.0+ is now needed.
  • pydyf 0.0.3+ is now needed.
  • fontTools 4.0.0+ is now needed.
  • html5lib 1.0.1+ is now needed.

API changes:

  • FontConfiguration is now in the weasyprint.text.fonts module.
  • --format and --resolution options have been deprecated, PDF is the only output format supported.
  • --optimize-images option has been deprecated and replaced by --optimize-size, allowing images, fonts, all and none values.
  • weasyprint.tools have been removed.
  • Document.resolve_links, Document.make_bookmark_tree and Document.add_hyperlinks have been removed.

Performance:

Improve image management

New features:

#1374: Support basic "clipPath" in SVG

Bug fixes:

  • #1369: Render use path in SVG
  • #1370: Fix fill color on use path in SVG
  • #1371: Handle stroke-opacity and fill-opacity
  • #1378: Fix crash with borders whose widths are in em
  • #1394: Fix crash on draw_pattern
  • #880: Handle stacking contexts put in contexts by previous generations
  • #1386: Catch font subsetting errors
  • #1403: Fix how x and y attributes are handled in SVG
  • #1399, #1401: Don’t crash when use tags reference non-existing element
  • #1393: Handle font collections
  • #1408: Handle x and y attributes in use tags

Documentation:

#1391, #1405: Add documentation for installation

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade
  • Pelle Bo Regener
  • aschmitz
  • John Jackson
  • Felix Schwarz
  • Syrus Dark
  • Christoph Päper

Backers and sponsors:

  • OpenEdition
  • Grip Angebotssoftware
  • Simonsoft
  • PDF Blocks
  • Menutech
  • Manuel Barkhau
  • print-css.rocks
  • Simon Sapin
  • KontextWork
  • René Fritz
  • Maykin Media
  • Nathalie Gutton
  • Andreas Zettl
  • Tom Pohl
  • NCC Group
  • Moritz Mahringer
  • Florian Demmer
  • Des images et des mots
  • Mohammed Y. Alnajdi
  • Yanal-Yvez Fargialla
  • Yevhenii Hyzyla

Version 53.0b2

Released on 2021-05-30.

This version is experimental, don't use it in production. If you find bugs, please report them!

New features:

#359: Embed full sets of fonts in PDF

Bug fixes:

  • #1345: Fix position of SVG use tags
  • #1346: Handle "stroke-dasharray: none"
  • #1352, #1358: Sort link target identifiers
  • #1357: Fix font information
  • #1362: Handle visibility and display properties in SVG
  • #1365: Cascade inherited attributes for use tags
  • #1366: Correctly handle style attributes in SVG
  • #1367: Include line stroke in box bounding

Documentation:

#1341: Fix typos

Contributors:

  • Guillaume Ayoub
  • aschmitz
  • John Jackson
  • Lucie Anglade
  • Pelle Bo Regener

Backers and sponsors:

  • OpenEdition
  • print-css.rocks
  • Simonsoft
  • PDF Blocks
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • Grip Angebotssoftware
  • KontextWork
  • René Fritz
  • Nathalie Gutton
  • Andreas Zettl
  • Tom Pohl
  • Maykin Media
  • Moritz Mahringer
  • Florian Demmer
  • Mohammed Y. Alnajdi
  • NCC Group
  • Des images et des mots
  • Yanal-Yvez Fargialla
  • Yevhenii Hyzyla

Version 53.0b1

Released on 2021-04-22.

This version is experimental, don't use it in production. If you find bugs, please report them!

Dependencies:

  • This version uses its own PDF generator instead of Cairo. Rendering may be different for text, gradients, SVG images…
  • Packaging is now done with Flit.

New features:

  • #1328: Add ISO and JIS paper sizes
  • #1309: Leader support, with financial support from Simonsoft

Bug fixes:

  • #504: Fix rendering bugs with PDF gradients
  • #606: Fix rounding errors on PDF dimensions
  • #1264: Include witdh/height when calculating auto margins of absolute boxes
  • #1191: Don’t try to get an earlier page break between columns
  • #1235: Include padding, border, padding when calculating inline-block width
  • #1199: Fix kerning issues with small fonts

Documentation:

#1298: Rewrite documentation

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade
  • Felix Schwarz
  • Syrus Dark
  • Christoph Päper

Backers and sponsors:

  • Simonsoft
  • PDF Blocks
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • Nathalie Gutton
  • Andreas Zettl
  • René Fritz
  • Tom Pohl
  • KontextWork
  • Moritz Mahringer
  • Florian Demmer
  • Maykin Media
  • Yanal-Yvez Fargialla
  • Des images et des mots
  • Yevhenii Hyzyla

Version 52.5

Released on 2021-04-17.

Bug fixes:

  • #1336: Fix text breaking exception
  • #1318: Fix @font-face rules with Pango 1.48.3+

Contributors:

Guillaume Ayoub

Backers and sponsors:

  • Simonsoft
  • PDF Blocks
  • Menutech
  • Manuel Barkhau
  • Simon Sapin
  • Nathalie Gutton
  • Andreas Zettl
  • René Fritz
  • Tom Pohl
  • KontextWork
  • Moritz Mahringer
  • Florian Demmer
  • Maykin Media
  • Yanal-Yvez Fargialla
  • Des images et des mots
  • Yevhenii Hyzyla

Version 52.4

Released on 2021-03-11.

Bug fixes:

  • #1304: Don’t try to draw SVG files with no size
  • ece5f066: Avoid crash on last word detection
  • 4ee42e48: Remove last word before ellipses when hyphenated

Contributors:

Guillaume Ayoub

Backers and sponsors:

  • PDF Blocks
  • Simonsoft
  • Menutech
  • Simon Sapin
  • Manuel Barkhau
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • René Fritz
  • Moritz Mahringer
  • Florian Demmer
  • KontextWork
  • Michele Mostarda

Version 52.3

Released on 2021-03-02.

Bug fixes:

#1299: Fix imports with url() and quotes

New features:

#1300: Add support of line-clamp, with financial support from expert Germany

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade

Backers and sponsors:

  • PDF Blocks
  • Simonsoft
  • Menutech
  • Simon Sapin
  • Manuel Barkhau
  • Andreas Zettl
  • Nathalie Gutton
  • Tom Pohl
  • Moritz Mahringer
  • Florian Demmer
  • KontextWork
  • Michele Mostarda

Version 52.2

Released on 2020-12-06.

Bug fixes:

  • 238e214: Fix URL handling with tinycss2
  • #1248: Include missing test data
  • #1254: Top margins removed from children when tables are displayed on multiple pages
  • #1250: Correctly draw borders on the last line of split tables
  • a6f9c80: Add a nice gif to please gdk-pixbuf 2.42.0

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade
  • Felix Schwarz

Backers and sponsors:

  • PDF Blocks
  • Simonsoft
  • Menutech
  • Simon Sapin
  • Nathalie Gutton
  • Andreas Zetti
  • Tom Pohl
  • Florian Demmer
  • Moritz Mahringer

Version 52.1

Released on 2020-11-02.

Bug fixes:

238e214: Fix URL handling with tinycss2

Contributors:

Guillaume Ayoub

Backers and sponsors:

  • Simonsoft
  • Simon Sapin
  • Nathalie Gutton
  • Andreas Zettl
  • Florian Demmer
  • Moritz Mahringer

Version 52

Released on 2020-10-29.

Dependencies:

  • Python 3.6+ is now needed, Python 3.5 is not supported anymore
  • WeasyPrint now depends on Pillow

New features:

  • #1019: Implement counter-set
  • #1080: Don’t display template tags
  • #1210: Use download attribute in a tags for attachment's filename
  • #1206: Handle strings in list-style-type
  • #1165: Add support for concatenating var() functions in content declarations
  • c56b96b: Add an option to optimize embedded images size, with financial support from Hashbang
  • #969: Add an image cache that can be shared between documents, with financial support from Hashbang

Bug fixes:

  • #1141: Don’t clip page margins on account of body overflow
  • #1000: Don’t apply text-indent twice on inline blocks
  • #1051: Avoid random line breaks
  • #1120: Gather target counters in page margins
  • #1110: Handle most cases for boxes avoiding floats in rtl containers, with financial support from Innovative Software
  • #1111: Fix horizontal position of last rtl line, with financial support from Innovative Software
  • #1114: Fix bug with transparent borders in tables
  • #1146: Don’t gather bookmarks twice for blocks that are displayed on two pages
  • #1237: Use fallback fonts on unsupported WOFF2 and WOFF fonts
  • #1025: Don’t insert the same layout attributes multiple times
  • #1027: Don’t try to break tables after the header or before the footer
  • #1050: Don’t crash on absolute SVG files with no intrinsic size
  • #1204: Fix a crash with a flexbox corner case
  • #1030: Fix frozen builds
  • #1089: Fix Pyinstaller builds
  • #1216: Fix embedded files
  • #1225: Initial support of RTL direction in flexbox layout

Documentation:

  • #1149: Add the --quiet CLI option in the documentation
  • #1061: Update install instructions on Windows

Tests:

#1209: Use GitHub Actions instead of Travis

Contributors:

  • Guillaume Ayoub
  • Lucie Anglade
  • Tontyna
  • Mohammed Y. Alnajdi
  • Mike Voets
  • Bjarni Þórisson
  • Balázs Dukai
  • Bart Broere
  • Endalkachew
  • Felix Schwarz
  • Julien Sanchez
  • Konstantin Alekseev
  • Nicolas Hart
  • Nikolaus Schlemm
  • Thomas J. Lampoltshammer
  • mPyth
  • nempoBu4
  • saddy001

Backers and sponsors:

  • Hashbang
  • Innovative Software
  • Screenbreak
  • Simon Sapin
  • Lisa Warshaw
  • Nathalie Gutton
  • Andreas Zettl
  • Florian Demmer
  • Moritz Mahringer

Version 51

Released on 2019-12-23.

Dependencies:

Pyphen 0.9.1+ is now needed

New features:

  • #882: Add support of element() and running()
  • #972: Add HTML element to Box class
  • 7a4d6f8: Support larger and smaller values for font-size

Bug fixes:

  • #960: Fix how fonts used for macOS tests are installed
  • #956: Fix various crashes due to line breaking bugs
  • #983: Fix typo in variable name
  • #975: Don’t crash when string-set is set to none
  • #998: Keep font attributes when text lines are modified
  • #1005: Don’t let presentational hints add decorations on tables with no borders
  • #974: Don’t crash on improper var() values
  • #1012: Fix rendering of header and footer for empty tables
  • #1013: Avoid quadratic time relative to tree depth when setting page names

Contributors:

  • Lucie Anglade
  • Guillaume Ayoub
  • Guillermo Bonvehí
  • Holger Brunn
  • Felix Schwarz
  • Tontyna

Version 50

Released on 2019-09-19.

New features:

  • #209: Make break-* properties work inside tables
  • #661: Make blocks with overflow: auto grow to include floating children

Bug fixes:

  • #945: Don't break pages between a list item and its marker
  • #727: Avoid tables lost between pages
  • #831: Ignore auto margins on flex containers
  • #923: Fix a couple of crashes when splitting a line twice
  • #896: Fix skip stack order when using a reverse flex direction

Contributors:

  • Lucie Anglade
  • Guillaume Ayoub

Version 49

Released on 2019-09-11.

Performance:

Speed and memory use have been largely improved.

New features:

  • #700: Handle ::marker pseudo-selector
  • 135dc06c: Handle recto and verso parameters for page breaks
  • #907: Provide a clean way to build layout contexts

Bug fixes:

  • #937: Fix rendering of tables with empty lines and rowspans
  • #897: Don't crash when small columns are wrapped in absolute blocks
  • #913: Fix a test about gradient colors
  • #924: Fix title for document with attachments
  • #917: Fix tests with Pango 1.44
  • #919: Fix padding and margin management for column flex boxes
  • #901: Fix width of replaced boxes with no intrinsic width
  • #906: Don't respect table cell width when content doesn't fit
  • #927: Don't use deprecated logger.warn anymore
  • a8662794: Fix margin collapsing between caption and table wrapper
  • 87d9e84f: Avoid infinite loops when rendering columns
  • 789b80e6: Only use in flow children to set columns height
  • 615e298a: Don't include floating elements each time we try to render a column
  • 48d8632e: Avoid not in flow children to compute column height
  • e7c452ce: Fix collapsing margins for columns
  • fb0887cf: Fix crash when using currentColor in gradients
  • f66df067: Don't crash when using ex units in word-spacing in letter-spacing
  • c790ff20: Don't crash when properties needing base URL use var functions
  • d63eac31: Don't crash with object-fit: non images with no intrinsic size

Documentation:

  • #900: Add documentation about semantic versioning
  • #692: Add a snippet about PDF magnification
  • #899: Add .NET wrapper link
  • #893: Fixed wrong nested list comprehension example
  • #902: Add state to the make_bookmark_tree documentation
  • #921: Fix typos in the documentation
  • #328: Add CSS sample for forms

Contributors:

  • Lucie Anglade
  • Guillaume Ayoub
  • Raphael Gaschignard
  • Stani
  • Szmen
  • Thomas Dexter
  • Tontyna

Version 48

Released on 2019-07-08.

Dependencies:

CairoSVG 2.4.0+ is now needed

New features:

  • #891: Handle text-overflow
  • #878: Handle column-span
  • #855: Handle all the text-decoration features
  • #238: Don't repeat background images when it's not needed
  • #875: Handle object-fit and object-position
  • #870: Handle bookmark-state

Bug fixes:

  • #686: Fix column balance when children are not inline
  • #885: Actually use the content box to resolve flex items percentages
  • #867: Fix rendering of KaTeX output, including (1) set row baseline of tables when no cells are baseline-aligned, (2) set baseline for inline tables, (3) don't align lines larger than their parents, (4) force CairoSVG to respect image size defined by CSS.
  • #873: Set a minimum height for empty list elements with outside marker
  • #811: Don't use translations to align flex items
  • #851, #860: Don't cut pages when content overflows a very little bit
  • #862: Don't crash when using UTC dates in metadata

Documentation:

#854: Add a "Tips & Tricks" section

Contributors:

  • Gabriel Corona
  • Guillaume Ayoub
  • Manuel Barkhau
  • Nathan de Maestri
  • Lucie Anglade
  • theopeek

Version 47

Released on 2019-04-12.

New features:

  • #843: Handle CSS variables
  • #846: Handle :nth() page selector
  • #847: Allow users to use a custom SSL context for HTTP requests

Bug fixes:

  • #797: Fix underlined justified text
  • #836: Fix crash when flex items are replaced boxes
  • #835: Fix margin-break: auto

Version 46

Released on 2019-03-20.

New features:

  • #771: Handle box-decoration-break
  • #115: Handle margin-break
  • #821: Continuous integration includes tests on Windows

Bug fixes:

  • #765, #754, #800: Fix many crashes related to the flex layout
  • #783: Fix a couple of crashes with strange texts
  • #827: Named strings and counters are case-sensitive
  • #823: Shrink min/max-height/width according to box-sizing
  • #728, #171: Don't crash when fixed boxes are nested
  • #610, #828: Don't crash when preformatted text lines end with a space
  • #808, #387: Fix position of some images
  • #813: Don't crash when long preformatted text lines end with \n

Documentation:

#815: Add documentation about custom url_fetcher

Version 45

Released on 2019-02-20.

WeasyPrint now has a code of conduct.

A new website has been launched, with beautiful and useful graphs about speed and memory use across versions: check WeasyPerf.

Dependencies:

Python 3.5+ is now needed, Python 3.4 is not supported anymore

Bug fixes:

  • #798: Prevent endless loop and index out of range in pagination
  • #767: Add a --quiet CLI parameter
  • #784: Fix library loading on Alpine
  • #791: Use path2url in tests for Windows
  • #789: Add LICENSE file to distributed sources
  • #788: Fix pending references
  • #780: Don't draw patterns for empty page backgrounds
  • #774: Don't crash when links include quotes
  • #637: Fix a problem with justified text
  • #763: Launch tests with Python 3.7
  • #704: Fix a corner case with tables
  • #804: Don't logger handlers defined before importing WeasyPrint
  • #109, #748: Don't include punctuation for hyphenation
  • #770: Don't crash when people use uppercase words from old-fashioned Microsoft fonts in tables, especially when there's an 5th column
  • Use a separate logger to report the rendering process
  • Add a --debug CLI parameter and set debug level for unknown prefixed CSS properties
  • Define minimal versions of Python and setuptools in setup.cfg

Documentation:

  • #796: Fix a small typo in the tutorial
  • #792: Document no alignement character support
  • #773: Fix phrasing in Hacking section
  • #402: Add a paragraph about fontconfig error
  • #764: Fix list of dependencies for Alpine
  • Fix API documentation of HTML and CSS classes

Version 44

Released on 2018-12-29.

Bug fixes:

  • #742: Don't crash during PDF generation when locale uses commas as decimal separator
  • #746: Close file when reading VERSION
  • Improve speed and memory usage for long texts.

Documentation:

  • #733: Small documentation fixes
  • #735: Fix broken links in NEWS.rst

Version 43

Released on 2018-11-09.

Bug fixes:

  • #726: Make empty strings clear previous values of named strings
  • #729: Include tools in packaging

This version also includes the changes from unstable rc1 and rc2 versions listed below.

Version 43rc2

Released on 2018-11-02.

This version is experimental, don't use it in production. If you find bugs, please report them!

Bug fixes:

  • #706: Fix text-indent at the beginning of a page
  • #687: Allow query strings in file:// URIs
  • #720: Optimize minimum size calculation of long inline elements
  • #717: Display <details> tags as blocks
  • #691: Don't recalculate max content widths when distributing extra space for tables
  • #722: Fix bookmarks and strings set on images
  • #723: Warn users when string() is not used in page margin

Version 43rc1

Released on 2018-10-15.

This version is experimental, don't use it in production. If you find bugs, please report them!

Dependencies:

  • Python 3.4+ is now needed, Python 2.x is not supported anymore
  • Cairo 1.15.4+ is now needed, but 1.10+ should work with missing features (such as links, outlines and metadata)
  • Pdfrw is not needed anymore

New features:

  • Beautiful website
  • #579: Initial support of flexbox
  • #592: Support @font-face on Windows
  • #306: Add a timeout parameter to the URL fetcher functions
  • #594: Split tests using modern pytest features
  • #599: Make tests pass on Windows
  • #604: Handle target counters and target texts
  • #631: Enable counter-increment and counter-reset in page context
  • #622: Allow pathlib.Path objects for HTML, CSS and Attachment classes
  • #674: Add extensive installation instructions for Windows

Bug fixes:

  • #558: Fix attachments
  • #565, #596, #539: Fix many PDF rendering, printing and compatibility problems
  • #614: Avoid crashes and endless loops caused by a Pango bug
  • #662: Fix warnings and errors when generating documentation
  • #666, #685: Fix many table layout rendering problems
  • #680: Don't crash when there's no font available
  • #662: Fix support of some align values in tables

Version 0.42.3

Released on 2018-03-27.

Bug fixes:

  • #583: Fix floating-point number error to fix floating box layout
  • #586: Don't optimize resume_at when splitting lines with trailing spaces
  • #582: Fix table layout with no overflow
  • #580: Fix inline box breaking function
  • #576: Split replaced_min_content_width and replaced_max_content_width
  • #574: Respect text direction and don't translate rtl columns twice
  • #569: Get only first line's width of inline children to get linebox width

Version 0.42.2

Released on 2018-02-04.

Bug fixes:

#560: Fix a couple of crashes and endless loops when breaking lines.

Version 0.42.1

Released on 2018-02-01.

Bug fixes:

  • #566: Don't crash when using @font-config.
  • #567: Fix text-indent with text-align: justify.
  • #465: Fix string(*, start).
  • #562: Handle named pages with pseudo-class.
  • #507: Fix running headers.
  • #557: Avoid infinite loops in inline_line_width.
  • #555: Fix margins, borders and padding in column layouts.

Version 0.42

Released on 2017-12-26.

WeasyPrint is not tested with (end-of-life) Python 3.3 anymore.

This release is probably the last version of the 0.x series.

Next version may include big changes:

  • end of Python 2.7 support,
  • initial support of bidirectional text,
  • initial support of flexbox,
  • improvements for speed and memory usage.

New features:

#532: Support relative file URIs when using CLI.

Bug fixes:

  • #553: Fix slow performance for pre-formatted boxes with a lot of children.
  • #409: Don't crash when rendering some tables.
  • #39: Fix rendering of floats in inlines.
  • #301: Split lines carefully.
  • #530: Fix root when frozen with Pyinstaller.
  • #534: Handle SVGs containing images embedded as data URIs.
  • #360: Fix border-radius rendering problem with some PDF readers.
  • #525: Fix pipenv support.
  • #227: Smartly handle replaced boxes with percentage width in auto-width parents.
  • #520: Don't ignore CSS @page rules that are imported by an @import rule.

Version 0.41

Released on 2017-10-05.

WeasyPrint now depends on pdfrw >= 0.4.

New features:

#471: Support page marks and bleed.

Bug fixes:

  • #513: Don't crash on unsupported image-resolution values.
  • #506: Fix @font-face use with write_* methods.
  • #500: Improve readability of _select_source function.
  • #498: Use CSS prefixes as recommanded by the CSSWG.
  • #441: Fix rendering problems and crashes when using @font-face.
  • bb3a4db: Try to break pages after a block before trying to break inside it.
  • 1d1654c: Fix and test corner cases about named pages.

Documentation:

  • #508: Add missing libpangocairo dependency for Debian and Ubuntu.
  • a7b17fb: Add documentation on logged rendering steps.

Version 0.40

Released on 2017-08-17.

WeasyPrint now depends on cssselect2 instead of cssselect and lxml.

New features:

  • #57: Named pages.
  • Unprefix properties, see #498.
  • Add a "verbose" option logging the document generation steps.

Bug fixes:

  • #483: Fix slow performance with long pre-formatted texts.
  • #70: Improve speed and memory usage for long documents.
  • #487: Don't crash on local() fonts with a space and no quotes.

Version 0.39

Released on 2017-06-24.

Bug fixes:

Fix the use of WeasyPrint's URL fetcher with CairoSVG.

Version 0.38

Released on 2017-06-16.

Bug fixes:

#477: Don't crash on font-face's src attributes with local functions.

Version 0.37

Released on 2017-06-15.

WeasyPrint now depends on tinycss2 instead of tinycss.

New features:

#437: Support local links in generated PDFs.

Bug fixes:

  • #412: Use a NullHandler log handler when WeasyPrint is used as a library.
  • #417, #472: Don't crash on some line breaks.
  • #327: Don't crash with replaced elements with height set in percentages.
  • #467: Remove incorrect line breaks.
  • #446: Let the logging module do the string interpolation.

Version 0.36

Released on 2017-02-25.

New features:

  • #407: Handle ::first-letter.
  • #423: Warn user about broken cairo versions.

Bug fixes:

#411: Typos fixed in command-line help.

Version 0.35

Released on 2017-02-25.

Bug fixes:

#410: Fix AssertionError in split_text_box.

Version 0.34

Released on 2016-12-21.

Bug fixes:

  • #398: Honor the presentational_hints option for PDFs.
  • #399: Avoid CairoSVG-2.0.0rc* on Python 2.
  • #396: Correctly close files open by mkstemp.
  • #403: Cast the number of columns into int.
  • Fix multi-page multi-columns and add related tests.

Version 0.33

Released on 2016-11-28.

New features:

  • #393: Add tests on MacOS.
  • #370: Enable @font-face on MacOS.

Bug fixes:

  • #389: Always update resume_at when splitting lines.
  • #394: Don't build universal wheels.
  • #388: Fix logic when finishing block formatting context.

Version 0.32

Released on 2016-11-17.

New features:

  • #28: Support @font-face on Linux.
  • Support CSS fonts level 3 almost entirely, including OpenType features.
  • #253: Support presentational hints (optional).
  • Support break-after, break-before and break-inside for pages and columns.
  • #384: Major performance boost.

Bux fixes:

  • #368: Respect white-space for shrink-to-fit.
  • #382: Fix the preferred width for column groups.
  • Handle relative boxes in column-layout boxes.

Documentation:

  • Add more and more documentation about Windows installation.
  • #355: Add fonts requirements for tests.

Version 0.31

Released on 2016-08-28.

New features:

  • #124: Add MIME sniffing for images.
  • #60: CSS Multi-column Layout.
  • #197: Add hyphens at line breaks activated by a soft hyphen.

Bux fixes:

#132: Fix Python 3 compatibility on Windows.

Documentation:

#329: Add documentation about installation on Windows.

Version 0.30

Released on 2016-07-18.

WeasyPrint now depends on html5lib-0.999999999.

Bux fixes:

  • Fix Acid2
  • #325: Cutting lines is broken in page margin boxes.
  • #334: Newest html5lib 0.999999999 breaks rendering.

Version 0.29

Released on 2016-06-17.

Bug fixes:

  • #263: Don't crash with floats with percents in positions.
  • #323: Fix CairoSVG 2.0 pre-release dependency in Python 2.x.

Version 0.28

Released on 2016-05-16.

Bug fixes:

  • #189: white-space: nowrap still wraps on hyphens
  • #305: Fix crashes on some tables
  • Don't crash when transform matrix isn't invertible
  • Don't crash when rendering ratio-only SVG images
  • Fix margins and borders on some tables

Version 0.27

Released on 2016-04-08.

New features:

  • #295: Support the 'rem' unit.
  • #299: Enhance the support of SVG images.

Bug fixes:

#307: Fix the layout of cells larger than their tables.

Documentation:

  • The website is now on GitHub Pages, the documentation is on Read the Docs.
  • #297: Rewrite the CSS chapter of the documentation.

Version 0.26

Released on 2016-01-29.

New features:

  • Support the empty-cells attribute.
  • Respect table, column and cell widths.

Bug fixes:

  • #172: Unable to set table column width on tables td's.
  • #151: Table background colour bleeds beyond table cell boundaries.
  • #260: TypeError: unsupported operand type(s) for +: 'float' and 'str'.
  • #288: Unwanted line-breaks in bold text.
  • #286: AttributeError: 'Namespace' object has no attribute 'attachments'.

Version 0.25

Released on 2015-12-17.

New features:

Support the 'q' unit.

Bug fixes:

  • #285: Fix a crash happening when splitting lines.
  • #284: Escape parenthesis in PDF links.
  • #280: Replace utf8 with utf-8 for gettext/django compatibility.
  • #269: Add support for use when frozen.
  • #250: Don't crash when attachments are not available.

Version 0.24

Released on 2015-08-04.

New features:

#174: Basic support for Named strings.

Bug fixes:

  • #207: Draw rounded corners on replaced boxes.
  • #224: Rely on the font size for rounding bug workaround.
  • #31: Honor the vertical-align property in fixed-height cells.
  • #202: Remove unreachable area/border at bottom of page.
  • #225: Don't allow unknown units during line-height validation.
  • Fix some wrong conflict resolutions for table borders with inset and outset styles.

Version 0.23

Released on 2014-09-16.

Bug fixes:

  • #196: Use the default image sizing algorithm for images’s preferred size.
  • #194: Try more library aliases with dlopen().
  • #201: Consider page-break-after-avoid when pushing floats to the next page.
  • #217: Avoid a crash on zero-sized background images.

Release process:

Start testing on Python 3.4 on Travis-CI.

Version 0.22

Released on 2014-05-05.

New features:

  • #86: Support gzip and deflate encoding in HTTP responses
  • #177: Support for PDF attachments.

Bug fixes:

  • #169: Fix a crash on percentage-width columns in an auto-width table.
  • #168: Make <fieldset> a block in the user-agent stylesheet.
  • #175: Fix some dlopen() library loading issues on OS X.
  • #183: Break to the next page before a float that would overflow the page. (It might still overflow if it’s bigger than the page.)
  • #188: Require a recent enough version of Pyphen

Release process:

  • Drop Python 3.1 support.
  • Set up [Travis CI](http://travis-ci.org/) to automatically test all pushes and pull requests.
  • Start testing on Python 3.4 locally. (Travis does not support 3.4 yet.)

Version 0.21

Released on 2014-01-11.

New features:

  • Add the overflow-wrap property, allowing line breaks inside otherwise-unbreakable words. Thanks Frédérick Deslandes!
  • Add the image-resolution property, allowing images to be sized proportionally to their intrinsic size at a resolution other than 96 image pixels per CSS in (ie. one image pixel per CSS px)

Bug fixes:

  • #145: Fix parsing HTML from an HTTP URL on Python 3.x
  • #40: Use more general hyphenation dictionnaries for specific document languages. (E.g. use hyph_fr.dic for lang="fr_FR".)
  • #26: Fix min-width and max-width on floats.
  • #100: Fix a crash on trailing whitespace with font-size: 0
  • #82: Borders on tables with border-collapse: collapse were sometimes drawn at an incorrect position.
  • #30: Fix positioning of images with position: absolute.
  • #118: Fix a crash when using position: absolute inside a position: relative element.
  • Fix visibility: collapse to behave like visibility: hidden on elements other than table rows and table columns.
  • #147 and #153: Fix dependencies to require lxml 3.0 or a more recent version. Thanks gizmonerd and Thomas Grainger!
  • #152: Fix a crash on percentage-sized table cells in auto-sized tables. Thanks Johannes Duschl!

Version 0.20.2

Released on 2013-12-18.

Fix #146: don't crash when drawing really small boxes with dotted/dashed borders

Version 0.20.1

Released on 2013-12-16.

  • Depend on html5lib >= 0.99 instead of 1.0b3 to fix pip 1.4 support.
  • Fix #74: don't crash on space followed by dot at line break.
  • Fix #78: nicer colors for border-style: ridge/groove/inset/outset.

Version 0.20

Released on 2013-12-14.

  • Add support for border-radius.
  • Feature #77: Add PDF metadata from HTML.
  • Feature #12: Use html5lib.
  • Tables: handle percentages for column groups, columns and cells, and values for row height.
  • Bug fixes:
  • Fix #84: don't crash when stylesheets are not available.
  • Fix #101: use page ids instead of page numbers in PDF bookmarks.
  • Use logger.warning instead of deprecated logger.warn.
  • Add 'font-stretch' in the 'font' shorthand.


Version 0.19.2

Released on 2013-06-18.

Bug fix release:

  • Fix #88: text-decoration: overline not being drawn above the text
  • Bug fix: Actually draw multiple lines when multiple values are given to text-decoration.
  • Use the font metrics for text decoration positioning.
  • Bug fix: Don't clip the border with overflow: hidden.
  • Fix #99: Regression: JPEG images not loading with cairo 1.8.x.

Version 0.19.1

Released on 2013-04-30.

Bug fix release:

  • Fix incorrect intrinsic width calculation leading to unnecessary line breaks in floats, tables, etc.
  • Tweak border painting to look better
  • Fix unnecessary page break before big tables.
  • Fix table row overflowing at the bottom of the page when there are margins above the table.
  • Fix position: fixed to actually repeat on every page.
  • Fix #76: repeat <thead> and <tfoot> elements on every page, even with table border collapsing.

Version 0.19

Released on 2013-04-18.

  • Add support for linear-gradient() and radial-gradient in background images.
  • Add support for the ex and ch length units. (1ex is based on the font instead of being always 0.5em as before.)
  • Add experimental support for Level 4 hyphenation properties.
  • Drop support for CFFI < 0.6 and cairocffi < 0.4.
  • Many bug fixes, including:

  • Fix #54: min/max-width/height on block-level images.
  • Fix #71: Crash when parsing nested functional notation.



Version 0.18

Released on 2013-03-30.

  • Add support for Level 3 backgrounds, including multiple background layers per element/box.
  • Forward-compatibility with (future releases of) cairocffi 0.4+ and CFFI 0.6+.
  • Bug fixes:
  • Avoid some unnecessary line breaks for elements sized based on their content (aka. “shrink-to-fit”) such as floats and page headers.
  • Allow page breaks between empty blocks.
  • Fix #66: Resolve images’ auto width from non-auto height and intrinsic ratio.
  • Fix #21: The data: URL scheme is case-insensitive.
  • Fix #53: Crash when backtracking for break-before/after: avoid.


Version 0.17.1

Released on 2013-03-18.

Bug fixes:

  • Fix #41: GObject initialization when GDK-PixBuf is not installed.
  • Fix #42: absolute URLs without a base URL (ie. document parsed from a string.)
  • Fix some whitespace collapsing bugs.
  • Fix absolutely-positioned elements inside inline elements.
  • Fix URL escaping of image references from CSS.
  • Fix #49: Division by 0 on dashed or dotted border smaller than one dot/dash.
  • Fix #44: bad interaction of page-break-before/after: avoid and floats.

Version 0.17

Released on 2013-02-27.

  • Added text hyphenation with the -weasy-hyphens property.
  • When a document includes JPEG images, embed them as JPEG in the PDF output. This often results in smaller PDF file size compared to the default deflate compression.
  • Switched to using CFFI instead of PyGTK or PyGObject-introspection.
  • Layout bug fixes:
  • Correctly trim whitespace at the end of lines.
  • Fix some cases with floats within inline content.


Version 0.16

Released on 2012-12-13.

  • Add the zoom parameter to HTML.write_pdf and Document.write_pdf() <weasyprint.document.Document.write_pdf>
  • Fix compatibility with old (and buggy) pycairo versions. WeasyPrint is now tested on 1.8.8 in addition to the latest.
  • Fix layout bugs related to line trailing spaces.

Version 0.15

Released on 2012-10-09.

  • Add a low-level API that enables painting pages individually on any cairo surface.
  • Backward-incompatible change: remove the HTML.get_png_pages method. The new low-level API covers this functionality and more.
  • Add support for the font-stretch property.
  • Add support for @page:blank to select blank pages.
  • New Sphinx-based and improved docs
  • Bug fixes:
  • Importing Pango in some PyGTK installations.
  • Layout of inline-blocks with vertical-align: top or bottom.
  • Do not repeat a block’s margin-top or padding-top after a page break.
  • Performance problem with large tables split across many pages.
  • Anchors and hyperlinks areas now follow CSS transforms. Since PDF links have to be axis-aligned rectangles, the bounding box is used. This may be larger than expected with rotations that are not a multiple of 90 degrees.


Version 0.14

Released on 2012-08-03.

  • Add a public API to choose media type used for @media. (It still defaults to print). Thanks Chung Lu!
  • Add --base-url and --resolution to the command-line API, making it as complete as the Python one.
  • Add support for the <base href="..."> element in HTML.
  • Add support for CSS outlines
  • Switch to gdk-pixbuf instead of Pystacia for loading raster images.
  • Bug fixes:
  • Handling of filenames and URLs on Windows
  • Unicode filenames with older version of py2cairo
  • base_url now behaves as expected when set to a directory name.
  • Make some tests more robust


Version 0.13

Released on 2012-07-23.

  • Add support for PyGTK, as an alternative to PyGObject + introspection. This should make WeasyPrint easier to run on platforms that not not have packages for PyGObject 3.x yet.
  • Bug fix: crash in PDF outlines for some malformed HTML documents

Version 0.12

Released on 2012-07-19.

  • Add support for collapsed borders on tables. This is currently incompatible with repeating header and footer row groups on each page: headers and footers are treated as normal row groups on table with border-collapse: collapse.
  • Add url_fetcher to the public API. This enables users to hook into WeasyPrint for fetching linked stylesheets or images, eg. to generate them on the fly without going through the network. This enables the creation of Flask-WeasyPrint.

Version 0.11

Released on 2012-07-04.

  • Add support for floats and clear. Together with various bug fixes, this enables WeasyPrint to pass the Acid2 test! Acid2 is now part of our automated test suite.
  • Add support for the width, min-width, max-width, height, min-height and max-height properties in @page. The size property is now the size of the page’s containing block.
  • Switch the Variable Dimension rules to the new proposal. The previous implementation was broken in many cases.
  • The image-rendering, transform, transform-origin and size properties are now unprefixed. The prefixed form (eg. -weasy-size) is ignored but gives a specific warning.

Version 0.10

Released on 2012-06-25.

  • Add get_png_pages() to the public API. It returns each page as a separate PNG image.
  • Add a resolution parameter for PNG.
  • Add WeasyPrint Navigator, a web application that shows WeasyPrint’s output with clickable links. Yes, that’s a browser in your browser. Start it with python -m weasyprint.navigator
  • Add support for vertical-align: top and vertical-align: bottom
  • Add support for page-break-before: avoid and page-break-after: avoid
  • Bug fixes

Version 0.9

Released on 2012-06-04.

  • Relative, absolute and fixed positioning
  • Proper painting order (z-index)
  • In PDF: support for internal and external hyperlinks as well as bookmarks.
  • Added the tree parameter to the HTML class: accepts a parsed lxml object.
  • Bug fixes, including many crashes.

Bookmarks can be controlled by the -weasy-bookmark-level and -weasy-bookmark-label properties, as described in CSS Generated Content for Paged Media Module.

The default UA stylesheet sets a matching bookmark level on all <h1> to <h6> elements.

Version 0.8

Released on 2012-05-07.

  • Switch from cssutils to tinycss as the CSS parser.
  • Switch to the new cssselect, almost all level 3 selectors are supported now.
  • Support for inline blocks and inline tables
  • Automatic table layout (column widths)
  • Support for the min-width, max-width, min-height and max-height properties, except on table-related and page-related boxes.
  • Speed improvements on big stylesheets / small documents thanks to tinycss.
  • Many bug fixes

Version 0.7.1

Released on 2012-03-21.

Change the license from AGPL to BSD.

Version 0.7

Released on 2012-03-21.

  • Support page breaks between table rows
  • Support for the orphans and widows properties.
  • Support for page-break-inside: avoid
  • Bug fixes

Only avoiding page breaks before/after an element is still missing.

Version 0.6.1

Released on 2012-03-01.

Fix a packaging bug. (Remove use_2to3 in setup.py. We use the same codebase for Python 2 and 3.)

Version 0.6

Released on 2012-02-29.

  • Backward incompatible: completely change the Python API. See the documentation: https://weasyprint.readthedocs.io/en/latest/tutorial.html#as-a-python-library
  • Backward incompatible: Proper margin collapsing. This changes how blocks are rendered: adjoining margins "collapse" (their maximum is used) instead of accumulating.
  • Support images in embed or object elements.
  • Switch to pystacia instead of PIL for raster images
  • Add compatibility with CPython 2.6 and 3.2. (Previously only 2.7 was supported)
  • Many bug fixes

Version 0.5

Released on 2012-02-08.

  • Support for the overflow and clip properties.
  • Support for the opacity property from CSS3 Colors.
  • Support for CSS 2D Transforms. These are prefixed, so you need to use -weasy-transform and -weasy-transform-origin.

Version 0.4

Released on 2012-02-07.

  • Support text-align: justify, word-spacing and letter-spacing.
  • Partial support for CSS3 Paged Media: page size and margin boxes with page-based counters.
  • All CSS 2.1 border styles
  • Fix SVG images with non-pixel units. Requires CairoSVG 0.3
  • Support for page-break-before and page-break-after, except for the value avoid.
  • Support for the background-clip, background-origin and background-size from CSS3 (but still with a single background per element)
  • Support for the image-rendering from SVG. This one is prefixed, use -weasy-image-rendering. It only has an effect on PNG output.

Version 0.3.1

Released on 2011-12-14.

Compatibility with CairoSVG 0.1.2

Version 0.3

Released on 2011-12-13.

  • Backward-incompatible change: the 'size' property is now prefixed (since it is in an experimental specification). Use '-weasy-size' instead.
  • cssutils 0.9.8 or higher is now required.
  • Support SVG images with CairoSVG
  • Support generated content: the :before and :after pseudo-elements, the content, quotes and counter-* properties.
  • Support ordered lists: all CSS 2.1 values of the list-style-type property.
  • New user-agent stylesheet with HTML 5 elements and automatic quotes for many languages. Thanks Peter Moulder!
  • Disable cssutils validation warnings, they are redundant with WeasyPrint’s.
  • Add --version to the command-line script.
  • Various bug fixes

Version 0.2

Released on 2011-11-25.

  • Support for tables.
  • Support the box-sizing property from CSS 3 Basic User Interface
  • Support all values of vertical-align except top and bottom. They are interpreted as text-top and text-bottom.
  • Minor bug fixes

Tables have some limitations: Only the fixed layout and separate border model are supported. There are also no page break inside tables so a table higher than a page will overflow.

Version 0.1

Released on 2011-10-28.

First packaged release. Supports "simple" CSS 2.1 pages: there is no support for floats, tables, or absolute positioning. Other than that most of CSS 2.1 is supported, as well as CSS 3 Colors and Selectors.

CONTRIBUTE

You want to add some code to WeasyPrint, launch its tests or improve its documentation? Thank you very much! Here are some tips to help you play with WeasyPrint in good conditions.

The first step is to clone the repository, create a virtual environment and install WeasyPrint dependencies.

git clone https://github.com/Kozea/WeasyPrint.git
cd WeasyPrint
python -m venv venv
venv/bin/pip install -e .[doc,test]


You can then launch Python to test your changes.

venv/bin/python


Code & Issues

If you’ve found a bug in WeasyPrint, it’s time to report it, and to fix it if you can!

You can report bugs and feature requests on GitHub. If you want to add or fix some code, please fork the repository and create a pull request, we’ll be happy to review your work.

You can find more information about the code architecture in the Dive into the Source section.

Tests

Tests are stored in the tests folder at the top of the repository. They use the pytest library.

You can launch tests (with code coverage and lint) using the following command:

venv/bin/python -m pytest


Documentation

Documentation is stored in the docs folder at the top of the repository. It relies on the Sphinx library.

You can build the documentation using the following command:

venv/bin/sphinx-build docs docs/_build


The documentation home page can now be found in the /path/to/weasyprint/docs/_build/index.html file. You can open this file in a browser to see the final rendering.

SUPPORT

Sponsorship

With donations and sponsorship, you help make the projects better. Donations allow the CourtBouillon team to have more time dedicated to add new features, fix bugs, and improve documentation.

Professional Support

You can improve your experience with CourtBouillon’s tools thanks to our professional support. You want bugs fixed as soon as possible? Your projects would highly benefit from some new features? You or your team would like to get new skills with one of the technologies we master?

Please contact us by mail, by chat, or by tweet to get in touch and find the best way we can help you.

AUTHOR

Simon Sapin and contributors

COPYRIGHT

Simon Sapin and contributors

May 28, 2022 54.1