weasyprint 68.0__py3-none-any.whl → 68.1__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 CHANGED
@@ -14,7 +14,7 @@ import cssselect2
14
14
  import tinycss2
15
15
  import tinyhtml5
16
16
 
17
- VERSION = __version__ = '68.0'
17
+ VERSION = __version__ = '68.1'
18
18
 
19
19
  #: Default values for command-line and Python API rendering options. See
20
20
  #: :func:`__main__.main` to learn more about specific options for
@@ -779,7 +779,6 @@ def resolve_math(token, computed=None, property_name=None, refer_to=None):
779
779
  return
780
780
 
781
781
  args = []
782
- original_token = token
783
782
  function = Function(token)
784
783
  if function.name is None:
785
784
  return
@@ -795,7 +794,7 @@ def resolve_math(token, computed=None, property_name=None, refer_to=None):
795
794
  if function.name == 'calc':
796
795
  result = _resolve_calc_sum(computed, args[0], property_name, refer_to)
797
796
  if result is None:
798
- return original_token
797
+ return
799
798
  else:
800
799
  return tokenize(result)
801
800
 
@@ -1194,10 +1193,10 @@ class ComputedStyle(dict):
1194
1193
  try:
1195
1194
  token = resolve_math(function, self, key)
1196
1195
  except PercentageInMath:
1197
- token = None
1198
- if token is None:
1199
1196
  solved_tokens.append(function)
1200
1197
  else:
1198
+ if token is None:
1199
+ raise Exception
1201
1200
  solved_tokens.append(token)
1202
1201
  original_key = key.replace('_', '-')
1203
1202
  value = validate_non_shorthand(solved_tokens, original_key)[0][1]
weasyprint/draw/text.py CHANGED
@@ -17,6 +17,8 @@ from .color import get_color
17
17
 
18
18
  def draw_text(stream, textbox, offset_x, text_overflow, block_ellipsis):
19
19
  """Draw a textbox to a pydyf stream."""
20
+ from ..layout.percent import percentage
21
+
20
22
  # Pango crashes with font-size: 0.
21
23
  assert textbox.style['font_size']
22
24
 
@@ -30,11 +32,10 @@ def draw_text(stream, textbox, offset_x, text_overflow, block_ellipsis):
30
32
  if 'underline' in text_decoration_values or 'overline' in text_decoration_values:
31
33
  if textbox.style['text_decoration_thickness'] in ('auto', 'from-font'):
32
34
  thickness = textbox.pango_layout.underline_thickness
33
- elif textbox.style['text_decoration_thickness'].unit == '%':
34
- ratio = textbox.style['text_decoration_thickness'].value / 100
35
- thickness = textbox.style['font_size'] * ratio
36
35
  else:
37
- thickness = textbox.style['text_decoration_thickness'].value
36
+ thickness = percentage(
37
+ textbox.style['text_decoration_thickness'], textbox.style,
38
+ textbox.style['font_size'])
38
39
  if 'overline' in text_decoration_values:
39
40
  offset_y = (
40
41
  textbox.baseline - textbox.pango_layout.ascent + thickness / 2)
@@ -44,11 +45,10 @@ def draw_text(stream, textbox, offset_x, text_overflow, block_ellipsis):
44
45
  if 'underline' in text_decoration_values:
45
46
  if textbox.style['text_underline_offset'] == 'auto':
46
47
  underline_offset = - textbox.pango_layout.underline_position
47
- elif textbox.style['text_underline_offset'].unit == '%':
48
- ratio = textbox.style['text_underline_offset'].value / 100
49
- underline_offset = textbox.style['font_size'] * ratio
50
48
  else:
51
- underline_offset = textbox.style['text_underline_offset'].value
49
+ underline_offset = percentage(
50
+ textbox.style['text_underline_offset'], textbox.style,
51
+ textbox.style['font_size'])
52
52
  offset_y = textbox.baseline + underline_offset + thickness / 2
53
53
  draw_text_decoration(
54
54
  stream, textbox, offset_x, offset_y, thickness,
@@ -301,7 +301,7 @@ def _out_of_flow_layout(context, box, index, child, new_children,
301
301
  return stop, resume_at, new_child, out_of_flow_resume_at
302
302
 
303
303
 
304
- def _break_line(context, box, line, new_children, next_lines, page_is_empty, index,
304
+ def _break_line(context, box, line, new_children, needed, page_is_empty, index,
305
305
  skip_stack, resume_at, absolute_boxes, fixed_boxes):
306
306
  """Break line where allowed by orphans and widows.
307
307
 
@@ -316,7 +316,6 @@ def _break_line(context, box, line, new_children, next_lines, page_is_empty, ind
316
316
  return True, False, resume_at
317
317
  # How many lines we need on the next page to satisfy widows
318
318
  # -1 for the current line.
319
- needed = max(box.style['widows'] - 1 - next_lines, 0)
320
319
  if needed > over_orphans and not page_is_empty:
321
320
  # Total number of lines < orphans + widows
322
321
  remove_placeholders(context, line.children, absolute_boxes, fixed_boxes)
@@ -377,15 +376,21 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
377
376
  # If we couldn’t break the line before but can break now, first try to
378
377
  # report footnotes and see if we don’t overflow.
379
378
  could_break_before = can_break_now = True
380
- next_lines = len(tuple(lines_iterator))
379
+ needed = box.style['widows'] - 1
380
+ for _ in lines_iterator:
381
+ needed -= 1
382
+ # Don’t iterate over all lines as it can be long.
383
+ if needed == -1:
384
+ break
381
385
  if len(new_children) + 1 < box.style['orphans']:
382
386
  can_break_now = False
383
- elif next_lines < box.style['widows']:
387
+ elif needed >= 0:
384
388
  can_break_now = False
385
389
  if len(new_children) < box.style['orphans']:
386
390
  could_break_before = False
387
- elif next_lines + 1 < box.style['widows']:
391
+ elif needed > 0:
388
392
  could_break_before = False
393
+ needed = max(0, needed)
389
394
  report = not context.in_column and can_break_now and not could_break_before
390
395
  reported_footnotes = 0
391
396
  while report and context.current_page_footnotes:
@@ -397,9 +402,8 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
397
402
  break
398
403
  else:
399
404
  abort, stop, resume_at = _break_line(
400
- context, box, line, new_children, next_lines,
401
- page_is_empty, index, skip_stack, resume_at, absolute_boxes,
402
- fixed_boxes)
405
+ context, box, line, new_children, needed, page_is_empty, index,
406
+ skip_stack, resume_at, absolute_boxes, fixed_boxes)
403
407
 
404
408
  # Revert reported footnotes, as they’ve been reported starting from the last
405
409
  # one.
@@ -414,8 +418,7 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
414
418
  # "When an unforced page break occurs here, both the adjoining
415
419
  # ‘margin-top’ and ‘margin-bottom’ are set to zero."
416
420
  # See issue #115.
417
- elif page_is_empty and context.overflows_page(
418
- bottom_space, new_position_y):
421
+ elif page_is_empty and context.overflows_page(bottom_space, new_position_y):
419
422
  # Remove the top border when a page is empty and the box is
420
423
  # too high to be drawn in one page
421
424
  new_position_y -= box.margin_top
@@ -433,8 +436,7 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
433
436
  overflow = (
434
437
  overflow or
435
438
  context.reported_footnotes or
436
- context.overflows_page(
437
- bottom_space, new_position_y + offset_y))
439
+ context.overflows_page(bottom_space, new_position_y + offset_y))
438
440
  if overflow:
439
441
  context.report_footnote(footnote)
440
442
  # If we've put other content on this page, then we may want
@@ -443,11 +445,15 @@ def _linebox_layout(context, box, index, child, new_children, page_is_empty,
443
445
  # even try.
444
446
  if new_children or not page_is_empty:
445
447
  if footnote.style['footnote_policy'] == 'line':
446
- next_lines = len(tuple(lines_iterator))
448
+ if needed := box.style['widows'] - 1:
449
+ for _ in lines_iterator:
450
+ needed -= 1
451
+ # Don’t iterate over all lines as it can be long.
452
+ if needed == 0:
453
+ break
447
454
  abort, stop, resume_at = _break_line(
448
- context, box, line, new_children,
449
- next_lines, page_is_empty, index,
450
- skip_stack, resume_at, absolute_boxes,
455
+ context, box, line, new_children, needed, page_is_empty,
456
+ index, skip_stack, resume_at, absolute_boxes,
451
457
  fixed_boxes)
452
458
  break_linebox = True
453
459
  break
@@ -109,7 +109,7 @@ def _block_content_width(context, box, function, outer):
109
109
 
110
110
  for value in ('padding_left', 'padding_right'):
111
111
  style_value = box.style[value]
112
- if style_value != 'auto':
112
+ if style_value != 'auto' and not check_math(style_value):
113
113
  if style_value.unit.lower() == 'px':
114
114
  width -= style_value.value
115
115
  else:
@@ -175,7 +175,7 @@ def margin_width(box, width, left=True, right=True):
175
175
  (['margin_right', 'padding_right'] if right else [])
176
176
  ):
177
177
  style_value = box.style[value]
178
- if style_value != 'auto':
178
+ if style_value != 'auto' and not check_math(style_value):
179
179
  if style_value.unit.lower() == 'px':
180
180
  width += style_value.value
181
181
  else:
@@ -263,7 +263,7 @@ def inline_max_content_width(context, box, outer=True, is_line_start=False):
263
263
  def column_group_content_width(context, box):
264
264
  """Return the *-content width for a ``TableColumnGroupBox``."""
265
265
  width = box.style['width']
266
- if width == 'auto' or width.unit == '%':
266
+ if width == 'auto' or check_math(width) or width.unit == '%':
267
267
  width = 0
268
268
  else:
269
269
  assert width.unit.lower() == 'px'
@@ -597,21 +597,22 @@ def table_and_columns_preferred_widths(context, box, outer=True):
597
597
  # Define constrainedness
598
598
  constrainedness = [False for i in range(grid_width)]
599
599
  for i in range(grid_width):
600
- if (column_groups[i] and column_groups[i].style['width'] != 'auto' and
601
- column_groups[i].style['width'].unit != '%'):
602
- constrainedness[i] = True
603
- continue
604
- if (columns[i] and columns[i].style['width'] != 'auto' and
605
- columns[i].style['width'].unit != '%'):
606
- constrainedness[i] = True
607
- continue
608
- for cell in zipped_grid[i]:
609
- if (cell and cell.colspan == 1 and
610
- cell.style['width'] != 'auto' and
611
- not check_math(cell.style['width']) and
612
- cell.style['width'].unit != '%'):
600
+ if column_groups[i]:
601
+ width = column_groups[i].style['width']
602
+ if width != 'auto' and not check_math(width) and width.unit != '%':
613
603
  constrainedness[i] = True
614
- break
604
+ continue
605
+ if columns[i]:
606
+ width = columns[i].style['width']
607
+ if width != 'auto' and not check_math(width) and width.unit != '%':
608
+ constrainedness[i] = True
609
+ continue
610
+ for cell in zipped_grid[i]:
611
+ if cell and cell.colspan == 1:
612
+ width = cell.style['width']
613
+ if width != 'auto' and not check_math(width) and width.unit != '%':
614
+ constrainedness[i] = True
615
+ break
615
616
 
616
617
  intrinsic_percentages = [
617
618
  min(percentage, 100 - sum(intrinsic_percentages[:i]))
@@ -679,7 +680,8 @@ def table_and_columns_preferred_widths(context, box, outer=True):
679
680
  sum(max_content_widths), large_percentage_contribution,
680
681
  *small_percentage_contributions]))
681
682
 
682
- if table.style['width'] != 'auto' and table.style['width'].unit.lower() == 'px':
683
+ width = table.style['width']
684
+ if width != 'auto' and not check_math(width) and width.unit.lower() == 'px':
683
685
  # "percentages on the following properties are treated instead as
684
686
  # though they were the following: width: auto"
685
687
  # https://dbaron.org/css/intrinsic/#outer-intrinsic
@@ -714,12 +716,16 @@ def replaced_min_content_width(box, outer=True):
714
716
  width = box.style['width']
715
717
  if width == 'auto':
716
718
  height = box.style['height']
717
- if height == 'auto' or height.unit == '%':
719
+ if height == 'auto' or check_math(height) or height.unit == '%':
718
720
  height = 'auto'
719
721
  else:
720
722
  assert height.unit.lower() == 'px'
721
723
  height = height.value
722
- if box.style['max_width'] != 'auto' and box.style['max_width'].unit == '%':
724
+ unknown_max_width = (
725
+ box.style['max_width'] != 'auto' and
726
+ not check_math(box.style['max_width']) and
727
+ box.style['max_width'].unit == '%')
728
+ if unknown_max_width:
723
729
  # See https://drafts.csswg.org/css-sizing/#intrinsic-contribution
724
730
  width = 0
725
731
  else:
@@ -730,7 +736,7 @@ def replaced_min_content_width(box, outer=True):
730
736
  width, _ = default_image_sizing(
731
737
  intrinsic_width, intrinsic_height, intrinsic_ratio, 'auto',
732
738
  height, default_width=0, default_height=0)
733
- elif box.style['width'].unit == '%':
739
+ elif check_math(box.style['width']) or box.style['width'].unit == '%':
734
740
  # See https://drafts.csswg.org/css-sizing/#intrinsic-contribution
735
741
  width = 0
736
742
  else:
@@ -744,7 +750,7 @@ def replaced_max_content_width(box, outer=True):
744
750
  width = box.style['width']
745
751
  if width == 'auto':
746
752
  height = box.style['height']
747
- if height == 'auto' or height.unit == '%':
753
+ if height == 'auto' or check_math(height) or height.unit == '%':
748
754
  height = 'auto'
749
755
  else:
750
756
  assert height.unit.lower() == 'px'
@@ -756,7 +762,7 @@ def replaced_max_content_width(box, outer=True):
756
762
  width, _ = default_image_sizing(
757
763
  intrinsic_width, intrinsic_height, intrinsic_ratio, 'auto', height,
758
764
  default_width=300, default_height=150)
759
- elif box.style['width'].unit == '%':
765
+ elif check_math(box.style['width']) or box.style['width'].unit == '%':
760
766
  # See https://drafts.csswg.org/css-sizing/#intrinsic-contribution
761
767
  width = 0
762
768
  else:
weasyprint/pdf/stream.py CHANGED
@@ -201,6 +201,8 @@ class Stream(pydyf.Stream):
201
201
  'Group': pydyf.Dictionary({
202
202
  'Type': '/Group',
203
203
  'S': '/Transparency',
204
+ 'I': 'true',
205
+ 'CS': '/DeviceRGB',
204
206
  }),
205
207
  })
206
208
  group = self.clone(resources=resources, extra=extra)
@@ -9,7 +9,7 @@ from cssselect2 import ElementWrapper
9
9
 
10
10
  from ..urls import get_url_attribute
11
11
  from .css import parse_declarations, parse_stylesheets
12
- from .defs import apply_filters, clip_path, draw_gradient_or_pattern, paint_mask, use
12
+ from .defs import apply_filters, draw_gradient_or_pattern, paint_mask, use
13
13
  from .images import image, svg
14
14
  from .path import path
15
15
  from .shapes import circle, ellipse, line, polygon, polyline, rect
@@ -24,7 +24,6 @@ from .utils import ( # isort:skip
24
24
  TAGS = {
25
25
  'a': text,
26
26
  'circle': circle,
27
- 'clipPath': clip_path,
28
27
  'ellipse': ellipse,
29
28
  'image': image,
30
29
  'line': line,
weasyprint/svg/defs.py CHANGED
@@ -517,9 +517,3 @@ def paint_mask(svg, node, mask, font_size):
517
517
  svg.stream = svg.stream.set_alpha_state(x, y, width, height)
518
518
  svg.draw_node(mask, font_size)
519
519
  svg.stream = svg_stream
520
-
521
-
522
- def clip_path(svg, node, font_size):
523
- """Store a clip path definition."""
524
- if 'id' in node.attrib:
525
- svg.paths[node.attrib['id']] = node
weasyprint/svg/text.py CHANGED
@@ -141,7 +141,7 @@ def text(svg, node, font_size):
141
141
  svg.cursor_d_position[1] = 0
142
142
  svg.cursor_d_position[0] += dx or 0
143
143
  svg.cursor_d_position[1] += dy or 0
144
- layout, _, _, width, height, _ = split_first_line(
144
+ layout, _, _, width, height, baseline = split_first_line(
145
145
  letter, style, svg.context, inf, 0)
146
146
  x = svg.cursor_position[0] if x is None else x
147
147
  y = svg.cursor_position[1] if y is None else y
@@ -154,8 +154,9 @@ def text(svg, node, font_size):
154
154
  y_position = y + svg.cursor_d_position[1] + y_align
155
155
  angle = last_r if r is None else r
156
156
  points = (
157
- (x_position, y_position),
158
- (x_position + width, y_position - height))
157
+ (x_position, y_position - baseline),
158
+ (x_position + width, y_position - baseline + height))
159
+ # TODO: Use ink extents instead of logical from line_break.line_size().
159
160
  node.text_bounding_box = extend_bounding_box(
160
161
  node.text_bounding_box, points)
161
162
 
@@ -256,6 +256,8 @@ def split_first_line(text, style, context, max_width, justification_spacing,
256
256
  ``baseline``: baseline in pixels of the first line
257
257
 
258
258
  """
259
+ from ..layout.percent import percentage
260
+
259
261
  # See https://www.w3.org/TR/css-text-3/#white-space-property
260
262
  text_wrap = style['white_space'] in ('normal', 'pre-wrap', 'pre-line')
261
263
  space_collapse = style['white_space'] in ('normal', 'nowrap', 'pre-line')
@@ -392,11 +394,8 @@ def split_first_line(text, style, context, max_width, justification_spacing,
392
394
  # This word is long enough.
393
395
  first_line_width, _ = line_size(first_line, style)
394
396
  space = max_width - first_line_width
395
- if style['hyphenate_limit_zone'].unit == '%':
396
- limit_zone = (
397
- max_width * style['hyphenate_limit_zone'].value / 100)
398
- else:
399
- limit_zone = style['hyphenate_limit_zone'].value
397
+ limit_zone = percentage(
398
+ style['hyphenate_limit_zone'], style, max_width)
400
399
  if space > limit_zone or space < 0:
401
400
  # Available space is worth the try, or the line is even too long
402
401
  # to fit: try to hyphenate.
weasyprint/urls.py CHANGED
@@ -330,17 +330,18 @@ class URLFetcher(request.OpenerDirector):
330
330
 
331
331
  """
332
332
  # Discard URLs with no or invalid protocol.
333
- if not UNICODE_SCHEME_RE.match(url): # pragma: no cover
333
+ if not (match := UNICODE_SCHEME_RE.match(url)): # pragma: no cover
334
334
  raise ValueError(f'Not an absolute URI: {url}')
335
+ scheme = match[1].lower()
335
336
 
336
337
  # Discard URLs with forbidden protocol.
337
338
  if self._allowed_protocols is not None:
338
- if url.split('://', 1)[0].lower() not in self._allowed_protocols:
339
+ if scheme not in self._allowed_protocols:
339
340
  raise ValueError(f'URI uses disallowed protocol: {url}')
340
341
 
341
342
  # Remove query and fragment parts from file URLs.
342
343
  # See https://bugs.python.org/issue34702.
343
- if url.lower().startswith('file://'):
344
+ if scheme == 'file':
344
345
  url = url.split('?')[0]
345
346
 
346
347
  # Transform Unicode IRI to ASCII URI.
@@ -385,7 +386,7 @@ class URLFetcherResponse:
385
386
  :param body: The body of the HTTP response.
386
387
  :type headers: dict or email.message.EmailMessage
387
388
  :param headers: The headers of the HTTP response.
388
- :param str status: The status of the HTTP response.
389
+ :param int status: The status of the HTTP response.
389
390
 
390
391
  Has the same interface as :class:`urllib.response.addinfourl`.
391
392
 
@@ -395,7 +396,7 @@ class URLFetcherResponse:
395
396
  is used elsewhere, the file object has to be closed manually.
396
397
 
397
398
  """
398
- def __init__(self, url, body=None, headers=None, status='200 OK', **kwargs):
399
+ def __init__(self, url, body=None, headers=None, status=200, **kwargs):
399
400
  self.url = url
400
401
  self.status = status
401
402
 
@@ -404,7 +405,10 @@ class URLFetcherResponse:
404
405
  else:
405
406
  self.headers = EmailMessage()
406
407
  for key, value in (headers or {}).items():
407
- self.headers[key] = value
408
+ try:
409
+ self.headers[key] = value
410
+ except ValueError:
411
+ pass # Ignore forbidden duplicated headers.
408
412
 
409
413
  if hasattr(body, 'read'):
410
414
  self._file_obj = body
@@ -440,6 +444,19 @@ class URLFetcherResponse:
440
444
  def charset(self):
441
445
  return self.headers.get_param('charset')
442
446
 
447
+ def geturl(self):
448
+ return self.url
449
+
450
+ def info(self):
451
+ return self.headers
452
+
453
+ @property
454
+ def code(self):
455
+ return self.status
456
+
457
+ def getcode(self):
458
+ return self.status
459
+
443
460
 
444
461
  @contextlib.contextmanager
445
462
  def fetch(url_fetcher, url):
@@ -467,7 +484,7 @@ def fetch(url_fetcher, url):
467
484
  resource['body'] = resource.get('file_obj', resource.get('string'))
468
485
  content_type = resource.get('mime_type', 'application/octet-stream')
469
486
  if charset := resource.get('encoding'):
470
- content_type += f';{charset}'
487
+ content_type += f'; charset={charset}'
471
488
  resource['headers'] = {'Content-Type': content_type}
472
489
  resource = URLFetcherResponse(**resource)
473
490
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: weasyprint
3
- Version: 68.0
3
+ Version: 68.1
4
4
  Summary: The Awesome Document Factory
5
5
  Keywords: html,css,pdf,converter
6
6
  Author-email: Simon Sapin <simon.sapin@exyr.org>
@@ -1,4 +1,4 @@
1
- weasyprint/__init__.py,sha256=jrEFcq7TAw6IYcFPYNAvbiTFAQos-QtYmy0ftmPnvEI,14949
1
+ weasyprint/__init__.py,sha256=Z8RQi3arBn0J5Wlpm56inGnfXYuen9NRT2WyNqxS5q8,14949
2
2
  weasyprint/__main__.py,sha256=L6pqmXo68pHGPkXth8obc9DlUHYdc3YXwDG5bCky4Pc,9374
3
3
  weasyprint/anchors.py,sha256=fytc05l3TO4AWuyPJx532RBEbZe8L7UlnbYYJpB-bGA,6472
4
4
  weasyprint/document.py,sha256=W_pmP05WT_bucoU7eTwkYuYMGG6h-19ZpdVZZcbxpAc,13681
@@ -7,8 +7,8 @@ weasyprint/images.py,sha256=nh1RXq7-8M2dzuOX7gLRwmHDm7LVwulTGcgOsgB_Fr8,36372
7
7
  weasyprint/logger.py,sha256=z1q548fX5shfAyLoMLeM9ozWGKgoBTKQsdlTtfRE_9U,1824
8
8
  weasyprint/matrix.py,sha256=v1BPtyn_-S_4TrAUgzOOR-viUXgdqsABKRndCEprkPc,1909
9
9
  weasyprint/stacking.py,sha256=6c6eZ_BxtcYvlEbH6JQdqaKwYBkuaqUwGGSs3OfkpS8,5697
10
- weasyprint/urls.py,sha256=zCiZVkjLKsxL4b0IkYdUQhzXbL6oJQC72HPb0wV9ZNM,17945
11
- weasyprint/css/__init__.py,sha256=799t6zg9ERCYgGJjHB2CnsuvS8BXn2AeYNbdjAdticc,77545
10
+ weasyprint/urls.py,sha256=6ZsVvV5TKHH1lyXvAkeV0qIgMavWKWKVjLvS7aMagRE,18287
11
+ weasyprint/css/__init__.py,sha256=rCwc157BawGI6j1z_ymYmjT-_-0jEUDVw1DYdJPW9OM,77514
12
12
  weasyprint/css/computed_values.py,sha256=WPySY5DFXusCxa7wC5mUv4uzwBi2c7ACMLI3_iHqDnI,24187
13
13
  weasyprint/css/counters.py,sha256=RAUuZGOLZj5oKrZexbkDUYPncTFWzwtT870xTKYkQmI,11374
14
14
  weasyprint/css/functions.py,sha256=PXPZX0EJKI1FL_ydPGLueICMTHPxwiZwQr74vWpEaMY,6779
@@ -27,13 +27,13 @@ weasyprint/css/validation/properties.py,sha256=DYjW8TZl_y_cedVkleY6kTVw6G3nUlDsp
27
27
  weasyprint/draw/__init__.py,sha256=l4q_L6k93tIobB8hHui_PSElstO5MI5FTHCBTISb_ew,22715
28
28
  weasyprint/draw/border.py,sha256=5s-FZyw3MN085cmmAJHp8Yms5gM90j-XzInpwldgPFs,30373
29
29
  weasyprint/draw/color.py,sha256=xoqq6LmkyN1xdubX0Qm-MKy7xijzT3Zd7kF2MSaqZiQ,1449
30
- weasyprint/draw/text.py,sha256=c5kNqiYCILh1W8YgdgZwRi1ogfLOh5ZRzQydWgASxw0,12640
30
+ weasyprint/draw/text.py,sha256=vHzgHNGiTB8TGJw1GOOAVCzj4ZOnREQ2enbRJL0kVzM,12444
31
31
  weasyprint/formatting_structure/boxes.py,sha256=QDX3FRmSY7pG6QjWTuhANlSMrePNRPm1iX5-CJ8tU98,27199
32
32
  weasyprint/formatting_structure/build.py,sha256=j_pKsHxsNt-ErNj-TT12QczQa6RszPOWjDztqzH5yMo,58491
33
33
  weasyprint/layout/__init__.py,sha256=mUlsoqBIamjdIqtINS9W0njkrgn8guyYORu3UCedon0,16767
34
34
  weasyprint/layout/absolute.py,sha256=JA4mjOweZt2h-Hrsa91nHnvzZDnF-gneMpZfcXiTugc,14005
35
35
  weasyprint/layout/background.py,sha256=IfcmSZ-E4_NES-RSeKi5DGbmrloGdu9zVz5zZ87m9gU,10023
36
- weasyprint/layout/block.py,sha256=czlH2egB6a92UeZGrdggiWOXPj50K5IR9UzJ7-y96GY,48691
36
+ weasyprint/layout/block.py,sha256=I5E7-aTPbkEqIHLcm8PJNXCfq32XbDmu6a9jv8czUBA,48990
37
37
  weasyprint/layout/column.py,sha256=g64aPoNZYpPlrma4F1nyrW7_ji5DBYoamA92YrbFHZM,17209
38
38
  weasyprint/layout/flex.py,sha256=KZNFElr2QDT5FYI6JlZGpXxJHYFvMMN8QGylLx98PUs,44148
39
39
  weasyprint/layout/float.py,sha256=5iBDHg1KSexArW1SfbnMShuILzkkEH8DW7n1bdk5OU4,9488
@@ -43,7 +43,7 @@ weasyprint/layout/leader.py,sha256=wklI0aLyTx0VJhqU7D_FxtJpfe7dXswcN-VApAusM-Q,2
43
43
  weasyprint/layout/min_max.py,sha256=JdXJG9ISO_RsfeHua_-3g477a16I-NrnYuwH_tQwq4o,1527
44
44
  weasyprint/layout/page.py,sha256=m4z24NqI6bc08j1GwXsRCpyMkKxC93XE6--QMHUaKxM,41565
45
45
  weasyprint/layout/percent.py,sha256=F2kNcNz7b6to70GwiFFu-oWWpYs011TM021COH7feEc,5829
46
- weasyprint/layout/preferred.py,sha256=UY-Uq00wvFeZtvnA_giljI2X-LgD8VuKH4XLi5ef1VY,34908
46
+ weasyprint/layout/preferred.py,sha256=ZZAc7tbn5Rdl9DjgXgnT4J9sBBljNXvY5qj47HjUXGM,35288
47
47
  weasyprint/layout/replaced.py,sha256=7-foaAPIAVC329QEnUN_1u2U6VTrEbQ0Qx254BlrLCo,11357
48
48
  weasyprint/layout/table.py,sha256=KyFOg9aiMl_wO31_0kQ7WrCVeHtGJY0Ir-hdub2qSSg,47778
49
49
  weasyprint/pdf/__init__.py,sha256=5OG1Tgdyk1XPhcren50OY2S9ZLT4SseIajlEhDl7PSw,14303
@@ -55,23 +55,23 @@ weasyprint/pdf/pdfa.py,sha256=JDKtJ3-v-i2CMWScTbesZi3YQ8C-5PYOheYAYM5Y1iw,4239
55
55
  weasyprint/pdf/pdfua.py,sha256=RrV7qky5Djc_tP5ipdDUDC5BqOi6T_LDZpVy8cyXRGc,486
56
56
  weasyprint/pdf/pdfx.py,sha256=1DB9afper1oZpmoktSxBvRTpUuxHj7TBy3dhXdD2qGc,2629
57
57
  weasyprint/pdf/sRGB2014.icc,sha256=OEuDLeNBIGZ0O1KnXukGtvufuNngnpNvwsQyI4Fcbgo,3024
58
- weasyprint/pdf/stream.py,sha256=ME9S63n_xFJa3fQoIi2kPcpJv5cQiYKWpPdEjqZe7bg,11550
58
+ weasyprint/pdf/stream.py,sha256=7L7EcGhxwDp06VSqgVWVP2ZgpIdJ35LPLE6IAN4sQzQ,11615
59
59
  weasyprint/pdf/tags.py,sha256=914AozTYgFOMpFSP2UtEZCVzsPIKueHWjI9DA77w28M,11789
60
- weasyprint/svg/__init__.py,sha256=1IYQDVPZVW6m28draJKg0kqR_JUnwEBcFfCOiHrAJho,32219
60
+ weasyprint/svg/__init__.py,sha256=96DOr-LUCMiEOL81QbgpnPL96Bw9ItPDMb9AUvxygJU,32181
61
61
  weasyprint/svg/bounding_box.py,sha256=auXs-vD2nvOx3cplHLGXFzy7X_f_IY4hg_IzKlUTXjM,13129
62
62
  weasyprint/svg/css.py,sha256=MohmaDCX6oDIIxJPrn6bn1fKq4la0oPfxvMYrfL5vbI,4871
63
- weasyprint/svg/defs.py,sha256=OzHw-8oejyDojP-jiozgLnlVhq_NyYvbg5DGuZbyMnM,20925
63
+ weasyprint/svg/defs.py,sha256=kkuNKYp9ymb1hK-w45_ClV9iGWULyEGmXhazmAUnXF8,20774
64
64
  weasyprint/svg/images.py,sha256=msVOn7_DgKFVB6Pz25SDLXU22-p7H5y0fJGKBpFDjrc,3333
65
65
  weasyprint/svg/path.py,sha256=Z-T6kbUU3pyHhzVV0JSBgO--XaCGXLsH-cS9iAsITMM,10064
66
66
  weasyprint/svg/shapes.py,sha256=NDo0KMnwrm0hj3BOmfrKjRZo4iJF9o-MeUhZ5avANco,3845
67
- weasyprint/svg/text.py,sha256=vJ2FUquzpnGclA_y1dXu4jImvkGR0NvvnyoVLyHZlk0,6663
67
+ weasyprint/svg/text.py,sha256=RST3ss4HEGxrq87lX6z67T9K55nL5qBntz0dDqH0bfs,6772
68
68
  weasyprint/svg/utils.py,sha256=BEJvyOtxo4tAgLL-RORaEMIBAgmIZzwBNp2YuN1u3NM,7289
69
69
  weasyprint/text/constants.py,sha256=gtC92Hbzci0976gVTct3roVKLcQjNWIQM43zuEBqIuY,14189
70
70
  weasyprint/text/ffi.py,sha256=13hLmV19RiTspKHna_RlZMar6CpTIHwPDPSGV1FmhNc,18418
71
71
  weasyprint/text/fonts.py,sha256=P2Zi7cHwoR4WZsOfm3Ki0lQ3aRYu6YWyFsKvvd0DEqE,17568
72
- weasyprint/text/line_break.py,sha256=0hrm7916GfSFtGf4SLRzB8rp_-iwpi27bVaNI--th0c,28215
73
- weasyprint-68.0.dist-info/entry_points.txt,sha256=wgDp3XXzFywdYgI5vUWMp1zAwx1sZXXH0FTUQbFOq6A,55
74
- weasyprint-68.0.dist-info/licenses/LICENSE,sha256=v9FOzPphAFdUYOaFVWsYM5nUvTNZBOPJUhsBFtIcVNo,1534
75
- weasyprint-68.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
76
- weasyprint-68.0.dist-info/METADATA,sha256=pJpSpO6nIxcLtKWqctgn8OUIx_IswW0QXeu9VaJ4sLM,3709
77
- weasyprint-68.0.dist-info/RECORD,,
72
+ weasyprint/text/line_break.py,sha256=02vHDXwy_yuWSlG19CxDi-sC3rnh8wj6SBY63sskuTM,28091
73
+ weasyprint-68.1.dist-info/entry_points.txt,sha256=wgDp3XXzFywdYgI5vUWMp1zAwx1sZXXH0FTUQbFOq6A,55
74
+ weasyprint-68.1.dist-info/licenses/LICENSE,sha256=v9FOzPphAFdUYOaFVWsYM5nUvTNZBOPJUhsBFtIcVNo,1534
75
+ weasyprint-68.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
76
+ weasyprint-68.1.dist-info/METADATA,sha256=QsG5YIcitase__6kIbSxKZ2KsJYdm-LaIxguuOv9BVE,3709
77
+ weasyprint-68.1.dist-info/RECORD,,