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
CSSfiles sent ascssparameter throughpdfkit.from_stringare perfectly applied. - In the header the style for
html, bodyis working but I cannot display thediv.navigationas 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
jinja2variables are rendered fine, but I had to call thestrftimebecause 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
javascriptis 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': Nonedoes not affect
I also moved the script before the body (inside and outside the <head>.
Do you have any suggestion?
Thank you very much