Skip to content

Commit

Permalink
Allow var functions in shorthand properties
Browse files Browse the repository at this point in the history
Related to #1219.
  • Loading branch information
liZe committed Dec 27, 2023
1 parent 583d8d9 commit c641f59
Show file tree
Hide file tree
Showing 3 changed files with 269 additions and 63 deletions.
153 changes: 151 additions & 2 deletions tests/test_variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
from weasyprint.css.properties import KNOWN_PROPERTIES

from .testing_utils import assert_no_logs, render_pages
from .testing_utils import assert_no_logs, capture_logs, render_pages

SIDES = ('top', 'right', 'bottom', 'left')

Expand Down Expand Up @@ -120,7 +120,7 @@ def test_variable_chain_root_missing():


@assert_no_logs
def test_variable_partial_1():
def test_variable_shorthand_margin():
page, = render_pages('''
<style>
html { --var: 10px }
Expand All @@ -137,6 +137,155 @@ def test_variable_partial_1():
assert div.margin_left == 10


@assert_no_logs
def test_variable_shorthand_margin_multiple():
page, = render_pages('''
<style>
html { --var1: 10px; --var2: 20px }
div { margin: var(--var2) 0 0 var(--var1) }
</style>
<div></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.margin_top == 20
assert div.margin_right == 0
assert div.margin_bottom == 0
assert div.margin_left == 10


@assert_no_logs
def test_variable_shorthand_margin_invalid():
with capture_logs() as logs:
page, = render_pages('''
<style>
html { --var: blue }
div { margin: 0 0 0 var(--var) }
</style>
<div></div>
''')
log, = logs
assert 'invalid value' in log
html, = page.children
body, = html.children
div, = body.children
assert div.margin_top == 0
assert div.margin_right == 0
assert div.margin_bottom == 0
assert div.margin_left == 0


@assert_no_logs
def test_variable_shorthand_border():
page, = render_pages('''
<style>
html { --var: 1px solid blue }
div { border: var(--var) }
</style>
<div></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.border_top_width == 1
assert div.border_right_width == 1
assert div.border_bottom_width == 1
assert div.border_left_width == 1


@assert_no_logs
def test_variable_shorthand_border_side():
page, = render_pages('''
<style>
html { --var: 1px solid blue }
div { border-top: var(--var) }
</style>
<div></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.border_top_width == 1
assert div.border_right_width == 0
assert div.border_bottom_width == 0
assert div.border_left_width == 0


@assert_no_logs
def test_variable_shorthand_border_mixed():
page, = render_pages('''
<style>
html { --var: 1px solid }
div { border: blue var(--var) }
</style>
<div></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.border_top_width == 1
assert div.border_right_width == 1
assert div.border_bottom_width == 1
assert div.border_left_width == 1


def test_variable_shorthand_border_mixed_invalid():
with capture_logs() as logs:
page, = render_pages('''
<style>
html { --var: 1px solid blue }
div { border: blue var(--var) }
</style>
<div></div>
''')
# TODO: we should only get one warning here
assert 'multiple color values' in logs[0]
html, = page.children
body, = html.children
div, = body.children
assert div.border_top_width == 0
assert div.border_right_width == 0
assert div.border_bottom_width == 0
assert div.border_left_width == 0


@assert_no_logs
@pytest.mark.parametrize('var, background', (
('blue', 'var(--v)'),
('padding-box url(pattern.png)', 'var(--v)'),
('padding-box url(pattern.png)', 'white var(--v) center'),
('100%', 'url(pattern.png) var(--v) var(--v) / var(--v) var(--v)'),
('left / 100%', 'url(pattern.png) top var(--v) 100%'),
))
def test_variable_shorthand_background(var, background):
page, = render_pages('''
<style>
html { --v: %s }
div { background: %s }
</style>
<div></div>
''' % (var, background))


@pytest.mark.parametrize('var, background', (
('invalid', 'var(--v)'),
('blue', 'var(--v) var(--v)'),
('100%', 'url(pattern.png) var(--v) var(--v) var(--v)'),
))
def test_variable_shorthand_background_invalid(var, background):
with capture_logs() as logs:
page, = render_pages('''
<style>
html { --v: %s }
div { background: %s }
</style>
<div></div>
''' % (var, background))
log, = logs
assert 'invalid value' in log


@assert_no_logs
def test_variable_initial():
page, = render_pages('''
Expand Down
21 changes: 17 additions & 4 deletions weasyprint/css/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
from .computed_values import (
COMPUTER_FUNCTIONS, ZERO_PIXELS, compute_var, resolve_var)
from .properties import INHERITED, INITIAL_NOT_COMPUTED, INITIAL_VALUES
from .utils import check_var_function, get_url, remove_whitespace
from .utils import (
InvalidValues, check_var_function, get_url, remove_whitespace)
from .validation import preprocess_declarations
from .validation.descriptors import preprocess_descriptors
from .validation.expanders import PendingExpander
from .validation.properties import validate_non_shorthand

# Reject anything not in here:
PSEUDO_ELEMENTS = (
Expand Down Expand Up @@ -732,6 +732,8 @@ def __missing__(self, key):
return self[key]

if isinstance(value, PendingExpander):
# Expander with pending values, validate them.
computed = False
solved_tokens = []
for token in value.tokens:
variable = check_var_function(token)
Expand All @@ -743,8 +745,19 @@ def __missing__(self, key):
else:
solved_tokens.append(token)
original_key = key.replace('_', '-')
solved = value.solve(solved_tokens, original_key)
value = validate_non_shorthand(None, original_key, solved)[0][1]
try:
value = value.solve(solved_tokens, original_key)
except InvalidValues:
if key in INHERITED:
# Values in parent_style are already computed.
self[key] = value = parent_style[key]
return value
else:
value = INITIAL_VALUES[key]
if key not in INITIAL_NOT_COMPUTED:
# The value is the same as when computed.
self[key] = value
return value

if not computed and key in COMPUTER_FUNCTIONS:
# Value not computed yet: compute.
Expand Down
Loading

0 comments on commit c641f59

Please sign in to comment.