0

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 as css parameter through pdfkit.from_string are perfectly applied.
  • In the header the style for html, body is working but I cannot display the div.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.
  • All the jinja2 variables are rendered fine, but I had to call the strftime because formatting inline with moment (loaded at the end of the document) using moment(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

ddgg
  • 145
  • 1
  • 10

1 Answers1

0

The problem is not UIKit at all. The incompatibility is due to the fact that wkhtmltopdf uses an old version of UIKit as explained here.

Which means that in order to create a flex element you should use the non-standard -webkit-box-flex CSS property in place of the uk-flex class

ddgg
  • 145
  • 1
  • 10
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 23 '21 at 10:05