Last active
October 8, 2024 04:49
-
-
Save pikhovkin/5642563 to your computer and use it in GitHub Desktop.
Repeat on each page of complex headers (eg, tables) except the first page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# coding: utf-8 | |
from weasyprint import HTML, CSS | |
def get_page_body(boxes): | |
for box in boxes: | |
if box.element_tag == 'body': | |
return box | |
return get_page_body(box.all_children()) | |
# Main template | |
html = HTML('template.html') | |
main_doc = html.render(stylesheets=[CSS('styles.css')]) | |
exists_links = False | |
# Template of header | |
html = HTML('header.html') | |
header = html.render(stylesheets=[CSS(string='div {position: fixed; top: 1cm; left: 1cm;}')]) | |
header_page = header.pages[0] | |
exists_links = exists_links or header_page.links | |
header_body = get_page_body(header_page._page_box.all_children()) | |
header_body = header_body.copy_with_children(header_body.all_children()) | |
# Template of footer | |
html = HTML('footer.html') | |
footer = html.render(stylesheets=[CSS(string='div {position: fixed; bottom: 1cm; left: 1cm;}')]) | |
footer_page = footer.pages[0] | |
exists_links = exists_links or footer_page.links | |
footer_body = get_page_body(footer_page._page_box.all_children()) | |
footer_body = footer_body.copy_with_children(footer_body.all_children()) | |
# Insert header and footer in main doc | |
for i, page in enumerate(main_doc.pages): | |
if not i: | |
continue | |
page_body = get_page_body(page._page_box.all_children()) | |
page_body.children += header_body.all_children() | |
page_body.children += footer_body.all_children() | |
if exists_links: | |
page.links.extend(header_page.links) | |
page.links.extend(footer_page.links) | |
main_doc.write_pdf(target='main_doc.pdf') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's a neat solution but I'd be wary of using non-documented internal attributes like
_page_box
here as there is always a chance these might break in the future without anyone mentioning it in change logs.I'd also like to point out that at least as of WeasyPrint 52.5
running()
andcontent()
values are supported, see https://www.w3.org/TR/css-gcpm-3/#running-syntax for example.This way you can include your as-complex-as-needed headers and footers right in the main document, select them with CSS and place them in one of the page margins. With this solution
counter(page)
will also work as the headers are actually part of the full document.To skip the first page, you'd just include the header element only in the second page. You can also change headers further down the document simply by inlining another header with the same CSS selector. This is something that's rather hard to do with this solution when dynamic length data is concerned.
I have noticed that WeasyPrint will by default size these according to content and even setting
width: 100%
orwidth: 100vw
will not stretch them to full width - maybe there is no proper parent element? In any case I worked around that by setting an absolute width equal to the page width, there may also be better ways.