I apologize for the long post in advance...I just hope that some of the information included in my question might be helpful for someone else.
I have been trying to print a PDF from an html page rendered in Flask.
This PDF contains several feature that I would like to include in the PDF such as Jinja2
templating variables inline css
and static files, javascript
libraries like momentjs
and UIKit
, and some images.
I have been successful in putting together the majority of these pieces but it seems that I can't find any solution for 2 features: the UIKit
javascript
library some inline CSS.
here a simplified version of the ecosystem:
I define the absolute path base
that I send to Jinja2
to correctly include the JS
static libraries (including momentjs
) and render the html. After defining some options for wkhtmltopdf
, I prepare the array a static css
files (uikit.min.css
amongst others) that I use to style the PDF, and I send the pdf as a response to the browser.
def generatePdf():
## missing text ##
base = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
document = render_template('to_be_printed.html', base=base, order=res) # order is variable for Jinja2 - not relevant
options = {
'page-size': 'A4',
'enable-local-file-access': None, # to avoid blanks
'javascript-delay': 1000,
'no-stop-slow-scripts': None,
'debug-javascript': None,
'enable-javascript': None
}
css = assets.bundles['home_css'].urls()
css = [base+path for path in css]
pdf = pdfkit.from_string(document, False, options=options, verbose=True, css=css)
response = make_response(pdf)
response.headers['Content-Type'] = 'application/pdf'
return response
In this version of the file there are all the element that I am trying to render in to_be_printed.html
:
<html>
<head>
<meta charset="utf-8">
<style media="screen">
html, body {
background: #fff
}
.navigation {
display: flex;
flex-direction: row;
justify-content: space-between;
}
</style>
<title>Reservation N. {{ order }}</title>
</head>
<body>
<div class="navigation uk-flex uk-flex-between uk-flex-bottom" style="display:flex; flex-direction:row">
<div class="">
<h2 class="uk-margin-remove" style="color:red">Hello {{order.from_data.strftime('%d %B %Y at %H:%M') }}</h2>
</div>
<div class="uk-logo">
<a class="uk-logo" href="{{ url_for('index')}}">
<img class="" src="{{ order.logo }}" alt="Database X" style="max-width: 350px; width: 70%">
</a>
<p id="io">doesn't matter</p>
</div>
</div>
{% assets "home_js" %}
<script type="text/javascript" src="{{ base_url+ASSET_URL }}"></script>
{% endassets %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js" charset="utf-8"></script>
<script type="text/javascript">
var el = document.getElementById('io')
el.style.color = 'red'
</script>
</body>
</html>
- All the
CSS
files sent ascss
parameter throughpdfkit.from_string
are perfectly applied. - In the header the style for
html, body
is working but I cannot display thediv.navigation
as flex. I am trying it from- the
<head>
, - inline from UIKit
class='uk-flex'
and - manually
style='display:flex
, although the inline style<h2 style="color:red">
is working fine.
- the
- All the
jinja2
variables are rendered fine, but I had to call thestrftime
because formatting inline withmoment
(loaded at the end of the document) usingmoment(order.from_date).format()
didn't work. - a simple handwritten script at the bottom of the page is working fine (so
javascript
is actually running on the template).
The problems seems to be different, but everything would work if I manage to load and apply the UIKit javascript library
(not sure about the flex
though). I tried a lot of different options for pdfkit, but no changes seems to affect this behaviour:
'javascript-delay': 1000,
I even set it to 50000...no changes'no-stop-slow-scripts': None,
does not affect'debug-javascript': None,
helped me a lot, but now there are no error/warning/logs'enable-javascript': None
does not affect
I also moved the script before the body (inside and outside the <head>
.
Do you have any suggestion?
Thank you very much