Skip to content

Commit 238e214

Browse files
committed
Fix URL handling with tinycss2
URLs used to be dedicated tokens in the CSS specification, but it’s now a common function unless its value isn’t quoted. tinycss2 1.1.0 includes this change, and WeasyPrint has to take care of these two different tokens.
1 parent 77dbcb7 commit 238e214

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

weasyprint/css/utils.py

+17-9
Original file line numberDiff line numberDiff line change
@@ -564,12 +564,12 @@ def get_image(token, base_url):
564564
"""Parse an <image> token."""
565565
from ..images import LinearGradient, RadialGradient
566566

567+
parsed_url = get_url(token, base_url)
568+
if parsed_url:
569+
assert parsed_url[0] == 'url'
570+
if parsed_url[1][0] == 'external':
571+
return 'url', parsed_url[1][1]
567572
if token.type != 'function':
568-
parsed_url = get_url(token, base_url)
569-
if parsed_url:
570-
assert parsed_url[0] == 'url'
571-
if parsed_url[1][0] == 'external':
572-
return 'url', parsed_url[1][1]
573573
return
574574
arguments = split_on_comma(remove_whitespace(token.arguments))
575575
name = token.lower_name
@@ -594,16 +594,24 @@ def get_image(token, base_url):
594594
shape, size, position, 'repeating' in name)
595595

596596

597+
def _get_url_tuple(string, base_url):
598+
if string.startswith('#'):
599+
return ('url', ('internal', unquote(string[1:])))
600+
else:
601+
return ('url', ('external', safe_urljoin(base_url, string)))
602+
603+
597604
def get_url(token, base_url):
598605
"""Parse an <url> token."""
599606
if token.type == 'url':
600-
if token.value.startswith('#'):
601-
return ('url', ('internal', unquote(token.value[1:])))
602-
else:
603-
return ('url', ('external', safe_urljoin(base_url, token.value)))
607+
return _get_url_tuple(token.value, base_url)
604608
elif token.type == 'function':
605609
if token.name == 'attr':
606610
return check_attr_function(token, 'url')
611+
elif token.name == 'url' and len(token.arguments) in (1, 2):
612+
# Ignore url modifiers
613+
# See https://drafts.csswg.org/css-values-3/#urls
614+
return _get_url_tuple(token.arguments[0].value, base_url)
607615

608616

609617
def get_quote(token):

weasyprint/css/validation/descriptors.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,9 @@ def pad(tokens, base_url):
300300
values[0] = token.int_value
301301
elif token.type in ('string', 'ident'):
302302
values[1] = ('string', token.value)
303-
elif token.type == 'function':
304-
url = get_url(token, base_url)
305-
if url is not None and url[0] == 'url':
306-
values[1] = ('url', url[1])
303+
url = get_url(token, base_url)
304+
if url is not None and url[0] == 'url':
305+
values[1] = ('url', url[1])
307306

308307
if None not in values:
309308
return tuple(values)

weasyprint/css/validation/properties.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,12 @@ def background_image(token, base_url):
179179
@single_token
180180
def list_style_image(token, base_url):
181181
"""``list-style-image`` property validation."""
182-
if token.type != 'function':
183-
if get_keyword(token) == 'none':
184-
return 'none', None
185-
parsed_url = get_url(token, base_url)
186-
if parsed_url:
187-
if parsed_url[0] == 'url' and parsed_url[1][0] == 'external':
188-
return 'url', parsed_url[1][1]
182+
if get_keyword(token) == 'none':
183+
return 'none', None
184+
parsed_url = get_url(token, base_url)
185+
if parsed_url:
186+
if parsed_url[0] == 'url' and parsed_url[1][0] == 'external':
187+
return 'url', parsed_url[1][1]
189188

190189

191190
@property()

0 commit comments

Comments
 (0)