1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-04 07:57:52 +03:00
WeasyPrint/tests/test_counters.py
2021-04-19 17:15:53 +02:00

624 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
weasyprint.tests.test_counters
------------------------------
Test CSS counters.
"""
import pytest
from weasyprint import HTML
from .testing_utils import assert_no_logs, assert_tree, parse_all, render_pages
@assert_no_logs
def test_counters_1():
assert_tree(parse_all('''
<style>
p { counter-increment: p 2 }
p:before { content: counter(p); }
p:nth-child(1) { counter-increment: none; }
p:nth-child(2) { counter-increment: p; }
</style>
<p></p>
<p></p>
<p></p>
<p style="counter-reset: p 117 p"></p>
<p></p>
<p></p>
<p style="counter-reset: p -13"></p>
<p></p>
<p></p>
<p style="counter-reset: p 42"></p>
<p></p>
<p></p>'''), [
('p', 'Block', [
('p', 'Line', [
('p::before', 'Inline', [
('p::before', 'Text', counter)])])])
for counter in '0 1 3 2 4 6 -11 -9 -7 44 46 48'.split()])
@assert_no_logs
def test_counters_2():
assert_tree(parse_all('''
<ol style="list-style-position: inside">
<li></li>
<li></li>
<li></li>
<li><ol>
<li></li>
<li style="counter-increment: none"></li>
<li></li>
</ol></li>
<li></li>
</ol>'''), [
('ol', 'Block', [
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '1. ')])])]),
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '2. ')])])]),
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '3. ')])])]),
('li', 'Block', [
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '4. ')])])]),
('ol', 'Block', [
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '1. ')])])]),
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '1. ')])])]),
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '2. ')])])])])]),
('li', 'Block', [
('li', 'Line', [
('li::marker', 'Inline', [
('li::marker', 'Text', '5. ')])])])])])
@assert_no_logs
def test_counters_3():
assert_tree(parse_all('''
<style>
p { display: list-item; list-style: inside decimal }
</style>
<div>
<p></p>
<p></p>
<p style="counter-reset: list-item 7 list-item -56"></p>
</div>
<p></p>'''), [
('div', 'Block', [
('p', 'Block', [
('p', 'Line', [
('p::marker', 'Inline', [
('p::marker', 'Text', '1. ')])])]),
('p', 'Block', [
('p', 'Line', [
('p::marker', 'Inline', [
('p::marker', 'Text', '2. ')])])]),
('p', 'Block', [
('p', 'Line', [
('p::marker', 'Inline', [
('p::marker', 'Text', '-55. ')])])])]),
('p', 'Block', [
('p', 'Line', [
('p::marker', 'Inline', [
('p::marker', 'Text', '1. ')])])])])
@assert_no_logs
def test_counters_4():
assert_tree(parse_all('''
<style>
section:before { counter-reset: h; content: '' }
h1:before { counter-increment: h; content: counters(h, '.') }
</style>
<body>
<section><h1></h1>
<h1></h1>
<section><h1></h1>
<h1></h1>
</section>
<h1></h1>
</section>
</body>'''), [
('section', 'Block', [
('section', 'Block', [
('section', 'Line', [
('section::before', 'Inline', [])])]),
('h1', 'Block', [
('h1', 'Line', [
('h1::before', 'Inline', [
('h1::before', 'Text', '1')])])]),
('h1', 'Block', [
('h1', 'Line', [
('h1::before', 'Inline', [
('h1::before', 'Text', '2')])])]),
('section', 'Block', [
('section', 'Block', [
('section', 'Line', [
('section::before', 'Inline', [])])]),
('h1', 'Block', [
('h1', 'Line', [
('h1::before', 'Inline', [
('h1::before', 'Text', '2.1')])])]),
('h1', 'Block', [
('h1', 'Line', [
('h1::before', 'Inline', [
('h1::before', 'Text', '2.2')])])])]),
('h1', 'Block', [
('h1', 'Line', [
('h1::before', 'Inline', [
('h1::before', 'Text', '3')])])])])])
@assert_no_logs
def test_counters_5():
assert_tree(parse_all('''
<style>
p:before { content: counter(c) }
</style>
<div>
<span style="counter-reset: c">
Scope created now, deleted after the div
</span>
</div>
<p></p>'''), [
('div', 'Block', [
('div', 'Line', [
('span', 'Inline', [
('span', 'Text',
'Scope created now, deleted after the div ')])])]),
('p', 'Block', [
('p', 'Line', [
('p::before', 'Inline', [
('p::before', 'Text', '0')])])])])
@assert_no_logs
def test_counters_6():
# counter-increment may interfere with display: list-item
assert_tree(parse_all('''
<p style="counter-increment: c;
display: list-item; list-style: inside decimal">'''), [
('p', 'Block', [
('p', 'Line', [
('p::marker', 'Inline', [
('p::marker', 'Text', '0. ')])])])])
@assert_no_logs
def test_counters_7():
# Test that counters are case-sensitive
# See https://github.com/Kozea/WeasyPrint/pull/827
assert_tree(parse_all('''
<style>
p { counter-increment: p 2 }
p:before { content: counter(p) '.' counter(P); }
</style>
<p></p>
<p style="counter-increment: P 3"></p>
<p></p>'''), [
('p', 'Block', [
('p', 'Line', [
('p::before', 'Inline', [
('p::before', 'Text', counter)])])])
for counter in '2.0 2.3 4.3'.split()])
@assert_no_logs
def test_counters_8():
assert_tree(parse_all('''
<style>
p:before { content: 'a'; display: list-item }
</style>
<p></p>
<p></p>'''), 2 * [
('p', 'Block', [
('p::before', 'Block', [
('p::marker', 'Block', [
('p::marker', 'Line', [
('p::marker', 'Text', '')])]),
('p::before', 'Block', [
('p::before', 'Line', [
('p::before', 'Text', 'a')])])])])])
@assert_no_logs
def test_counter_styles_1():
assert_tree(parse_all('''
<style>
body { --var: 'Counter'; counter-reset: p -12 }
p { counter-increment: p }
p:nth-child(1):before { content: '-' counter(p, none) '-'; }
p:nth-child(2):before { content: counter(p, disc); }
p:nth-child(3):before { content: counter(p, circle); }
p:nth-child(4):before { content: counter(p, square); }
p:nth-child(5):before { content: counter(p); }
p:nth-child(6):before { content: var(--var) ':' counter(p); }
p:nth-child(7):before { content: counter(p) ':' var(--var); }
</style>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
'''), [
('p', 'Block', [
('p', 'Line', [
('p::before', 'Inline', [
('p::before', 'Text', counter)])])])
for counter in '-- • ◦ ▪ -7 Counter:-6 -5:Counter'.split()])
@assert_no_logs
def test_counter_styles_2():
assert_tree(parse_all('''
<style>
p { counter-increment: p }
p::before { content: counter(p, decimal-leading-zero); }
</style>
<p style="counter-reset: p -1987"></p>
<p></p>
<p style="counter-reset: p -12"></p>
<p></p>
<p></p>
<p></p>
<p style="counter-reset: p -2"></p>
<p></p>
<p></p>
<p></p>
<p style="counter-reset: p 8"></p>
<p></p>
<p></p>
<p style="counter-reset: p 98"></p>
<p></p>
<p></p>
<p style="counter-reset: p 4134"></p>
<p></p>
'''), [
('p', 'Block', [
('p', 'Line', [
('p::before', 'Inline', [
('p::before', 'Text', counter)])])])
for counter in '''-1986 -1985 -11 -10 -9 -8 -1 00 01 02 09 10 11
99 100 101 4135 4136'''.split()])
@assert_no_logs
def test_counter_styles_3():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'decimal-leading-zero') for value in [
-1986, -1985,
-11, -10, -9, -8,
-1, 0, 1, 2,
9, 10, 11,
99, 100, 101,
4135, 4136
]] == '''
-1986 -1985 -11 -10 -9 -8 -1 00 01 02 09 10 11
99 100 101 4135 4136
'''.split()
@assert_no_logs
def test_counter_styles_4():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'lower-roman') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
49, 50,
389, 390,
3489, 3490, 3491,
4999, 5000, 5001
]] == '''
-1986 -1985 -1 0 i ii iii iv v vi vii viii ix x xi xii
xlix l ccclxxxix cccxc mmmcdlxxxix mmmcdxc mmmcdxci
4999 5000 5001
'''.split()
@assert_no_logs
def test_counter_styles_5():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'upper-roman') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
49, 50,
389, 390,
3489, 3490, 3491,
4999, 5000, 5001
]] == '''
-1986 -1985 -1 0 I II III IV V VI VII VIII IX X XI XII
XLIX L CCCLXXXIX CCCXC MMMCDLXXXIX MMMCDXC MMMCDXCI
4999 5000 5001
'''.split()
@assert_no_logs
def test_counter_styles_6():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'lower-alpha') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4,
25, 26, 27, 28, 29,
2002, 2003
]] == '''
-1986 -1985 -1 0 a b c d y z aa ab ac bxz bya
'''.split()
@assert_no_logs
def test_counter_styles_7():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'upper-alpha') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4,
25, 26, 27, 28, 29,
2002, 2003
]] == '''
-1986 -1985 -1 0 A B C D Y Z AA AB AC BXZ BYA
'''.split()
@assert_no_logs
def test_counter_styles_8():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'lower-latin') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4,
25, 26, 27, 28, 29,
2002, 2003
]] == '''
-1986 -1985 -1 0 a b c d y z aa ab ac bxz bya
'''.split()
@assert_no_logs
def test_counter_styles_9():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'upper-latin') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4,
25, 26, 27, 28, 29,
2002, 2003
]] == '''
-1986 -1985 -1 0 A B C D Y Z AA AB AC BXZ BYA
'''.split()
@assert_no_logs
def test_counter_styles_10():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'georgian') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
20, 30, 40, 50, 60, 70, 80, 90, 100,
200, 300, 400, 500, 600, 700, 800, 900, 1000,
2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000,
19999, 20000, 20001
]] == '''
-1986 -1985 -1 0 ა
ბ გ დ ე ვ ზ ჱ თ ი ია იბ
კ ლ მ ნ ჲ ო პ ჟ რ
ს ტ ჳ ფ ქ ღ შ ჩ
ც ძ წ ჭ ხ ჴ ჯ ჰ ჵ
ჵჰშჟთ 20000 20001
'''.split()
@assert_no_logs
def test_counter_styles_11():
render = HTML(string='')._ua_counter_style()[0].render_value
assert [render(value, 'armenian') for value in [
-1986, -1985,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
20, 30, 40, 50, 60, 70, 80, 90, 100,
200, 300, 400, 500, 600, 700, 800, 900, 1000,
2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000,
9999, 10000, 10001
]] == '''
-1986 -1985 -1 0 Ա
Բ Գ Դ Ե Զ Է Ը Թ Ժ ԺԱ ԺԲ
Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ
Մ Յ Ն Շ Ո Չ Պ Ջ Ռ
Ս Վ Տ Ր Ց Ւ Փ Ք
ՔՋՂԹ 10000 10001
'''.split()
@assert_no_logs
@pytest.mark.parametrize('arguments, values', (
('cyclic "a" "b" "c"', ('a ', 'b ', 'c ', 'a ')),
('symbolic "a" "b"', ('a ', 'b ', 'aa ', 'bb ')),
('"a" "b"', ('a ', 'b ', 'aa ', 'bb ')),
('alphabetic "a" "b"', ('a ', 'b ', 'aa ', 'ab ')),
('fixed "a" "b"', ('a ', 'b ', '3 ', '4 ')),
('numeric "0" "1" "2"', ('1 ', '2 ', '10 ', '11 ')),
))
def test_counter_symbols(arguments, values):
page, = render_pages('''
<style>
ol { list-style-type: symbols(%s) }
</style>
<ol>
<li>abc</li>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ol>
''' % arguments)
html, = page.children
body, = html.children
ol, = body.children
li_1, li_2, li_3, li_4 = ol.children
assert li_1.children[0].children[0].children[0].text == values[0]
assert li_2.children[0].children[0].children[0].text == values[1]
assert li_3.children[0].children[0].children[0].text == values[2]
assert li_4.children[0].children[0].children[0].text == values[3]
@assert_no_logs
@pytest.mark.parametrize('style_type, values', (
('decimal', ('1. ', '2. ', '3. ', '4. ')),
('"/"', ('/', '/', '/', '/')),
))
def test_list_style_types(style_type, values):
page, = render_pages('''
<style>
ol { list-style-type: %s }
</style>
<ol>
<li>abc</li>
<li>abc</li>
<li>abc</li>
<li>abc</li>
</ol>
''' % style_type)
html, = page.children
body, = html.children
ol, = body.children
li_1, li_2, li_3, li_4 = ol.children
assert li_1.children[0].children[0].children[0].text == values[0]
assert li_2.children[0].children[0].children[0].text == values[1]
assert li_3.children[0].children[0].children[0].text == values[2]
assert li_4.children[0].children[0].children[0].text == values[3]
def test_counter_set():
page, = render_pages('''
<style>
body { counter-reset: h2 0 h3 4; font-size: 1px }
article { counter-reset: h2 2 }
h1 { counter-increment: h1 }
h1::before { content: counter(h1) }
h2 { counter-increment: h2; counter-set: h3 3 }
h2::before { content: counter(h2) }
h3 { counter-increment: h3 }
h3::before { content: counter(h3) }
</style>
<article>
<h1></h1>
</article>
<article>
<h2></h2>
<h3></h3>
</article>
<article>
<h3></h3>
</article>
<article>
<h2></h2>
</article>
<article>
<h3></h3>
<h3></h3>
</article>
<article>
<h1></h1>
<h2></h2>
<h3></h3>
</article>
''')
html, = page.children
body, = html.children
art_1, art_2, art_3, art_4, art_5, art_6 = body.children
h1, = art_1.children
assert h1.children[0].children[0].children[0].text == '1'
h2, h3, = art_2.children
assert h2.children[0].children[0].children[0].text == '3'
assert h3.children[0].children[0].children[0].text == '4'
h3, = art_3.children
assert h3.children[0].children[0].children[0].text == '5'
h2, = art_4.children
assert h2.children[0].children[0].children[0].text == '3'
h3_1, h3_2 = art_5.children
assert h3_1.children[0].children[0].children[0].text == '4'
assert h3_2.children[0].children[0].children[0].text == '5'
h1, h2, h3 = art_6.children
assert h1.children[0].children[0].children[0].text == '1'
assert h2.children[0].children[0].children[0].text == '3'
assert h3.children[0].children[0].children[0].text == '4'
def test_counter_multiple_extends():
# Inspired by W3C failing test system-extends-invalid
page, = render_pages('''
<style>
@counter-style a {
system: extends b;
prefix: a;
}
@counter-style b {
system: extends c;
suffix: b;
}
@counter-style c {
system: extends b;
pad: 2 c;
}
@counter-style d {
system: extends d;
prefix: d;
}
@counter-style e {
system: extends unknown;
prefix: e;
}
@counter-style f {
system: extends decimal;
symbols: a;
}
@counter-style g {
system: extends decimal;
additive-symbols: 1 a;
}
</style>
<ol>
<li style="list-style-type: a"></li>
<li style="list-style-type: b"></li>
<li style="list-style-type: c"></li>
<li style="list-style-type: d"></li>
<li style="list-style-type: e"></li>
<li style="list-style-type: f"></li>
<li style="list-style-type: g"></li>
<li style="list-style-type: h"></li>
</ol>
''')
html, = page.children
body, = html.children
ol, = body.children
li_1, li_2, li_3, li_4, li_5, li_6, li_7, li_8 = ol.children
assert li_1.children[0].children[0].children[0].text == 'a1b'
assert li_2.children[0].children[0].children[0].text == '2b'
assert li_3.children[0].children[0].children[0].text == 'c3. '
assert li_4.children[0].children[0].children[0].text == 'd4. '
assert li_5.children[0].children[0].children[0].text == 'e5. '
assert li_6.children[0].children[0].children[0].text == '6. '
assert li_7.children[0].children[0].children[0].text == '7. '
assert li_8.children[0].children[0].children[0].text == '8. '