weasyprint 65.1__py3-none-any.whl → 67.0__py3-none-any.whl
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.
- weasyprint/__init__.py +17 -7
- weasyprint/__main__.py +21 -10
- weasyprint/anchors.py +4 -4
- weasyprint/css/__init__.py +732 -67
- weasyprint/css/computed_values.py +65 -170
- weasyprint/css/counters.py +1 -1
- weasyprint/css/functions.py +206 -0
- weasyprint/css/html5_ua.css +3 -7
- weasyprint/css/html5_ua_form.css +2 -2
- weasyprint/css/media_queries.py +3 -1
- weasyprint/css/properties.py +6 -2
- weasyprint/css/{utils.py → tokens.py} +306 -397
- weasyprint/css/units.py +91 -0
- weasyprint/css/validation/__init__.py +1 -1
- weasyprint/css/validation/descriptors.py +47 -19
- weasyprint/css/validation/expanders.py +7 -8
- weasyprint/css/validation/properties.py +341 -357
- weasyprint/document.py +20 -19
- weasyprint/draw/__init__.py +56 -63
- weasyprint/draw/border.py +121 -69
- weasyprint/draw/color.py +1 -1
- weasyprint/draw/text.py +60 -41
- weasyprint/formatting_structure/boxes.py +24 -5
- weasyprint/formatting_structure/build.py +33 -45
- weasyprint/images.py +76 -62
- weasyprint/layout/__init__.py +32 -26
- weasyprint/layout/absolute.py +7 -6
- weasyprint/layout/background.py +7 -7
- weasyprint/layout/block.py +195 -152
- weasyprint/layout/column.py +19 -24
- weasyprint/layout/flex.py +54 -26
- weasyprint/layout/float.py +12 -7
- weasyprint/layout/grid.py +284 -90
- weasyprint/layout/inline.py +121 -68
- weasyprint/layout/page.py +45 -12
- weasyprint/layout/percent.py +14 -10
- weasyprint/layout/preferred.py +105 -63
- weasyprint/layout/replaced.py +9 -6
- weasyprint/layout/table.py +16 -9
- weasyprint/pdf/__init__.py +58 -18
- weasyprint/pdf/anchors.py +3 -4
- weasyprint/pdf/fonts.py +126 -69
- weasyprint/pdf/metadata.py +36 -4
- weasyprint/pdf/pdfa.py +19 -3
- weasyprint/pdf/pdfua.py +7 -115
- weasyprint/pdf/pdfx.py +83 -0
- weasyprint/pdf/stream.py +57 -49
- weasyprint/pdf/tags.py +307 -0
- weasyprint/stacking.py +14 -15
- weasyprint/svg/__init__.py +59 -32
- weasyprint/svg/bounding_box.py +4 -2
- weasyprint/svg/defs.py +4 -9
- weasyprint/svg/images.py +11 -3
- weasyprint/svg/text.py +11 -2
- weasyprint/svg/utils.py +15 -8
- weasyprint/text/constants.py +1 -1
- weasyprint/text/ffi.py +4 -3
- weasyprint/text/fonts.py +13 -5
- weasyprint/text/line_break.py +146 -43
- weasyprint/urls.py +41 -13
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/METADATA +5 -6
- weasyprint-67.0.dist-info/RECORD +77 -0
- weasyprint/draw/stack.py +0 -13
- weasyprint-65.1.dist-info/RECORD +0 -74
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/WHEEL +0 -0
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/entry_points.txt +0 -0
- {weasyprint-65.1.dist-info → weasyprint-67.0.dist-info}/licenses/LICENSE +0 -0
weasyprint/__init__.py
CHANGED
|
@@ -15,7 +15,7 @@ import cssselect2
|
|
|
15
15
|
import tinycss2
|
|
16
16
|
import tinyhtml5
|
|
17
17
|
|
|
18
|
-
VERSION = __version__ = '
|
|
18
|
+
VERSION = __version__ = '67.0'
|
|
19
19
|
|
|
20
20
|
#: Default values for command-line and Python API options. See
|
|
21
21
|
#: :func:`__main__.main` to learn more about specific options for
|
|
@@ -39,6 +39,8 @@ VERSION = __version__ = '65.1'
|
|
|
39
39
|
#: A PDF version number.
|
|
40
40
|
#: :param bool pdf_forms:
|
|
41
41
|
#: Whether PDF forms have to be included.
|
|
42
|
+
#: :param bool pdf_tags:
|
|
43
|
+
#: Whether PDF should be tagged for accessibility.
|
|
42
44
|
#: :param bool uncompressed_pdf:
|
|
43
45
|
#: Whether PDF content should be compressed.
|
|
44
46
|
#: :param bool custom_metadata:
|
|
@@ -71,6 +73,7 @@ DEFAULT_OPTIONS = {
|
|
|
71
73
|
'pdf_variant': None,
|
|
72
74
|
'pdf_version': None,
|
|
73
75
|
'pdf_forms': None,
|
|
76
|
+
'pdf_tags': False,
|
|
74
77
|
'uncompressed_pdf': False,
|
|
75
78
|
'custom_metadata': False,
|
|
76
79
|
'presentational_hints': False,
|
|
@@ -195,7 +198,8 @@ class HTML:
|
|
|
195
198
|
def _ph_stylesheets(self):
|
|
196
199
|
return [HTML5_PH_STYLESHEET]
|
|
197
200
|
|
|
198
|
-
def render(self, font_config=None, counter_style=None,
|
|
201
|
+
def render(self, font_config=None, counter_style=None, color_profiles=None,
|
|
202
|
+
**options):
|
|
199
203
|
"""Lay out and paginate the document, but do not (yet) export it.
|
|
200
204
|
|
|
201
205
|
This returns a :class:`document.Document` object which provides
|
|
@@ -219,10 +223,11 @@ class HTML:
|
|
|
219
223
|
new_options = DEFAULT_OPTIONS.copy()
|
|
220
224
|
new_options.update(options)
|
|
221
225
|
options = new_options
|
|
222
|
-
return Document._render(
|
|
226
|
+
return Document._render(
|
|
227
|
+
self, font_config, counter_style, color_profiles, options)
|
|
223
228
|
|
|
224
229
|
def write_pdf(self, target=None, zoom=1, finisher=None,
|
|
225
|
-
font_config=None, counter_style=None, **options):
|
|
230
|
+
font_config=None, counter_style=None, color_profiles=None, **options):
|
|
226
231
|
"""Render the document to a PDF file.
|
|
227
232
|
|
|
228
233
|
This is a shortcut for calling :meth:`render`, then
|
|
@@ -262,7 +267,7 @@ class HTML:
|
|
|
262
267
|
new_options.update(options)
|
|
263
268
|
options = new_options
|
|
264
269
|
return (
|
|
265
|
-
self.render(font_config, counter_style, **options)
|
|
270
|
+
self.render(font_config, counter_style, color_profiles, **options)
|
|
266
271
|
.write_pdf(target, zoom, finisher, **options))
|
|
267
272
|
|
|
268
273
|
|
|
@@ -285,7 +290,8 @@ class CSS:
|
|
|
285
290
|
string=None, encoding=None, base_url=None,
|
|
286
291
|
url_fetcher=default_url_fetcher, _check_mime_type=False,
|
|
287
292
|
media_type='print', font_config=None, counter_style=None,
|
|
288
|
-
matcher=None, page_rules=None
|
|
293
|
+
color_profiles=None, matcher=None, page_rules=None, layers=None,
|
|
294
|
+
layer=None):
|
|
289
295
|
PROGRESS_LOGGER.info(
|
|
290
296
|
'Step 2 - Fetching and parsing CSS - %s',
|
|
291
297
|
filename or url or getattr(file_obj, 'name', 'CSS string'))
|
|
@@ -306,10 +312,13 @@ class CSS:
|
|
|
306
312
|
self.base_url = base_url
|
|
307
313
|
self.matcher = matcher or cssselect2.Matcher()
|
|
308
314
|
self.page_rules = [] if page_rules is None else page_rules
|
|
315
|
+
self.layers = [] if layers is None else layers
|
|
309
316
|
counter_style = {} if counter_style is None else counter_style
|
|
317
|
+
color_profiles = {} if color_profiles is None else color_profiles
|
|
310
318
|
preprocess_stylesheet(
|
|
311
319
|
media_type, base_url, stylesheet, url_fetcher, self.matcher,
|
|
312
|
-
self.page_rules, font_config, counter_style
|
|
320
|
+
self.page_rules, self.layers, font_config, counter_style, color_profiles,
|
|
321
|
+
layer=layer)
|
|
313
322
|
|
|
314
323
|
|
|
315
324
|
class Attachment:
|
|
@@ -426,6 +435,7 @@ def _select_source(guess=None, filename=None, url=None, file_obj=None,
|
|
|
426
435
|
assert string is not None
|
|
427
436
|
yield 'string', string, base_url, None
|
|
428
437
|
|
|
438
|
+
|
|
429
439
|
# Work around circular imports.
|
|
430
440
|
from .css import preprocess_stylesheet # noqa: I001, E402
|
|
431
441
|
from .html import ( # noqa: E402
|
weasyprint/__main__.py
CHANGED
|
@@ -16,16 +16,18 @@ from .urls import default_url_fetcher
|
|
|
16
16
|
|
|
17
17
|
class PrintInfo(argparse.Action):
|
|
18
18
|
def __call__(*_, **__):
|
|
19
|
+
# TODO: ignore check at block-level when available.
|
|
20
|
+
# https://github.com/astral-sh/ruff/issues/3711
|
|
19
21
|
uname = platform.uname()
|
|
20
|
-
print('System:', uname.system)
|
|
21
|
-
print('Machine:', uname.machine)
|
|
22
|
-
print('Version:', uname.version)
|
|
23
|
-
print('Release:', uname.release)
|
|
24
|
-
print()
|
|
25
|
-
print('WeasyPrint version:', __version__)
|
|
26
|
-
print('Python version:', sys.version.split()[0])
|
|
27
|
-
print('Pydyf version:', pydyf.__version__)
|
|
28
|
-
print('Pango version:', pango.pango_version())
|
|
22
|
+
print('System:', uname.system) # noqa: T201
|
|
23
|
+
print('Machine:', uname.machine) # noqa: T201
|
|
24
|
+
print('Version:', uname.version) # noqa: T201
|
|
25
|
+
print('Release:', uname.release) # noqa: T201
|
|
26
|
+
print() # noqa: T201
|
|
27
|
+
print('WeasyPrint version:', __version__) # noqa: T201
|
|
28
|
+
print('Python version:', sys.version.split()[0]) # noqa: T201
|
|
29
|
+
print('Pydyf version:', pydyf.__version__) # noqa: T201
|
|
30
|
+
print('Pango version:', pango.pango_version()) # noqa: T201
|
|
29
31
|
sys.exit()
|
|
30
32
|
|
|
31
33
|
|
|
@@ -89,6 +91,8 @@ PARSER.add_argument(
|
|
|
89
91
|
PARSER.add_argument('--pdf-version', help='PDF version number')
|
|
90
92
|
PARSER.add_argument(
|
|
91
93
|
'--pdf-forms', action='store_true', help='include PDF forms')
|
|
94
|
+
PARSER.add_argument(
|
|
95
|
+
'--pdf-tags', action='store_true', help='tag PDF for accessibility')
|
|
92
96
|
PARSER.add_argument(
|
|
93
97
|
'--uncompressed-pdf', action='store_true',
|
|
94
98
|
help='do not compress PDF content, mainly for debugging purpose')
|
|
@@ -136,7 +140,10 @@ PARSER.add_argument(
|
|
|
136
140
|
help='print system information and exit')
|
|
137
141
|
PARSER.add_argument(
|
|
138
142
|
'-t', '--timeout', type=int,
|
|
139
|
-
help='
|
|
143
|
+
help='set timeout in seconds for HTTP requests')
|
|
144
|
+
PARSER.add_argument(
|
|
145
|
+
'--allowed-protocols', dest='allowed_protocols',
|
|
146
|
+
help='only authorize comma-separated list of protocols for fetching URLs')
|
|
140
147
|
PARSER.set_defaults(**DEFAULT_OPTIONS)
|
|
141
148
|
|
|
142
149
|
|
|
@@ -167,6 +174,10 @@ def main(argv=None, stdout=None, stdin=None, HTML=HTML): # noqa: N803
|
|
|
167
174
|
url_fetcher = default_url_fetcher
|
|
168
175
|
if args.timeout is not None:
|
|
169
176
|
url_fetcher = partial(default_url_fetcher, timeout=args.timeout)
|
|
177
|
+
if args.allowed_protocols is not None:
|
|
178
|
+
protocols = {
|
|
179
|
+
protocol.strip().lower() for protocol in args.allowed_protocols.split(',')}
|
|
180
|
+
url_fetcher = partial(url_fetcher, allowed_protocols=protocols)
|
|
170
181
|
|
|
171
182
|
options = {
|
|
172
183
|
key: value for key, value in vars(args).items() if key in DEFAULT_OPTIONS}
|
weasyprint/anchors.py
CHANGED
|
@@ -43,8 +43,8 @@ def gather_anchors(box, anchors, links, bookmarks, forms, parent_matrix=None,
|
|
|
43
43
|
border_width = box.border_width()
|
|
44
44
|
border_height = box.border_height()
|
|
45
45
|
origin_x, origin_y = box.style['transform_origin']
|
|
46
|
-
offset_x = percentage(origin_x, border_width)
|
|
47
|
-
offset_y = percentage(origin_y, border_height)
|
|
46
|
+
offset_x = percentage(origin_x, box.style, border_width)
|
|
47
|
+
offset_y = percentage(origin_y, box.style, border_height)
|
|
48
48
|
origin_x = box.border_box_x() + offset_x
|
|
49
49
|
origin_y = box.border_box_y() + offset_y
|
|
50
50
|
|
|
@@ -58,8 +58,8 @@ def gather_anchors(box, anchors, links, bookmarks, forms, parent_matrix=None,
|
|
|
58
58
|
b = math.sin(args)
|
|
59
59
|
c = -b
|
|
60
60
|
elif name == 'translate':
|
|
61
|
-
e = percentage(args[0], border_width)
|
|
62
|
-
f = percentage(args[1], border_height)
|
|
61
|
+
e = percentage(args[0], box.style, border_width)
|
|
62
|
+
f = percentage(args[1], box.style, border_height)
|
|
63
63
|
elif name == 'skew':
|
|
64
64
|
b, c = math.tan(args[1]), math.tan(args[0])
|
|
65
65
|
else:
|