2011-06-30 00:34:01 +04:00
|
|
|
|
# coding: utf8
|
|
|
|
|
|
|
|
|
|
# WeasyPrint converts web documents (HTML, CSS, ...) to PDF.
|
|
|
|
|
# Copyright (C) 2011 Simon Sapin
|
|
|
|
|
#
|
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
|
# it under the terms of the GNU Affero General Public License as
|
|
|
|
|
# published by the Free Software Foundation, either version 3 of the
|
|
|
|
|
# License, or (at your option) any later version.
|
|
|
|
|
#
|
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
# GNU Affero General Public License for more details.
|
|
|
|
|
#
|
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""
|
|
|
|
|
Test the layout.
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from attest import Tests, assert_hook # pylint: disable=W0611
|
2011-06-30 00:34:01 +04:00
|
|
|
|
|
2011-08-20 20:02:04 +04:00
|
|
|
|
from ..css.values import get_single_keyword, get_single_pixel_value
|
2011-09-27 20:11:31 +04:00
|
|
|
|
from . import TestPNGDocument
|
2011-07-21 15:47:42 +04:00
|
|
|
|
from ..formatting_structure import boxes
|
2011-08-16 18:01:50 +04:00
|
|
|
|
from .test_boxes import monkeypatch_validation
|
2011-10-03 18:37:02 +04:00
|
|
|
|
from . import FONTS
|
2011-06-30 00:34:01 +04:00
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
SUITE = Tests()
|
2011-06-30 00:34:01 +04:00
|
|
|
|
|
2011-08-16 18:01:50 +04:00
|
|
|
|
|
2011-08-25 14:50:23 +04:00
|
|
|
|
def body_children(page):
|
2011-09-09 01:15:14 +04:00
|
|
|
|
"""Take a ``page`` and return its <body>’s children."""
|
2011-08-25 14:50:23 +04:00
|
|
|
|
html = page.root_box
|
|
|
|
|
assert html.element.tag == 'html'
|
|
|
|
|
body, = html.children
|
|
|
|
|
assert body.element.tag == 'body'
|
|
|
|
|
return body.children
|
|
|
|
|
|
2011-09-02 14:03:37 +04:00
|
|
|
|
|
2011-08-25 14:33:32 +04:00
|
|
|
|
def parse_without_layout(html_content):
|
2011-09-09 01:15:14 +04:00
|
|
|
|
"""Parse some HTML, apply stylesheets, transform to boxes."""
|
2011-09-27 20:11:31 +04:00
|
|
|
|
return TestPNGDocument.from_string(html_content).formatting_structure
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
|
2011-09-09 01:15:14 +04:00
|
|
|
|
def validate_absolute_and_float(
|
|
|
|
|
real_non_shorthand, name, values, required=False):
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Fake validator for ``absolute`` and ``float``."""
|
2011-08-16 18:01:50 +04:00
|
|
|
|
if (
|
|
|
|
|
name == 'position' and
|
|
|
|
|
get_single_keyword(values) == 'absolute'
|
|
|
|
|
) or (
|
|
|
|
|
name == 'float' and
|
|
|
|
|
get_single_keyword(values) == 'left'
|
|
|
|
|
):
|
|
|
|
|
return [(name, values)]
|
|
|
|
|
return real_non_shorthand(name, values, required)
|
|
|
|
|
|
|
|
|
|
|
2011-07-12 17:12:08 +04:00
|
|
|
|
def parse(html_content):
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Parse some HTML, apply stylesheets, transform to boxes and lay out."""
|
2011-08-16 18:01:50 +04:00
|
|
|
|
# TODO: remove this patching when asbolute and floats are validated
|
|
|
|
|
with monkeypatch_validation(validate_absolute_and_float):
|
2011-09-27 20:11:31 +04:00
|
|
|
|
return TestPNGDocument.from_string(html_content).pages
|
2011-06-30 00:34:01 +04:00
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-07-07 19:33:17 +04:00
|
|
|
|
def test_page():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the layout for ``@page`` properties."""
|
2011-07-11 14:47:00 +04:00
|
|
|
|
pages = parse('<p>')
|
|
|
|
|
page = pages[0]
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert isinstance(page, boxes.PageBox)
|
|
|
|
|
assert int(page.outer_width) == 793 # A4: 210 mm in pixels
|
|
|
|
|
assert int(page.outer_height) == 1122 # A4: 297 mm in pixels
|
|
|
|
|
|
2011-07-11 17:03:06 +04:00
|
|
|
|
page, = parse('''<style>@page { size: 2in 10in; }</style>''')
|
|
|
|
|
assert page.outer_width == 192
|
|
|
|
|
assert page.outer_height == 960
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: 242px; }</style>''')
|
|
|
|
|
assert page.outer_width == 242
|
|
|
|
|
assert page.outer_height == 242
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: letter; }</style>''')
|
|
|
|
|
assert page.outer_width == 816 # 8.5in
|
|
|
|
|
assert page.outer_height == 1056 # 11in
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: letter portrait; }</style>''')
|
|
|
|
|
assert page.outer_width == 816 # 8.5in
|
|
|
|
|
assert page.outer_height == 1056 # 11in
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: letter landscape; }</style>''')
|
|
|
|
|
assert page.outer_width == 1056 # 11in
|
|
|
|
|
assert page.outer_height == 816 # 8.5in
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: portrait; }</style>''')
|
|
|
|
|
assert int(page.outer_width) == 793 # A4: 210 mm
|
|
|
|
|
assert int(page.outer_height) == 1122 # A4: 297 mm
|
|
|
|
|
|
|
|
|
|
page, = parse('''<style>@page { size: landscape; }</style>''')
|
|
|
|
|
assert int(page.outer_width) == 1122 # A4: 297 mm
|
|
|
|
|
assert int(page.outer_height) == 793 # A4: 210 mm
|
|
|
|
|
|
2011-07-11 14:47:00 +04:00
|
|
|
|
page, = parse('''
|
2011-09-27 20:11:31 +04:00
|
|
|
|
<style>@page { size: 200px 300px; margin: 10px 10% 20% 1in }
|
|
|
|
|
body { margin: 8px }
|
|
|
|
|
</style>
|
2011-07-12 19:09:41 +04:00
|
|
|
|
<p style="margin: 0">
|
2011-07-11 17:03:06 +04:00
|
|
|
|
''')
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert page.outer_width == 200
|
|
|
|
|
assert page.outer_height == 300
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert page.position_x == 0
|
|
|
|
|
assert page.position_y == 0
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert page.width == 84 # 200px - 10% - 1 inch
|
|
|
|
|
assert page.height == 230 # 300px - 10px - 20%
|
2011-07-07 19:33:17 +04:00
|
|
|
|
|
2011-07-11 14:47:00 +04:00
|
|
|
|
html = page.root_box
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert html.element.tag == 'html'
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert html.position_x == 96 # 1in
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert html.position_y == 10
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert html.width == 84
|
|
|
|
|
|
2011-08-25 14:50:23 +04:00
|
|
|
|
body, = html.children
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert body.element.tag == 'body'
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert body.position_x == 96 # 1in
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert body.position_y == 10
|
2011-07-07 19:33:17 +04:00
|
|
|
|
# body has margins in the UA stylesheet
|
|
|
|
|
assert body.margin_left == 8
|
|
|
|
|
assert body.margin_right == 8
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert body.margin_top == 8
|
|
|
|
|
assert body.margin_bottom == 8
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert body.width == 68
|
|
|
|
|
|
2011-08-25 14:50:23 +04:00
|
|
|
|
paragraph, = body.children
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert paragraph.element.tag == 'p'
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert paragraph.position_x == 104 # 1in + 8px
|
|
|
|
|
assert paragraph.position_y == 18 # 10px + 8px
|
2011-07-12 19:09:41 +04:00
|
|
|
|
assert paragraph.width == 68
|
2011-07-07 19:33:17 +04:00
|
|
|
|
|
2011-07-22 17:36:49 +04:00
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
@page { size: 100px; margin: 1px 2px; padding: 4px 8px;
|
|
|
|
|
border-width: 16px 32px; border-style: solid }
|
|
|
|
|
</style>
|
|
|
|
|
<body>
|
|
|
|
|
''')
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert page.width == 16 # 100 - 2 * 42
|
|
|
|
|
assert page.height == 58 # 100 - 2 * 21
|
2011-07-22 17:36:49 +04:00
|
|
|
|
html = page.root_box
|
|
|
|
|
assert html.element.tag == 'html'
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert html.position_x == 42 # 2 + 8 + 32
|
|
|
|
|
assert html.position_y == 21 # 1 + 4 + 16
|
2011-07-22 17:36:49 +04:00
|
|
|
|
|
2011-07-07 19:33:17 +04:00
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-07-12 15:50:54 +04:00
|
|
|
|
def test_block_widths():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the blocks widths."""
|
2011-08-22 20:14:37 +04:00
|
|
|
|
page, = parse('''
|
2011-07-07 19:33:17 +04:00
|
|
|
|
<style>
|
2011-08-22 20:14:37 +04:00
|
|
|
|
@page { margin: 0; size: 120px 2000px }
|
2011-07-07 19:33:17 +04:00
|
|
|
|
body { margin: 0 }
|
2011-07-08 20:08:11 +04:00
|
|
|
|
div { margin: 10px }
|
2011-07-07 19:33:17 +04:00
|
|
|
|
p { padding: 2px; border-width: 1px; border-style: solid }
|
|
|
|
|
</style>
|
|
|
|
|
<div>
|
|
|
|
|
<p></p>
|
|
|
|
|
<p style="width: 50px"></p>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="direction: rtl">
|
|
|
|
|
<p style="width: 50px; direction: rtl"></p>
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<p style="margin: 0 10px 0 20px"></p>
|
|
|
|
|
<p style="width: 50px; margin-left: 20px; margin-right: auto"></p>
|
|
|
|
|
<p style="width: 50px; margin-left: auto; margin-right: 20px"></p>
|
|
|
|
|
<p style="width: 50px; margin: auto"></p>
|
|
|
|
|
|
|
|
|
|
<p style="margin-left: 20px; margin-right: auto"></p>
|
|
|
|
|
<p style="margin-left: auto; margin-right: 20px"></p>
|
|
|
|
|
<p style="margin: auto"></p>
|
|
|
|
|
|
|
|
|
|
<p style="width: 200px; margin: auto"></p>
|
|
|
|
|
</div>
|
2011-07-11 17:03:06 +04:00
|
|
|
|
''')
|
2011-08-22 20:14:37 +04:00
|
|
|
|
html = page.root_box
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert html.element.tag == 'html'
|
2011-08-25 14:50:23 +04:00
|
|
|
|
body, = html.children
|
2011-07-07 19:33:17 +04:00
|
|
|
|
assert body.element.tag == 'body'
|
2011-07-08 20:08:11 +04:00
|
|
|
|
assert body.width == 120
|
2011-07-07 19:33:17 +04:00
|
|
|
|
|
|
|
|
|
divs = body.children
|
|
|
|
|
# TODO: remove this when we have proper whitespace handling that
|
|
|
|
|
# does not create anonymous block boxes for the whitespace between divs.
|
|
|
|
|
divs = [box for box in divs if not isinstance(box, boxes.AnonymousBox)]
|
|
|
|
|
|
|
|
|
|
paragraphs = []
|
|
|
|
|
for div in divs:
|
|
|
|
|
assert isinstance(div, boxes.BlockBox)
|
|
|
|
|
assert div.element.tag == 'div'
|
|
|
|
|
assert div.width == 100
|
|
|
|
|
for paragraph in div.children:
|
|
|
|
|
if isinstance(paragraph, boxes.AnonymousBox):
|
2011-09-09 00:44:10 +04:00
|
|
|
|
# TODO: remove this when we have proper whitespace handling
|
2011-07-07 19:33:17 +04:00
|
|
|
|
continue
|
|
|
|
|
assert isinstance(paragraph, boxes.BlockBox)
|
|
|
|
|
assert paragraph.element.tag == 'p'
|
|
|
|
|
assert paragraph.padding_left == 2
|
|
|
|
|
assert paragraph.padding_right == 2
|
|
|
|
|
assert paragraph.border_left_width == 1
|
|
|
|
|
assert paragraph.border_right_width == 1
|
|
|
|
|
paragraphs.append(paragraph)
|
|
|
|
|
|
|
|
|
|
assert len(paragraphs) == 11
|
|
|
|
|
|
|
|
|
|
# width is 'auto'
|
|
|
|
|
assert paragraphs[0].width == 94
|
|
|
|
|
assert paragraphs[0].margin_left == 0
|
|
|
|
|
assert paragraphs[0].margin_right == 0
|
|
|
|
|
|
|
|
|
|
# No 'auto', over-constrained equation with ltr, the initial
|
|
|
|
|
# 'margin-right: 0' was ignored.
|
|
|
|
|
assert paragraphs[1].width == 50
|
|
|
|
|
assert paragraphs[1].margin_left == 0
|
|
|
|
|
assert paragraphs[1].margin_right == 44
|
|
|
|
|
|
|
|
|
|
# No 'auto', over-constrained equation with ltr, the initial
|
|
|
|
|
# 'margin-right: 0' was ignored.
|
|
|
|
|
assert paragraphs[2].width == 50
|
|
|
|
|
assert paragraphs[2].margin_left == 44
|
|
|
|
|
assert paragraphs[2].margin_right == 0
|
|
|
|
|
|
|
|
|
|
# width is 'auto'
|
|
|
|
|
assert paragraphs[3].width == 64
|
|
|
|
|
assert paragraphs[3].margin_left == 20
|
|
|
|
|
assert paragraphs[3].margin_right == 10
|
|
|
|
|
|
|
|
|
|
# margin-right is 'auto'
|
|
|
|
|
assert paragraphs[4].width == 50
|
|
|
|
|
assert paragraphs[4].margin_left == 20
|
|
|
|
|
assert paragraphs[4].margin_right == 24
|
|
|
|
|
|
|
|
|
|
# margin-left is 'auto'
|
|
|
|
|
assert paragraphs[5].width == 50
|
|
|
|
|
assert paragraphs[5].margin_left == 24
|
|
|
|
|
assert paragraphs[5].margin_right == 20
|
|
|
|
|
|
|
|
|
|
# Both margins are 'auto', remaining space is split in half
|
|
|
|
|
assert paragraphs[6].width == 50
|
|
|
|
|
assert paragraphs[6].margin_left == 22
|
|
|
|
|
assert paragraphs[6].margin_right == 22
|
|
|
|
|
|
|
|
|
|
# width is 'auto', other 'auto' are set to 0
|
|
|
|
|
assert paragraphs[7].width == 74
|
|
|
|
|
assert paragraphs[7].margin_left == 20
|
|
|
|
|
assert paragraphs[7].margin_right == 0
|
|
|
|
|
|
|
|
|
|
# width is 'auto', other 'auto' are set to 0
|
|
|
|
|
assert paragraphs[8].width == 74
|
|
|
|
|
assert paragraphs[8].margin_left == 0
|
|
|
|
|
assert paragraphs[8].margin_right == 20
|
|
|
|
|
|
|
|
|
|
# width is 'auto', other 'auto' are set to 0
|
|
|
|
|
assert paragraphs[9].width == 94
|
|
|
|
|
assert paragraphs[9].margin_left == 0
|
|
|
|
|
assert paragraphs[9].margin_right == 0
|
|
|
|
|
|
|
|
|
|
# sum of non-auto initially is too wide, set auto values to 0
|
|
|
|
|
assert paragraphs[10].width == 200
|
|
|
|
|
assert paragraphs[10].margin_left == 0
|
|
|
|
|
assert paragraphs[10].margin_right == -106
|
2011-07-12 15:50:54 +04:00
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-07-12 15:50:54 +04:00
|
|
|
|
def test_block_heights():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the blocks heights."""
|
2011-07-12 15:50:54 +04:00
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
2011-07-13 20:28:27 +04:00
|
|
|
|
@page { margin: 0; size: 100px 2000px }
|
2011-07-12 15:50:54 +04:00
|
|
|
|
html, body { margin: 0 }
|
|
|
|
|
div { margin: 4px; border-width: 2px; border-style: solid;
|
|
|
|
|
padding: 4px }
|
|
|
|
|
p { margin: 8px; border-width: 4px; border-style: solid;
|
|
|
|
|
padding: 8px; height: 50px }
|
|
|
|
|
</style>
|
|
|
|
|
<div>
|
|
|
|
|
<p></p>
|
2011-07-22 20:16:31 +04:00
|
|
|
|
<!-- These two are not in normal flow: the do not contribute to
|
2011-08-16 18:01:50 +04:00
|
|
|
|
the parent’s height. -->
|
2011-07-22 20:16:31 +04:00
|
|
|
|
<p style="position: absolute"></p>
|
|
|
|
|
<p style="float: left"></p>
|
2011-07-12 15:50:54 +04:00
|
|
|
|
</div><div>
|
|
|
|
|
<p></p>
|
|
|
|
|
<p></p>
|
|
|
|
|
<p></p>
|
|
|
|
|
</div>
|
|
|
|
|
''')
|
2011-08-25 14:50:23 +04:00
|
|
|
|
divs = body_children(page)
|
2011-07-12 15:50:54 +04:00
|
|
|
|
|
|
|
|
|
assert divs[0].height == 90
|
|
|
|
|
assert divs[1].height == 90 * 3
|
2011-07-13 20:26:39 +04:00
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-08-10 12:28:33 +04:00
|
|
|
|
def test_block_percentage_heights():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the blocks heights set in percents."""
|
2011-08-08 18:17:10 +04:00
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
html, body { margin: 0 }
|
|
|
|
|
body { height: 50% }
|
|
|
|
|
</style>
|
|
|
|
|
<body>
|
|
|
|
|
''')
|
|
|
|
|
html = page.root_box
|
|
|
|
|
assert html.element.tag == 'html'
|
2011-08-25 14:50:23 +04:00
|
|
|
|
body, = html.children
|
2011-08-08 18:17:10 +04:00
|
|
|
|
assert body.element.tag == 'body'
|
|
|
|
|
|
|
|
|
|
# Since html’s height depend on body’s, body’s 50% means 'auto'
|
|
|
|
|
assert body.height == 0
|
|
|
|
|
|
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
html, body { margin: 0 }
|
|
|
|
|
html { height: 300px }
|
|
|
|
|
body { height: 50% }
|
|
|
|
|
</style>
|
|
|
|
|
<body>
|
|
|
|
|
''')
|
|
|
|
|
html = page.root_box
|
|
|
|
|
assert html.element.tag == 'html'
|
2011-08-25 14:50:23 +04:00
|
|
|
|
body, = html.children
|
2011-08-08 18:17:10 +04:00
|
|
|
|
assert body.element.tag == 'body'
|
|
|
|
|
|
|
|
|
|
# This time the percentage makes sense
|
|
|
|
|
assert body.height == 150
|
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-08-20 17:07:14 +04:00
|
|
|
|
def test_lists():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the lists."""
|
2011-08-20 17:07:14 +04:00
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
body { margin: 0 }
|
|
|
|
|
ul { margin-left: 50px; list-style: inside circle }
|
|
|
|
|
</style>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>abc</li>
|
|
|
|
|
</ul>
|
|
|
|
|
''')
|
2011-08-25 14:50:23 +04:00
|
|
|
|
unordered_list, = body_children(page)
|
2011-08-24 14:28:25 +04:00
|
|
|
|
list_element, = [child for child in unordered_list.children
|
2011-08-20 17:07:14 +04:00
|
|
|
|
if not isinstance(child, boxes.AnonymousBox)]
|
2011-08-25 14:50:23 +04:00
|
|
|
|
line, = list_element.children
|
2011-08-20 20:54:42 +04:00
|
|
|
|
marker, spacer, content = line.children
|
2011-09-30 19:18:53 +04:00
|
|
|
|
assert marker.utf8_text.decode('utf8') == u'◦'
|
|
|
|
|
assert spacer.utf8_text.decode('utf8') == u'\u00a0' # NO-BREAK SPACE
|
|
|
|
|
assert content.utf8_text.decode('utf8') == u'abc'
|
2011-08-20 17:07:14 +04:00
|
|
|
|
|
|
|
|
|
page, = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
body { margin: 0 }
|
|
|
|
|
ul { margin-left: 50px; }
|
|
|
|
|
</style>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>abc</li>
|
|
|
|
|
</ul>
|
|
|
|
|
''')
|
2011-08-25 14:50:23 +04:00
|
|
|
|
unordered_list, = body_children(page)
|
2011-08-24 14:28:25 +04:00
|
|
|
|
list_element, = [child for child in unordered_list.children
|
2011-08-20 17:07:14 +04:00
|
|
|
|
if not isinstance(child, boxes.AnonymousBox)]
|
2011-08-24 14:28:25 +04:00
|
|
|
|
marker = list_element.outside_list_marker
|
2011-08-20 20:54:42 +04:00
|
|
|
|
font_size = get_single_pixel_value(marker.style.font_size)
|
|
|
|
|
assert marker.margin_right == 0.5 * font_size # 0.5em
|
2011-08-24 14:28:25 +04:00
|
|
|
|
assert marker.position_x == (
|
|
|
|
|
list_element.padding_box_x() - marker.width - marker.margin_right)
|
|
|
|
|
assert marker.position_y == list_element.position_y
|
2011-09-30 19:18:53 +04:00
|
|
|
|
assert marker.utf8_text.decode('utf8') == u'•'
|
2011-08-25 14:50:23 +04:00
|
|
|
|
line, = list_element.children
|
2011-08-20 20:54:42 +04:00
|
|
|
|
content, = line.children
|
2011-09-30 19:18:53 +04:00
|
|
|
|
assert content.utf8_text == b'abc'
|
2011-08-20 17:07:14 +04:00
|
|
|
|
|
2011-08-08 18:17:10 +04:00
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_empty_linebox():
|
|
|
|
|
"""Test lineboxes with no content other than space-like characters."""
|
2011-07-26 19:34:55 +04:00
|
|
|
|
def get_paragraph_linebox(width, font_size):
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Helper returning a paragraph with given style."""
|
2011-07-26 19:34:55 +04:00
|
|
|
|
page = u'''
|
|
|
|
|
<style>
|
2011-08-09 12:15:53 +04:00
|
|
|
|
p { font-size:%(font_size)spx; width:%(width)spx;
|
|
|
|
|
font-family:%(fonts)s;}
|
2011-07-26 19:34:55 +04:00
|
|
|
|
</style>
|
|
|
|
|
<p> </p>'''
|
2011-08-24 14:28:25 +04:00
|
|
|
|
page, = parse(page % {
|
|
|
|
|
'fonts': FONTS, 'font_size': font_size, 'width': width})
|
2011-08-25 14:50:23 +04:00
|
|
|
|
paraghaph, = body_children(page)
|
2011-08-24 14:28:25 +04:00
|
|
|
|
return paraghaph
|
2011-07-26 19:34:55 +04:00
|
|
|
|
|
|
|
|
|
font_size = 12
|
|
|
|
|
width = 500
|
2011-08-24 14:28:25 +04:00
|
|
|
|
paragraph = get_paragraph_linebox(width, font_size)
|
|
|
|
|
assert len(paragraph.children) == 0
|
|
|
|
|
assert paragraph.height == 0
|
2011-07-26 19:34:55 +04:00
|
|
|
|
|
|
|
|
|
|
2011-10-03 18:37:02 +04:00
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_breaking_linebox():
|
|
|
|
|
"""Test lineboxes breaks with a lot of text and deep nesting."""
|
|
|
|
|
def get_paragraph_linebox(width, font_size):
|
2011-10-03 20:57:26 +04:00
|
|
|
|
"""Helper returning a paragraph with given style."""
|
2011-10-03 18:37:02 +04:00
|
|
|
|
page = u'''
|
|
|
|
|
<style>
|
|
|
|
|
p { font-size: %(font_size)spx;
|
|
|
|
|
width: %(width)spx;
|
|
|
|
|
font-family: %(fonts)s;
|
|
|
|
|
background-color: #393939;
|
|
|
|
|
color: #FFFFFF;
|
|
|
|
|
line-height: 1;
|
|
|
|
|
text-decoration: underline overline line-through;}
|
|
|
|
|
</style>
|
|
|
|
|
<p><em>Lorem<strong> Ipsum <span>is very</span>simply</strong><em>
|
|
|
|
|
dummy</em>text of the printing and. naaaa </em> naaaa naaaa naaaa
|
|
|
|
|
naaaa naaaa naaaa naaaa naaaa</p>'''
|
|
|
|
|
page, = parse(
|
|
|
|
|
page % {'fonts': FONTS, 'font_size': font_size, 'width': width})
|
|
|
|
|
html = page.root_box
|
|
|
|
|
body = html.children[0]
|
|
|
|
|
paragraph = body.children[0]
|
|
|
|
|
return paragraph
|
|
|
|
|
font_size = 13
|
|
|
|
|
width = 350
|
|
|
|
|
paragraph = get_paragraph_linebox(width, font_size)
|
|
|
|
|
assert len(list(paragraph.children)) == 3
|
|
|
|
|
|
|
|
|
|
lines = paragraph.children
|
|
|
|
|
for line in lines:
|
|
|
|
|
assert line.style.font_size[0].value == font_size
|
|
|
|
|
assert line.element.tag == 'p'
|
|
|
|
|
for child in line.children:
|
|
|
|
|
assert child.element.tag in ('em', 'p')
|
|
|
|
|
assert child.style.font_size[0].value == font_size
|
|
|
|
|
if isinstance(child, boxes.ParentBox):
|
|
|
|
|
for child_child in child.children:
|
|
|
|
|
assert child.element.tag in ('em', 'strong', 'span')
|
|
|
|
|
assert child.style.font_size[0].value == font_size
|
2011-07-28 20:39:35 +04:00
|
|
|
|
|
2011-07-29 16:07:27 +04:00
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-07-29 16:07:27 +04:00
|
|
|
|
def test_linebox_text():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the creation of line boxes."""
|
2011-07-29 16:07:27 +04:00
|
|
|
|
def get_paragraph_linebox():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Helper returning a paragraph with customizable style."""
|
2011-07-29 16:07:27 +04:00
|
|
|
|
page = u'''
|
|
|
|
|
<style>
|
2011-08-09 12:15:53 +04:00
|
|
|
|
p { width:%(width)spx; font-family:%(fonts)s;}
|
2011-07-29 16:07:27 +04:00
|
|
|
|
</style>
|
|
|
|
|
<p><em>Lorem Ipsum</em>is very <strong>coool</strong></p>'''
|
2011-08-09 12:15:53 +04:00
|
|
|
|
|
2011-10-03 18:13:19 +04:00
|
|
|
|
page, = parse(page % {'fonts': FONTS, 'width': 220})
|
2011-08-25 14:50:23 +04:00
|
|
|
|
paragraph, = body_children(page)
|
2011-07-29 16:07:27 +04:00
|
|
|
|
return paragraph
|
|
|
|
|
|
|
|
|
|
paragraph = get_paragraph_linebox()
|
|
|
|
|
lines = list(paragraph.children)
|
|
|
|
|
assert len(lines) == 2
|
|
|
|
|
|
2011-09-30 19:18:53 +04:00
|
|
|
|
text = ' '.join(
|
|
|
|
|
(''.join(box.utf8_text for box in line.descendants()
|
|
|
|
|
if isinstance(box, boxes.TextBox)))
|
|
|
|
|
for line in lines)
|
|
|
|
|
assert text == b'Lorem Ipsumis very coool'
|
2011-07-29 16:07:27 +04:00
|
|
|
|
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
@SUITE.test
|
2011-07-29 16:07:27 +04:00
|
|
|
|
def test_linebox_positions():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the position of line boxes."""
|
2011-07-29 16:07:27 +04:00
|
|
|
|
def get_paragraph_linebox():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Helper returning a paragraph with customizable style."""
|
2011-07-29 16:07:27 +04:00
|
|
|
|
page = u'''
|
|
|
|
|
<style>
|
2011-08-09 12:15:53 +04:00
|
|
|
|
p { width:%(width)spx; font-family:%(fonts)s;}
|
2011-07-29 16:07:27 +04:00
|
|
|
|
</style>
|
2011-08-09 12:15:53 +04:00
|
|
|
|
<p>this is test for <strong>Weasyprint</strong></p>'''
|
2011-10-03 18:13:19 +04:00
|
|
|
|
page, = parse(page % {'fonts': FONTS, 'width': 220})
|
2011-08-25 14:50:23 +04:00
|
|
|
|
paragraph, = body_children(page)
|
2011-07-29 16:07:27 +04:00
|
|
|
|
return paragraph
|
|
|
|
|
|
|
|
|
|
paragraph = get_paragraph_linebox()
|
|
|
|
|
lines = list(paragraph.children)
|
2011-08-17 16:01:06 +04:00
|
|
|
|
assert len(lines) == 2
|
2011-07-29 16:07:27 +04:00
|
|
|
|
|
|
|
|
|
ref_position_y = lines[0].position_y
|
|
|
|
|
ref_position_x = lines[0].position_x
|
|
|
|
|
for line in lines:
|
|
|
|
|
assert ref_position_y == line.position_y
|
|
|
|
|
assert ref_position_x == line.position_x
|
|
|
|
|
for box in line.children:
|
2011-08-01 20:28:05 +04:00
|
|
|
|
assert ref_position_x == box.position_x
|
2011-07-29 16:07:27 +04:00
|
|
|
|
ref_position_x += box.width
|
|
|
|
|
assert ref_position_y == box.position_y
|
2011-08-01 20:28:05 +04:00
|
|
|
|
assert ref_position_x - line.position_x <= line.width
|
2011-07-29 16:07:27 +04:00
|
|
|
|
ref_position_x = line.position_x
|
|
|
|
|
ref_position_y += line.height
|
2011-08-22 20:14:37 +04:00
|
|
|
|
|
|
|
|
|
|
2011-08-25 14:50:23 +04:00
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_forced_line_breaks():
|
|
|
|
|
"""Test <pre> and <br>."""
|
|
|
|
|
# These lines should be small enough to fit on the default A4 page
|
|
|
|
|
# with the default 12pt font-size.
|
2011-09-09 01:15:14 +04:00
|
|
|
|
page, = parse('''
|
2011-08-25 14:50:23 +04:00
|
|
|
|
<pre>Lorem ipsum dolor sit amet,
|
|
|
|
|
consectetur adipiscing elit.
|
|
|
|
|
Sed sollicitudin nibh
|
|
|
|
|
et turpis molestie tristique.</pre>
|
2011-09-09 01:15:14 +04:00
|
|
|
|
''')
|
2011-08-25 14:50:23 +04:00
|
|
|
|
pre, = body_children(page)
|
|
|
|
|
assert pre.element.tag == 'pre'
|
|
|
|
|
lines = pre.children
|
|
|
|
|
assert all(isinstance(line, boxes.LineBox) for line in lines)
|
|
|
|
|
assert len(lines) == 4
|
|
|
|
|
|
2011-09-09 01:15:14 +04:00
|
|
|
|
page, = parse('''
|
2011-08-25 14:50:23 +04:00
|
|
|
|
<p>Lorem ipsum dolor sit amet,<br>
|
|
|
|
|
consectetur adipiscing elit.<br>
|
|
|
|
|
Sed sollicitudin nibh<br>
|
|
|
|
|
et turpis molestie tristique.</p>
|
2011-09-09 01:15:14 +04:00
|
|
|
|
''')
|
2011-08-25 14:50:23 +04:00
|
|
|
|
pre, = body_children(page)
|
|
|
|
|
assert pre.element.tag == 'p'
|
|
|
|
|
lines = pre.children
|
|
|
|
|
assert all(isinstance(line, boxes.LineBox) for line in lines)
|
|
|
|
|
assert len(lines) == 4
|
|
|
|
|
|
|
|
|
|
|
2011-09-30 14:17:53 +04:00
|
|
|
|
#@SUITE.test
|
2011-08-22 20:14:37 +04:00
|
|
|
|
def test_page_breaks():
|
2011-08-24 14:28:25 +04:00
|
|
|
|
"""Test the page breaks."""
|
2011-08-22 20:14:37 +04:00
|
|
|
|
pages = parse('''
|
|
|
|
|
<style>
|
|
|
|
|
@page { size: 100px; margin: 10px }
|
|
|
|
|
body { margin: 0 }
|
|
|
|
|
div { height: 30px }
|
|
|
|
|
</style>
|
|
|
|
|
<div/><div/><div/><div/><div/>
|
|
|
|
|
''')
|
|
|
|
|
page_divs = []
|
|
|
|
|
for page in pages:
|
2011-08-25 14:50:23 +04:00
|
|
|
|
divs = body_children(page)
|
2011-08-22 20:14:37 +04:00
|
|
|
|
assert all([div.element.tag == 'div' for div in divs])
|
|
|
|
|
assert all([div.position_x == 10 for div in divs])
|
|
|
|
|
page_divs.append(divs)
|
|
|
|
|
|
2011-08-24 14:28:25 +04:00
|
|
|
|
positions_y = [[div.position_y for div in divs] for divs in page_divs]
|
2011-08-22 20:14:37 +04:00
|
|
|
|
assert positions_y == [[10, 40], [10, 40], [10]]
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_inlinebox_spliting():
|
2011-08-25 19:27:00 +04:00
|
|
|
|
"""Test the inline boxes spliting."""
|
2011-08-25 14:33:32 +04:00
|
|
|
|
from ..layout.inlines import split_inline_box
|
|
|
|
|
from ..layout.percentages import resolve_percentages
|
2011-09-02 14:03:37 +04:00
|
|
|
|
|
2011-08-25 14:33:32 +04:00
|
|
|
|
def get_inlinebox(content):
|
|
|
|
|
"""Helper returning a inlinebox with customizable style."""
|
|
|
|
|
page = u'<style>p { width:%(width)spx; font-family:%(fonts)s;}</style>'
|
|
|
|
|
page = '%s <p>%s</p>' % (page, content)
|
|
|
|
|
html = parse_without_layout(page % {'fonts': FONTS, 'width': 200})
|
|
|
|
|
body = html.children[0]
|
|
|
|
|
paragraph = body.children[0]
|
|
|
|
|
return paragraph.children[0].children[0]
|
|
|
|
|
|
2011-08-25 19:27:00 +04:00
|
|
|
|
def get_parts(inlinebox, width):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Yield the parts of the splitted ``inlinebox`` of given ``width``."""
|
2011-09-30 21:04:05 +04:00
|
|
|
|
skip = None
|
|
|
|
|
while 1:
|
|
|
|
|
box, skip = split_inline_box(inlinebox, width, skip)
|
|
|
|
|
yield box
|
|
|
|
|
if skip is None:
|
|
|
|
|
break
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
def get_joined_text(parts):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Get the joined text from ``parts``."""
|
2011-09-30 19:18:53 +04:00
|
|
|
|
return ''.join(part.children[0].utf8_text for part in parts)
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
def test_inlinebox_all_spacing(inlinebox, value):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Test the spacing for the four sides of ``inlinebox``."""
|
|
|
|
|
for side in ('left', 'top', 'bottom', 'right'):
|
2011-08-25 14:33:32 +04:00
|
|
|
|
test_inlinebox_spacing(inlinebox, value, side)
|
|
|
|
|
|
|
|
|
|
def test_inlinebox_spacing(inlinebox, value, side):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Test the margin, padding and border-width of ``inlinebox``."""
|
2011-08-25 19:27:00 +04:00
|
|
|
|
assert getattr(inlinebox, 'margin_%s' % side) == value
|
2011-08-25 14:33:32 +04:00
|
|
|
|
assert getattr(inlinebox, 'padding_%s' % side) == value
|
|
|
|
|
assert getattr(inlinebox, 'border_%s_width' % side) == value
|
|
|
|
|
|
2011-09-09 01:02:17 +04:00
|
|
|
|
content = '''<strong>WeasyPrint is a free software visual rendering engine
|
|
|
|
|
for HTML and CSS</strong>'''
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
2011-09-30 19:18:53 +04:00
|
|
|
|
original_text = inlinebox.children[0].utf8_text
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
# test with width = 1000
|
|
|
|
|
parts = list(get_parts(inlinebox, 1000))
|
|
|
|
|
assert len(parts) == 1
|
|
|
|
|
assert original_text == get_joined_text(parts)
|
|
|
|
|
|
2011-08-25 19:27:00 +04:00
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
2011-09-30 19:18:53 +04:00
|
|
|
|
original_text = inlinebox.children[0].utf8_text
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
2011-08-25 14:33:32 +04:00
|
|
|
|
# test with width = 100
|
|
|
|
|
parts = list(get_parts(inlinebox, 100))
|
2011-09-30 21:04:05 +04:00
|
|
|
|
assert len(parts) > 1
|
2011-08-25 14:33:32 +04:00
|
|
|
|
assert original_text == get_joined_text(parts)
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
2011-09-30 19:18:53 +04:00
|
|
|
|
original_text = inlinebox.children[0].utf8_text
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
# test with width = 10
|
|
|
|
|
parts = list(get_parts(inlinebox, 10))
|
2011-09-30 21:04:05 +04:00
|
|
|
|
assert len(parts) > 1
|
2011-08-25 14:33:32 +04:00
|
|
|
|
assert original_text == get_joined_text(parts)
|
|
|
|
|
|
|
|
|
|
# with margin-border-padding
|
2011-09-09 01:02:17 +04:00
|
|
|
|
content = '''<strong style="border:10px solid; margin:10px; padding:10px">
|
2011-08-25 14:33:32 +04:00
|
|
|
|
WeasyPrint is a free software visual rendering engine
|
2011-09-09 01:02:17 +04:00
|
|
|
|
for HTML and CSS</strong>'''
|
2011-08-25 14:33:32 +04:00
|
|
|
|
|
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
2011-09-30 19:18:53 +04:00
|
|
|
|
original_text = inlinebox.children[0].utf8_text
|
2011-08-25 14:33:32 +04:00
|
|
|
|
# test with width = 1000
|
|
|
|
|
parts = list(get_parts(inlinebox, 1000))
|
|
|
|
|
assert len(parts) == 1
|
|
|
|
|
assert original_text == get_joined_text(parts)
|
|
|
|
|
test_inlinebox_all_spacing(parts[0], 10)
|
|
|
|
|
|
2011-08-25 19:27:00 +04:00
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
2011-09-30 19:18:53 +04:00
|
|
|
|
original_text = inlinebox.children[0].utf8_text
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
2011-08-25 14:33:32 +04:00
|
|
|
|
# test with width = 1000
|
|
|
|
|
parts = list(get_parts(inlinebox, 100))
|
|
|
|
|
assert len(parts) != 1
|
|
|
|
|
assert original_text == get_joined_text(parts)
|
|
|
|
|
first_inline_box = parts.pop(0)
|
|
|
|
|
test_inlinebox_spacing(first_inline_box, 10, 'left')
|
|
|
|
|
test_inlinebox_spacing(first_inline_box, 0, 'right')
|
|
|
|
|
last_inline_box = parts.pop()
|
|
|
|
|
test_inlinebox_spacing(last_inline_box, 10, 'right')
|
|
|
|
|
test_inlinebox_spacing(last_inline_box, 0, 'left')
|
|
|
|
|
for part in parts:
|
|
|
|
|
test_inlinebox_spacing(part, 0, 'right')
|
|
|
|
|
test_inlinebox_spacing(part, 0, 'left')
|
|
|
|
|
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_inlinebox_text_after_spliting():
|
|
|
|
|
"""Test the inlinebox text after spliting."""
|
|
|
|
|
from ..layout.inlines import split_inline_box
|
|
|
|
|
from ..layout.percentages import resolve_percentages
|
2011-09-02 14:03:37 +04:00
|
|
|
|
|
2011-08-25 19:27:00 +04:00
|
|
|
|
def get_inlinebox(content):
|
|
|
|
|
"""Helper returning a inlinebox with customizable style."""
|
|
|
|
|
page = u'<style>p { width:%(width)spx; font-family:%(fonts)s;}</style>'
|
|
|
|
|
page = '%s <p>%s</p>' % (page, content)
|
|
|
|
|
html = parse_without_layout(page % {'fonts': FONTS, 'width': 200})
|
|
|
|
|
body = html.children[0]
|
|
|
|
|
paragraph = body.children[0]
|
|
|
|
|
return paragraph.children[0].children[0]
|
|
|
|
|
|
|
|
|
|
def get_parts(inlinebox, width):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Yield the parts of the splitted ``inlinebox`` of given ``width``."""
|
2011-09-30 21:04:05 +04:00
|
|
|
|
skip = None
|
|
|
|
|
while 1:
|
|
|
|
|
box, skip = split_inline_box(inlinebox, width, skip)
|
|
|
|
|
yield box
|
|
|
|
|
if skip is None:
|
|
|
|
|
break
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
def get_full_text(inlinebox):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Get the full text in ``inlinebox``."""
|
|
|
|
|
return ''.join(
|
2011-09-30 19:18:53 +04:00
|
|
|
|
part.utf8_text for part in inlinebox.descendants()
|
2011-09-09 01:02:17 +04:00
|
|
|
|
if isinstance(part, boxes.TextBox))
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
def get_joined_text(parts):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Get the joined text from ``parts``."""
|
|
|
|
|
return ''.join(get_full_text(part) for part in parts)
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
2011-09-09 01:02:17 +04:00
|
|
|
|
content = '''<strong><em><em><em>
|
2011-08-25 19:27:00 +04:00
|
|
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
|
2011-09-09 01:02:17 +04:00
|
|
|
|
</em></em></em></strong>'''
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
inlinebox = get_inlinebox(content)
|
|
|
|
|
resolve_percentages(inlinebox)
|
|
|
|
|
|
|
|
|
|
original_text = get_full_text(inlinebox)
|
|
|
|
|
|
|
|
|
|
# test with width = 10
|
|
|
|
|
parts = list(get_parts(inlinebox, 100))
|
|
|
|
|
assert len(parts) > 2
|
|
|
|
|
assert original_text == get_joined_text(parts)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SUITE.test
|
|
|
|
|
def test_page_and_linebox_breaking():
|
|
|
|
|
"""Test the linebox text after spliting linebox and page."""
|
|
|
|
|
def get_pages(content):
|
|
|
|
|
"""Helper returning a inlinebox with customizable style."""
|
|
|
|
|
page = '''
|
|
|
|
|
<style>
|
|
|
|
|
p { font-family:%(fonts)s; font-size:12px}
|
|
|
|
|
@page { size: 100px; margin:2px; border:1px solid }
|
|
|
|
|
body { margin: 0 }
|
|
|
|
|
</style>
|
|
|
|
|
<div>%(content)s</div>'''
|
2011-09-02 14:03:37 +04:00
|
|
|
|
page = page % {'fonts': FONTS, 'content': content}
|
2011-08-25 19:27:00 +04:00
|
|
|
|
return parse(page)
|
|
|
|
|
|
|
|
|
|
def get_full_text(lines):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Get a list of a full text parts in ``inlinebox``."""
|
2011-08-26 14:03:17 +04:00
|
|
|
|
texts = []
|
2011-08-25 19:27:00 +04:00
|
|
|
|
for line in lines:
|
2011-08-26 14:03:17 +04:00
|
|
|
|
line_texts = []
|
2011-08-25 19:27:00 +04:00
|
|
|
|
for child in line.descendants():
|
|
|
|
|
if isinstance(child, boxes.TextBox):
|
2011-09-30 19:18:53 +04:00
|
|
|
|
line_texts.append(child.utf8_text)
|
2011-08-26 14:03:17 +04:00
|
|
|
|
texts.append(u''.join(line_texts))
|
|
|
|
|
return texts
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
def get_joined_text(pages):
|
2011-09-09 01:02:17 +04:00
|
|
|
|
"""Get the joined text from ``parts``."""
|
2011-08-26 14:03:17 +04:00
|
|
|
|
texts = []
|
2011-08-25 19:27:00 +04:00
|
|
|
|
for page in pages:
|
|
|
|
|
html = page.root_box
|
|
|
|
|
body = html.children[0]
|
|
|
|
|
div = body.children[0]
|
|
|
|
|
lines = div.children
|
2011-08-26 14:03:17 +04:00
|
|
|
|
texts.extend(get_full_text(lines))
|
|
|
|
|
return u' '.join(texts)
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
2011-09-30 21:04:05 +04:00
|
|
|
|
content = u'1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15'
|
2011-08-25 19:27:00 +04:00
|
|
|
|
|
|
|
|
|
pages = get_pages(content)
|
|
|
|
|
assert len(pages) == 2
|
|
|
|
|
assert content == get_joined_text(pages)
|