xhtml2pdf 0.2.22__tar.gz → 0.2.24__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xhtml2pdf-0.2.22/xhtml2pdf.egg-info → xhtml2pdf-0.2.24}/PKG-INFO +171 -84
- xhtml2pdf-0.2.24/README.rst +295 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/pyproject.toml +2 -3
- xhtml2pdf-0.2.24/tests/test_bidi.py +187 -0
- xhtml2pdf-0.2.24/tests/test_block_box.py +486 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_css_parser.py +81 -0
- xhtml2pdf-0.2.24/tests/test_css_variables.py +159 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_document.py +84 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_fonts.py +21 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_parser.py +95 -6
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_reportlab.py +69 -1
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_reportlab_api.py +64 -1
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_reportlab_paragraph.py +43 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_right_to_left_font_support.py +179 -9
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_security_limits.py +28 -8
- xhtml2pdf-0.2.24/tests/test_signatures.py +213 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_special_css.py +76 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_table_border_radius.py +23 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_tables.py +528 -1
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_tags.py +490 -6
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_utils.py +70 -0
- xhtml2pdf-0.2.24/tests/test_word_breaking.py +127 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/__init__.py +1 -1
- xhtml2pdf-0.2.24/xhtml2pdf/_bidi_data.py +578 -0
- xhtml2pdf-0.2.24/xhtml2pdf/bidi.py +654 -0
- xhtml2pdf-0.2.24/xhtml2pdf/builders/block.py +510 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/flex.py +57 -9
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/signs.py +15 -2
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/watermarks.py +11 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/charts.py +145 -8
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/context.py +117 -36
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/default.py +6 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/document.py +60 -3
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/parser.py +346 -37
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/properties.py +51 -2
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/reportlab_paragraph.py +496 -31
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/tables.py +61 -5
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/tags.py +84 -22
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/util.py +95 -46
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/w3c/css.py +14 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/w3c/cssParser.py +130 -12
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/w3c/cssSpecial.py +16 -0
- xhtml2pdf-0.2.24/xhtml2pdf/w3c/css_variables.py +184 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/xhtml2pdf_reportlab.py +577 -26
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24/xhtml2pdf.egg-info}/PKG-INFO +171 -84
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf.egg-info/SOURCES.txt +10 -1
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf.egg-info/requires.txt +2 -3
- xhtml2pdf-0.2.22/README.rst +0 -207
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/AUTHORS.rst +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/LICENSE.txt +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/MANIFEST.in +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/setup.cfg +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_asian_font_support.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_cli.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_css_media_rule.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_files.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_flex.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_flex_flowable.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_flex_layout.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_http.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_inline_block.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_inline_box.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_paragraph.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_paragraph_height.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_pdf.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_position.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_resource_policy.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_selectors.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_table_css.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_update_face_name.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_watermarks.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/tests/test_wsgi.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/__main__.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/__init__.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/flex_layout.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/builders/position.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/config/__init__.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/config/httpconfig.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/config/resources.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/files.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/paragraph.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/pdf.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/pisa.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/w3c/__init__.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/w3c/cssDOMElementInterface.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf/wsgi.py +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf.egg-info/dependency_links.txt +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf.egg-info/entry_points.txt +0 -0
- {xhtml2pdf-0.2.22 → xhtml2pdf-0.2.24}/xhtml2pdf.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: xhtml2pdf
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.24
|
|
4
4
|
Summary: PDF generator using HTML and CSS
|
|
5
5
|
Author-email: Dirk Holtwick <dirk.holtwick@gmail.com>
|
|
6
6
|
Maintainer-email: Luis Zarate <luisza14@gmail.com>, Timo Brembeck <opensource@timo.brembeck.email>
|
|
@@ -246,10 +246,9 @@ License-File: AUTHORS.rst
|
|
|
246
246
|
Requires-Dist: arabic-reshaper>=3.0.0
|
|
247
247
|
Requires-Dist: html5lib>=1.1
|
|
248
248
|
Requires-Dist: Pillow>=8.1.1
|
|
249
|
-
Requires-Dist: pyHanko>=0.
|
|
250
|
-
Requires-Dist: pyhanko-certvalidator>=0.
|
|
249
|
+
Requires-Dist: pyHanko>=0.37.0
|
|
250
|
+
Requires-Dist: pyhanko-certvalidator>=0.32.1
|
|
251
251
|
Requires-Dist: pypdf>=3.1.0
|
|
252
|
-
Requires-Dist: python-bidi>=0.5.0
|
|
253
252
|
Requires-Dist: reportlab<6,>=4.4.9
|
|
254
253
|
Requires-Dist: svglib>=1.2.1
|
|
255
254
|
Provides-Extra: pycairo
|
|
@@ -276,6 +275,9 @@ Dynamic: license-file
|
|
|
276
275
|
XHTML2PDF
|
|
277
276
|
=========
|
|
278
277
|
|
|
278
|
+
**Write the document in HTML and CSS. Get a PDF.** Pure Python on top of
|
|
279
|
+
ReportLab, with no browser to install or keep running.
|
|
280
|
+
|
|
279
281
|
.. image:: https://img.shields.io/pypi/v/xhtml2pdf?label=PyPI&logo=PyPI&logoColor=white&color=blue
|
|
280
282
|
:target: https://pypi.python.org/pypi/xhtml2pdf
|
|
281
283
|
:alt: PyPI version
|
|
@@ -304,152 +306,237 @@ XHTML2PDF
|
|
|
304
306
|
:target: http://xhtml2pdf.readthedocs.io/en/latest/?badge=latest
|
|
305
307
|
:alt: Read the Docs
|
|
306
308
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
309
|
+
xhtml2pdf turns HTML5 and CSS into PDF on top of the ReportLab toolkit. Anyone
|
|
310
|
+
who can build a web page can build an invoice, a report, a ticket or a book
|
|
311
|
+
with it, from a Django or Flask template or from a plain string, and render
|
|
312
|
+
it anywhere Python runs.
|
|
311
313
|
|
|
312
|
-
|
|
314
|
+
Made with xhtml2pdf
|
|
315
|
+
===================
|
|
313
316
|
|
|
314
|
-
|
|
315
|
-
|
|
317
|
+
Every page below is an HTML document converted by xhtml2pdf, fonts, charts,
|
|
318
|
+
barcodes and all.
|
|
316
319
|
|
|
317
|
-
|
|
320
|
+
.. |annual-report| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/annual-report.png
|
|
321
|
+
:width: 180px
|
|
322
|
+
:alt: An annual report with a cover photo, key figures and charts
|
|
318
323
|
|
|
319
|
-
|
|
324
|
+
.. |invoice| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/invoice.png
|
|
325
|
+
:width: 180px
|
|
326
|
+
:alt: An invoice with a long table of line items and totals
|
|
320
327
|
|
|
321
|
-
|
|
328
|
+
.. |book| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/book.png
|
|
329
|
+
:width: 180px
|
|
330
|
+
:alt: The cover of a novella, a full-page illustration with the title
|
|
322
331
|
|
|
332
|
+
.. |poster| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/poster.png
|
|
333
|
+
:width: 180px
|
|
334
|
+
:alt: A concert poster with a city skyline and a strip of dates
|
|
323
335
|
|
|
336
|
+
.. |certificate| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/certificate.png
|
|
337
|
+
:width: 180px
|
|
338
|
+
:alt: A certificate of completion in landscape with a QR code
|
|
324
339
|
|
|
325
|
-
|
|
326
|
-
|
|
340
|
+
.. |receipt-pos| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/receipt-pos.png
|
|
341
|
+
:width: 180px
|
|
342
|
+
:alt: A narrow point-of-sale receipt in a monospaced font
|
|
327
343
|
|
|
328
|
-
|
|
344
|
+
.. |boarding-pass| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/boarding-pass.png
|
|
345
|
+
:width: 180px
|
|
346
|
+
:alt: An airline boarding pass with a barcode and a QR code
|
|
329
347
|
|
|
330
|
-
|
|
348
|
+
.. |event-ticket| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/event-ticket.png
|
|
349
|
+
:width: 180px
|
|
350
|
+
:alt: A concert ticket with a stub and a barcode
|
|
331
351
|
|
|
352
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
353
|
+
| |annual-report| | |invoice| | |book| | |poster| |
|
|
354
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
355
|
+
| |certificate| | |receipt-pos| | |boarding-pass| | |event-ticket| |
|
|
356
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
332
357
|
|
|
333
|
-
|
|
334
|
-
|
|
358
|
+
Quick start
|
|
359
|
+
===========
|
|
335
360
|
|
|
336
|
-
|
|
361
|
+
.. code:: bash
|
|
337
362
|
|
|
338
363
|
pip install xhtml2pdf
|
|
339
364
|
|
|
365
|
+
.. code:: python
|
|
340
366
|
|
|
341
|
-
|
|
342
|
-
============
|
|
367
|
+
from xhtml2pdf import pisa
|
|
343
368
|
|
|
344
|
-
|
|
369
|
+
html = """
|
|
370
|
+
<style>
|
|
371
|
+
@page { size: a4; margin: 2cm;
|
|
372
|
+
@frame footer { -pdf-frame-content: footer; bottom: 1cm;
|
|
373
|
+
margin-left: 2cm; margin-right: 2cm; height: 1cm } }
|
|
374
|
+
h1 { color: #204a87 }
|
|
375
|
+
</style>
|
|
376
|
+
<h1>Hello, PDF</h1>
|
|
377
|
+
<p>Written in HTML, laid out by CSS.</p>
|
|
378
|
+
<div id="footer">Page <pdf:pagenumber /> of <pdf:pagecount /></div>
|
|
379
|
+
"""
|
|
345
380
|
|
|
346
|
-
|
|
381
|
+
with open("hello.pdf", "wb") as output:
|
|
382
|
+
result = pisa.CreatePDF(html, dest=output)
|
|
383
|
+
print("errors:", result.err)
|
|
347
384
|
|
|
348
|
-
|
|
349
|
-
For more information about this, have a look at the `reportlab docs <https://docs.reportlab.com/install/open_source_installation/>`__.
|
|
385
|
+
Or from the command line:
|
|
350
386
|
|
|
351
|
-
|
|
352
|
-
in combination with the ``PyCairo`` extra dependency:
|
|
387
|
+
.. code:: bash
|
|
353
388
|
|
|
354
|
-
|
|
389
|
+
xhtml2pdf report.html report.pdf
|
|
355
390
|
|
|
356
|
-
|
|
357
|
-
|
|
391
|
+
What it can do
|
|
392
|
+
==============
|
|
358
393
|
|
|
394
|
+
**Layout**
|
|
359
395
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
396
|
+
* Flexbox (``display: flex``), including containers that break across
|
|
397
|
+
pages, and ``display: inline-block``.
|
|
398
|
+
* ``position: relative``, ``absolute`` and ``fixed``, with ``z-index``.
|
|
399
|
+
* Block boxes with padding, borders and backgrounds around everything they
|
|
400
|
+
hold, ``border-radius`` on blocks, tables, cells, images and inline
|
|
401
|
+
boxes, and dashed, dotted and double borders.
|
|
402
|
+
* Tables with header rows repeated on every page, ``colspan`` and
|
|
403
|
+
``rowspan``, auto margins and widths, and rows taller than a page cut
|
|
404
|
+
between pages.
|
|
405
|
+
* Word breaking with ``overflow-wrap``, ``page-break-before``/``after``,
|
|
406
|
+
``page-break-inside: avoid`` and keeping a heading with what follows.
|
|
364
407
|
|
|
408
|
+
**CSS**
|
|
365
409
|
|
|
366
|
-
|
|
367
|
-
|
|
410
|
+
* Selectors up to Level 4: ``:not()``, ``:is()``, ``:where()``, ``:has()``,
|
|
411
|
+
``:nth-child()`` and attribute selectors.
|
|
412
|
+
* Custom properties with ``var()``, ``em``/``rem``/percent units, and colours
|
|
413
|
+
with an alpha channel.
|
|
414
|
+
* ``@font-face`` with TrueType and OpenType fonts, matched per character, so
|
|
415
|
+
a paragraph that mixes scripts finds a font for each of them.
|
|
368
416
|
|
|
369
|
-
|
|
417
|
+
**Pages**
|
|
370
418
|
|
|
371
|
-
|
|
419
|
+
* ``@page`` sizes and margins, named page templates and left/right pages,
|
|
420
|
+
background images, and frames for headers, footers and columns.
|
|
421
|
+
* Page numbers and page counts, watermarks and backgrounds from an image or
|
|
422
|
+
another PDF.
|
|
372
423
|
|
|
424
|
+
**Navigation**
|
|
373
425
|
|
|
374
|
-
|
|
375
|
-
|
|
426
|
+
* Tables of contents with dot leaders, more than one per document,
|
|
427
|
+
clickable entries and a PDF outline (bookmarks).
|
|
428
|
+
* Links to any element by ``id``, to other files and to the web.
|
|
376
429
|
|
|
377
|
-
|
|
430
|
+
**International text**
|
|
378
431
|
|
|
379
|
-
|
|
432
|
+
* Right-to-left documents in Arabic, Hebrew, Persian and Urdu, laid out with
|
|
433
|
+
a pure-Python implementation of the Unicode Bidirectional Algorithm that
|
|
434
|
+
passes the whole of the Unicode conformance suites.
|
|
435
|
+
* Chinese, Japanese and Korean, Cyrillic and Greek, with the document's
|
|
436
|
+
language written to the PDF.
|
|
380
437
|
|
|
381
|
-
|
|
438
|
+
**Graphics and PDF features**
|
|
382
439
|
|
|
383
|
-
|
|
440
|
+
* SVG images, bar, line and pie charts, and barcodes and QR codes.
|
|
441
|
+
* Fillable form fields, encryption with passwords and permissions, and
|
|
442
|
+
digital signatures (simple and PAdES) through pyHanko.
|
|
384
443
|
|
|
385
|
-
|
|
386
|
-
xhtml2pdf in editable mode with the ``test``, ``docs`` and ``release``
|
|
387
|
-
extras (the latter brings in ``build`` and ``twine``), and installs the
|
|
388
|
-
pre-commit hooks. Run it and skip to activating the environment::
|
|
444
|
+
**Safe by default**
|
|
389
445
|
|
|
390
|
-
|
|
391
|
-
|
|
446
|
+
* A document cannot read local files outside its directory or reach
|
|
447
|
+
internal network addresses, and ``ResourceAccessPolicy.server()`` adds
|
|
448
|
+
limits on size, nesting and time for HTML from untrusted sources. See
|
|
449
|
+
`Security <https://xhtml2pdf.readthedocs.io/en/latest/security.html>`__.
|
|
392
450
|
|
|
393
|
-
|
|
451
|
+
Documentation
|
|
452
|
+
=============
|
|
394
453
|
|
|
395
|
-
|
|
454
|
+
The documentation is on `Read the Docs <http://xhtml2pdf.readthedocs.io>`__,
|
|
455
|
+
and what changed in each version is in the `Release Notes
|
|
456
|
+
<https://xhtml2pdf.readthedocs.io/en/latest/release-notes.html>`__. Help
|
|
457
|
+
improving it is welcome; a good place to start is
|
|
458
|
+
``docs/source/quickstart.rst``.
|
|
396
459
|
|
|
397
|
-
|
|
460
|
+
Installation
|
|
461
|
+
============
|
|
398
462
|
|
|
399
|
-
|
|
463
|
+
.. code:: bash
|
|
400
464
|
|
|
401
|
-
|
|
465
|
+
pip install xhtml2pdf
|
|
402
466
|
|
|
403
|
-
|
|
467
|
+
Python 3.10 and newer is tested and supported. Every mandatory requirement is
|
|
468
|
+
listed in ``pyproject.toml`` and installed with xhtml2pdf.
|
|
404
469
|
|
|
405
|
-
|
|
470
|
+
ReportLab needs a rendering backend to turn vector graphics into bitmaps (for
|
|
471
|
+
charts and SVG rasterised into the page). The supported one is `cairo
|
|
472
|
+
<https://cairographics.org/>`__, installed system-wide, for example through
|
|
473
|
+
the OS package manager, together with the ``pycairo`` extra:
|
|
406
474
|
|
|
407
|
-
|
|
475
|
+
.. code:: bash
|
|
408
476
|
|
|
409
|
-
pip install
|
|
477
|
+
pip install xhtml2pdf[pycairo]
|
|
410
478
|
|
|
411
|
-
|
|
479
|
+
The ``renderpm`` extra is a deprecated alias for ``pycairo``: ReportLab 5
|
|
480
|
+
removed the C ``RenderPM`` backend. See the `ReportLab installation notes
|
|
481
|
+
<https://docs.reportlab.com/install/open_source_installation/>`__.
|
|
412
482
|
|
|
413
|
-
|
|
483
|
+
Development environment
|
|
484
|
+
=======================
|
|
414
485
|
|
|
415
|
-
|
|
486
|
+
``make devsetup`` creates ``.venv``, installs xhtml2pdf in editable mode with
|
|
487
|
+
the ``test``, ``docs`` and ``release`` extras and installs the pre-commit
|
|
488
|
+
hooks:
|
|
416
489
|
|
|
417
|
-
|
|
490
|
+
.. code:: bash
|
|
418
491
|
|
|
492
|
+
make devsetup
|
|
493
|
+
source .venv/bin/activate
|
|
419
494
|
|
|
420
|
-
|
|
421
|
-
==================
|
|
495
|
+
Or by hand:
|
|
422
496
|
|
|
423
|
-
|
|
497
|
+
.. code:: bash
|
|
424
498
|
|
|
499
|
+
python -m venv .venv
|
|
500
|
+
source .venv/bin/activate
|
|
501
|
+
pip install -e .[test,docs,release]
|
|
425
502
|
|
|
426
503
|
Running tests
|
|
427
504
|
=============
|
|
428
505
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
#. Unit tests. The unit testing framework is currently minimal, but is being
|
|
432
|
-
improved on a regular basis (contributions welcome). They should run in the
|
|
433
|
-
expected way for Python's unittest module, i.e.::
|
|
506
|
+
.. code:: bash
|
|
434
507
|
|
|
435
|
-
|
|
508
|
+
make test # unit tests
|
|
509
|
+
make test-ref # reference renders for testrender
|
|
510
|
+
make test-render # compare the renders against the reference
|
|
511
|
+
make test-browser # compare against a headless browser's rendering
|
|
512
|
+
make test-all # every supported Python and ReportLab, with tox
|
|
436
513
|
|
|
437
|
-
|
|
438
|
-
|
|
514
|
+
``testrender/`` renders a set of documents and compares the pages; the
|
|
515
|
+
browser comparison scores xhtml2pdf against Chrome on the same markup, so a
|
|
516
|
+
change that moves a layout away from a browser's shows up as a regression.
|
|
517
|
+
``tools/perf`` measures time and memory.
|
|
439
518
|
|
|
440
|
-
|
|
519
|
+
Contributing
|
|
520
|
+
============
|
|
441
521
|
|
|
442
|
-
|
|
522
|
+
This project is community-led. Ideas, bug reports with a small HTML that
|
|
523
|
+
shows the problem, and pull requests are welcome on GitHub. If xhtml2pdf is
|
|
524
|
+
useful to you, look at the `test coverage
|
|
525
|
+
<https://coveralls.io/github/xhtml2pdf/xhtml2pdf>`__ for parts that are not
|
|
526
|
+
yet tested.
|
|
443
527
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
528
|
+
You can also support the project on `Patreon
|
|
529
|
+
<https://www.patreon.com/xhtml2pdf>`__ or with Bitcoin:
|
|
530
|
+
``bc1qmr0skzwx5scyvh2ql28f7gfh6l65ua250qv227``.
|
|
447
531
|
|
|
448
|
-
|
|
449
|
-
|
|
532
|
+
**Big thanks** to everyone who has worked on this project so far and to those
|
|
533
|
+
who help maintain it.
|
|
450
534
|
|
|
451
|
-
|
|
535
|
+
Alternatives
|
|
536
|
+
============
|
|
452
537
|
|
|
538
|
+
`WeasyPrint <http://weasyprint.org>`__ covers much of the same ground with a
|
|
539
|
+
different design and set of features.
|
|
453
540
|
|
|
454
541
|
History
|
|
455
542
|
=======
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
XHTML2PDF
|
|
2
|
+
=========
|
|
3
|
+
|
|
4
|
+
**Write the document in HTML and CSS. Get a PDF.** Pure Python on top of
|
|
5
|
+
ReportLab, with no browser to install or keep running.
|
|
6
|
+
|
|
7
|
+
.. image:: https://img.shields.io/pypi/v/xhtml2pdf?label=PyPI&logo=PyPI&logoColor=white&color=blue
|
|
8
|
+
:target: https://pypi.python.org/pypi/xhtml2pdf
|
|
9
|
+
:alt: PyPI version
|
|
10
|
+
|
|
11
|
+
.. image:: https://img.shields.io/pypi/pyversions/xhtml2pdf?label=Python&logo=Python&logoColor=white
|
|
12
|
+
:target: https://www.python.org/downloads
|
|
13
|
+
:alt: Python versions
|
|
14
|
+
|
|
15
|
+
.. image:: https://img.shields.io/github/actions/workflow/status/xhtml2pdf/xhtml2pdf/tests.yml?branch=master&label=Tests&logo=github&logoColor=white
|
|
16
|
+
:target: https://github.com/xhtml2pdf/xhtml2pdf/actions/workflows/tests.yml
|
|
17
|
+
:alt: Tests
|
|
18
|
+
|
|
19
|
+
.. image:: https://img.shields.io/github/actions/workflow/status/xhtml2pdf/xhtml2pdf/linting.yml?branch=master&label=Linting&logo=github&logoColor=white
|
|
20
|
+
:target: https://github.com/xhtml2pdf/xhtml2pdf/actions/workflows/linting.yml
|
|
21
|
+
:alt: Linting
|
|
22
|
+
|
|
23
|
+
.. image:: https://img.shields.io/github/actions/workflow/status/xhtml2pdf/xhtml2pdf/spelling.yml?branch=master&label=Spelling&logo=github&logoColor=white
|
|
24
|
+
:target: https://github.com/xhtml2pdf/xhtml2pdf/actions/workflows/spelling.yml
|
|
25
|
+
:alt: Spelling
|
|
26
|
+
|
|
27
|
+
.. image:: https://img.shields.io/coveralls/github/xhtml2pdf/xhtml2pdf?label=Coveralls&logo=Coveralls&logoColor=white
|
|
28
|
+
:target: https://coveralls.io/github/xhtml2pdf/xhtml2pdf
|
|
29
|
+
:alt: Coveralls
|
|
30
|
+
|
|
31
|
+
.. image:: https://img.shields.io/readthedocs/xhtml2pdf?label=Read%20the%20Docs&logo=read%20the%20docs&logoColor=white
|
|
32
|
+
:target: http://xhtml2pdf.readthedocs.io/en/latest/?badge=latest
|
|
33
|
+
:alt: Read the Docs
|
|
34
|
+
|
|
35
|
+
xhtml2pdf turns HTML5 and CSS into PDF on top of the ReportLab toolkit. Anyone
|
|
36
|
+
who can build a web page can build an invoice, a report, a ticket or a book
|
|
37
|
+
with it, from a Django or Flask template or from a plain string, and render
|
|
38
|
+
it anywhere Python runs.
|
|
39
|
+
|
|
40
|
+
Made with xhtml2pdf
|
|
41
|
+
===================
|
|
42
|
+
|
|
43
|
+
Every page below is an HTML document converted by xhtml2pdf, fonts, charts,
|
|
44
|
+
barcodes and all.
|
|
45
|
+
|
|
46
|
+
.. |annual-report| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/annual-report.png
|
|
47
|
+
:width: 180px
|
|
48
|
+
:alt: An annual report with a cover photo, key figures and charts
|
|
49
|
+
|
|
50
|
+
.. |invoice| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/invoice.png
|
|
51
|
+
:width: 180px
|
|
52
|
+
:alt: An invoice with a long table of line items and totals
|
|
53
|
+
|
|
54
|
+
.. |book| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/book.png
|
|
55
|
+
:width: 180px
|
|
56
|
+
:alt: The cover of a novella, a full-page illustration with the title
|
|
57
|
+
|
|
58
|
+
.. |poster| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/poster.png
|
|
59
|
+
:width: 180px
|
|
60
|
+
:alt: A concert poster with a city skyline and a strip of dates
|
|
61
|
+
|
|
62
|
+
.. |certificate| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/certificate.png
|
|
63
|
+
:width: 180px
|
|
64
|
+
:alt: A certificate of completion in landscape with a QR code
|
|
65
|
+
|
|
66
|
+
.. |receipt-pos| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/receipt-pos.png
|
|
67
|
+
:width: 180px
|
|
68
|
+
:alt: A narrow point-of-sale receipt in a monospaced font
|
|
69
|
+
|
|
70
|
+
.. |boarding-pass| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/boarding-pass.png
|
|
71
|
+
:width: 180px
|
|
72
|
+
:alt: An airline boarding pass with a barcode and a QR code
|
|
73
|
+
|
|
74
|
+
.. |event-ticket| image:: https://raw.githubusercontent.com/xhtml2pdf/xhtml2pdf/master/docs/source/_static/readme/event-ticket.png
|
|
75
|
+
:width: 180px
|
|
76
|
+
:alt: A concert ticket with a stub and a barcode
|
|
77
|
+
|
|
78
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
79
|
+
| |annual-report| | |invoice| | |book| | |poster| |
|
|
80
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
81
|
+
| |certificate| | |receipt-pos| | |boarding-pass| | |event-ticket| |
|
|
82
|
+
+-----------------+-----------------+-----------------+-----------------+
|
|
83
|
+
|
|
84
|
+
Quick start
|
|
85
|
+
===========
|
|
86
|
+
|
|
87
|
+
.. code:: bash
|
|
88
|
+
|
|
89
|
+
pip install xhtml2pdf
|
|
90
|
+
|
|
91
|
+
.. code:: python
|
|
92
|
+
|
|
93
|
+
from xhtml2pdf import pisa
|
|
94
|
+
|
|
95
|
+
html = """
|
|
96
|
+
<style>
|
|
97
|
+
@page { size: a4; margin: 2cm;
|
|
98
|
+
@frame footer { -pdf-frame-content: footer; bottom: 1cm;
|
|
99
|
+
margin-left: 2cm; margin-right: 2cm; height: 1cm } }
|
|
100
|
+
h1 { color: #204a87 }
|
|
101
|
+
</style>
|
|
102
|
+
<h1>Hello, PDF</h1>
|
|
103
|
+
<p>Written in HTML, laid out by CSS.</p>
|
|
104
|
+
<div id="footer">Page <pdf:pagenumber /> of <pdf:pagecount /></div>
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
with open("hello.pdf", "wb") as output:
|
|
108
|
+
result = pisa.CreatePDF(html, dest=output)
|
|
109
|
+
print("errors:", result.err)
|
|
110
|
+
|
|
111
|
+
Or from the command line:
|
|
112
|
+
|
|
113
|
+
.. code:: bash
|
|
114
|
+
|
|
115
|
+
xhtml2pdf report.html report.pdf
|
|
116
|
+
|
|
117
|
+
What it can do
|
|
118
|
+
==============
|
|
119
|
+
|
|
120
|
+
**Layout**
|
|
121
|
+
|
|
122
|
+
* Flexbox (``display: flex``), including containers that break across
|
|
123
|
+
pages, and ``display: inline-block``.
|
|
124
|
+
* ``position: relative``, ``absolute`` and ``fixed``, with ``z-index``.
|
|
125
|
+
* Block boxes with padding, borders and backgrounds around everything they
|
|
126
|
+
hold, ``border-radius`` on blocks, tables, cells, images and inline
|
|
127
|
+
boxes, and dashed, dotted and double borders.
|
|
128
|
+
* Tables with header rows repeated on every page, ``colspan`` and
|
|
129
|
+
``rowspan``, auto margins and widths, and rows taller than a page cut
|
|
130
|
+
between pages.
|
|
131
|
+
* Word breaking with ``overflow-wrap``, ``page-break-before``/``after``,
|
|
132
|
+
``page-break-inside: avoid`` and keeping a heading with what follows.
|
|
133
|
+
|
|
134
|
+
**CSS**
|
|
135
|
+
|
|
136
|
+
* Selectors up to Level 4: ``:not()``, ``:is()``, ``:where()``, ``:has()``,
|
|
137
|
+
``:nth-child()`` and attribute selectors.
|
|
138
|
+
* Custom properties with ``var()``, ``em``/``rem``/percent units, and colours
|
|
139
|
+
with an alpha channel.
|
|
140
|
+
* ``@font-face`` with TrueType and OpenType fonts, matched per character, so
|
|
141
|
+
a paragraph that mixes scripts finds a font for each of them.
|
|
142
|
+
|
|
143
|
+
**Pages**
|
|
144
|
+
|
|
145
|
+
* ``@page`` sizes and margins, named page templates and left/right pages,
|
|
146
|
+
background images, and frames for headers, footers and columns.
|
|
147
|
+
* Page numbers and page counts, watermarks and backgrounds from an image or
|
|
148
|
+
another PDF.
|
|
149
|
+
|
|
150
|
+
**Navigation**
|
|
151
|
+
|
|
152
|
+
* Tables of contents with dot leaders, more than one per document,
|
|
153
|
+
clickable entries and a PDF outline (bookmarks).
|
|
154
|
+
* Links to any element by ``id``, to other files and to the web.
|
|
155
|
+
|
|
156
|
+
**International text**
|
|
157
|
+
|
|
158
|
+
* Right-to-left documents in Arabic, Hebrew, Persian and Urdu, laid out with
|
|
159
|
+
a pure-Python implementation of the Unicode Bidirectional Algorithm that
|
|
160
|
+
passes the whole of the Unicode conformance suites.
|
|
161
|
+
* Chinese, Japanese and Korean, Cyrillic and Greek, with the document's
|
|
162
|
+
language written to the PDF.
|
|
163
|
+
|
|
164
|
+
**Graphics and PDF features**
|
|
165
|
+
|
|
166
|
+
* SVG images, bar, line and pie charts, and barcodes and QR codes.
|
|
167
|
+
* Fillable form fields, encryption with passwords and permissions, and
|
|
168
|
+
digital signatures (simple and PAdES) through pyHanko.
|
|
169
|
+
|
|
170
|
+
**Safe by default**
|
|
171
|
+
|
|
172
|
+
* A document cannot read local files outside its directory or reach
|
|
173
|
+
internal network addresses, and ``ResourceAccessPolicy.server()`` adds
|
|
174
|
+
limits on size, nesting and time for HTML from untrusted sources. See
|
|
175
|
+
`Security <https://xhtml2pdf.readthedocs.io/en/latest/security.html>`__.
|
|
176
|
+
|
|
177
|
+
Documentation
|
|
178
|
+
=============
|
|
179
|
+
|
|
180
|
+
The documentation is on `Read the Docs <http://xhtml2pdf.readthedocs.io>`__,
|
|
181
|
+
and what changed in each version is in the `Release Notes
|
|
182
|
+
<https://xhtml2pdf.readthedocs.io/en/latest/release-notes.html>`__. Help
|
|
183
|
+
improving it is welcome; a good place to start is
|
|
184
|
+
``docs/source/quickstart.rst``.
|
|
185
|
+
|
|
186
|
+
Installation
|
|
187
|
+
============
|
|
188
|
+
|
|
189
|
+
.. code:: bash
|
|
190
|
+
|
|
191
|
+
pip install xhtml2pdf
|
|
192
|
+
|
|
193
|
+
Python 3.10 and newer is tested and supported. Every mandatory requirement is
|
|
194
|
+
listed in ``pyproject.toml`` and installed with xhtml2pdf.
|
|
195
|
+
|
|
196
|
+
ReportLab needs a rendering backend to turn vector graphics into bitmaps (for
|
|
197
|
+
charts and SVG rasterised into the page). The supported one is `cairo
|
|
198
|
+
<https://cairographics.org/>`__, installed system-wide, for example through
|
|
199
|
+
the OS package manager, together with the ``pycairo`` extra:
|
|
200
|
+
|
|
201
|
+
.. code:: bash
|
|
202
|
+
|
|
203
|
+
pip install xhtml2pdf[pycairo]
|
|
204
|
+
|
|
205
|
+
The ``renderpm`` extra is a deprecated alias for ``pycairo``: ReportLab 5
|
|
206
|
+
removed the C ``RenderPM`` backend. See the `ReportLab installation notes
|
|
207
|
+
<https://docs.reportlab.com/install/open_source_installation/>`__.
|
|
208
|
+
|
|
209
|
+
Development environment
|
|
210
|
+
=======================
|
|
211
|
+
|
|
212
|
+
``make devsetup`` creates ``.venv``, installs xhtml2pdf in editable mode with
|
|
213
|
+
the ``test``, ``docs`` and ``release`` extras and installs the pre-commit
|
|
214
|
+
hooks:
|
|
215
|
+
|
|
216
|
+
.. code:: bash
|
|
217
|
+
|
|
218
|
+
make devsetup
|
|
219
|
+
source .venv/bin/activate
|
|
220
|
+
|
|
221
|
+
Or by hand:
|
|
222
|
+
|
|
223
|
+
.. code:: bash
|
|
224
|
+
|
|
225
|
+
python -m venv .venv
|
|
226
|
+
source .venv/bin/activate
|
|
227
|
+
pip install -e .[test,docs,release]
|
|
228
|
+
|
|
229
|
+
Running tests
|
|
230
|
+
=============
|
|
231
|
+
|
|
232
|
+
.. code:: bash
|
|
233
|
+
|
|
234
|
+
make test # unit tests
|
|
235
|
+
make test-ref # reference renders for testrender
|
|
236
|
+
make test-render # compare the renders against the reference
|
|
237
|
+
make test-browser # compare against a headless browser's rendering
|
|
238
|
+
make test-all # every supported Python and ReportLab, with tox
|
|
239
|
+
|
|
240
|
+
``testrender/`` renders a set of documents and compares the pages; the
|
|
241
|
+
browser comparison scores xhtml2pdf against Chrome on the same markup, so a
|
|
242
|
+
change that moves a layout away from a browser's shows up as a regression.
|
|
243
|
+
``tools/perf`` measures time and memory.
|
|
244
|
+
|
|
245
|
+
Contributing
|
|
246
|
+
============
|
|
247
|
+
|
|
248
|
+
This project is community-led. Ideas, bug reports with a small HTML that
|
|
249
|
+
shows the problem, and pull requests are welcome on GitHub. If xhtml2pdf is
|
|
250
|
+
useful to you, look at the `test coverage
|
|
251
|
+
<https://coveralls.io/github/xhtml2pdf/xhtml2pdf>`__ for parts that are not
|
|
252
|
+
yet tested.
|
|
253
|
+
|
|
254
|
+
You can also support the project on `Patreon
|
|
255
|
+
<https://www.patreon.com/xhtml2pdf>`__ or with Bitcoin:
|
|
256
|
+
``bc1qmr0skzwx5scyvh2ql28f7gfh6l65ua250qv227``.
|
|
257
|
+
|
|
258
|
+
**Big thanks** to everyone who has worked on this project so far and to those
|
|
259
|
+
who help maintain it.
|
|
260
|
+
|
|
261
|
+
Alternatives
|
|
262
|
+
============
|
|
263
|
+
|
|
264
|
+
`WeasyPrint <http://weasyprint.org>`__ covers much of the same ground with a
|
|
265
|
+
different design and set of features.
|
|
266
|
+
|
|
267
|
+
History
|
|
268
|
+
=======
|
|
269
|
+
|
|
270
|
+
These are the major milestones and the maintainers of the project:
|
|
271
|
+
|
|
272
|
+
* 2000-2007 Dirk Holtwick (commercial project of spirito.de)
|
|
273
|
+
* 2007-2010 Dirk Holtwick (project named "pisa", project released as GPL)
|
|
274
|
+
* 2010-2012 Dirk Holtwick (project named "xhtml2pdf", changed license to Apache)
|
|
275
|
+
* 2012-2015 Chris Glass (@chrisglass)
|
|
276
|
+
* 2015-2016 Benjamin Bach (@benjaoming)
|
|
277
|
+
* 2016-2018 Sam Spencer (@LegoStormtroopr)
|
|
278
|
+
* 2018-Current Luis Zarate (@luisza)
|
|
279
|
+
|
|
280
|
+
For more history, see the `Release Notes <https://xhtml2pdf.readthedocs.io/en/latest/release-notes.html>`__.
|
|
281
|
+
|
|
282
|
+
License
|
|
283
|
+
=======
|
|
284
|
+
|
|
285
|
+
Copyright 2010 Dirk Holtwick, holtwick.it
|
|
286
|
+
|
|
287
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
288
|
+
you may not use this file except in compliance with the License.
|
|
289
|
+
You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
|
|
290
|
+
|
|
291
|
+
Unless required by applicable law or agreed to in writing, software
|
|
292
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
293
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
294
|
+
See the License for the specific language governing permissions and
|
|
295
|
+
limitations under the License.
|
|
@@ -50,10 +50,9 @@ dependencies = [
|
|
|
50
50
|
"arabic-reshaper>=3.0.0",
|
|
51
51
|
"html5lib>=1.1",
|
|
52
52
|
"Pillow>=8.1.1",
|
|
53
|
-
"pyHanko>=0.
|
|
54
|
-
"pyhanko-certvalidator>=0.
|
|
53
|
+
"pyHanko>=0.37.0",
|
|
54
|
+
"pyhanko-certvalidator>=0.32.1",
|
|
55
55
|
"pypdf>=3.1.0",
|
|
56
|
-
"python-bidi>=0.5.0",
|
|
57
56
|
"reportlab>=4.4.9,<6",
|
|
58
57
|
"svglib>=1.2.1"
|
|
59
58
|
]
|