WeasyPrint
WeasyPrint copied to clipboard
Dynamic page height, fit to content
Add an option on page size (for example for height) to adapt the size of the page to fit to its content. The document will have a dynamic size and not fixed-size pages.
Is the goal to disable pagination entirely, or would forced page breaks (e.g. page-break-after: always
) still apply?
For a grading tool, we're actually hoping to do something similar so that each page in a PDF is only as tall as it needs to be to contain the page's content. Inspired by @SimonSapin's comments and @sebasmagri's comments at https://github.com/Kozea/WeasyPrint/issues/274, we've figured out how to get the actual height of the content in the body
of a page, as via document.pages[0]._page_box.children[0].children[0].height
. But to keep everything on one page, is there perhaps a more elegant solution than
- initially specifying a very large height and then cutting it down as needed (for which we'd need to guess a max possible height), or
- letting the content span multiple pages initially, summing the pages' heights, and creating a brand-new document whose
@page
height equals that sum (which feels a bit inefficient)?
Many thanks!
Hi,
I've been working on this because I need to have dynamic height documents and I've found a workaround that works well for me.
Generating a 1cm height pages and then counting the result.
I hope this could help anybody.
Best Regards.
css_1cm = [CSS(string="@page {height: 1cm; page-break-inside: always;}}}")]
render = html.render(stylesheets=css + css_1cm)
css += [ CSS(string="@page {height: " + str(len(render.pages)) + "cm}}}")
html.write_pdf(stylesheets=css)
I'll add here my use case for which I think I want the same feature: I'm generating images of syntax-colored code, for viewing on screens.
- I don't want the lines to wrap, though it's not so bad that they do.
- The generated image has a transparent border I don't want, but I trim that post-creation with graphicsmagick.
- The generated image is extra long when the code is short, but I trim a second time with the same graphicsmagick invocation.
- When the code more than 50 lines, I get a transparent gap between what I guess are pages, but I'm confused by the notion of "pages" in an image file altogether.
My current usage looks like this:
from plumbum import local
from weasyprint import HTML
try:
convert = local['gm']['convert']
except CommandNotFound:
convert = local['convert']
def mk_png(html: str, folder=None) -> str:
"""Return generated PNG file path"""
folder = (local.path(folder) if folder else local.path('/tmp/ccb_png')) / uuid4()
folder.mkdir()
png = folder / 'code.png'
(
convert['-trim', '-trim', '-', png]
<<HTML(
string=html,
media_type='screen'
).write_png(resolution=384)
)()
return png