JSFiddle - React, Tailwind, and code Playground

by chucknelson

HTML

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.1.1/jspdf.umd.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.2.0/purify.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.js"></script>
</head>

<div id="myContainer">
  <h1>PDF Page!</h1>
  <p>You can try to make this a PDF!</p>
</div>

<button id="html2canvasButton">Use html2canvas only</button>
<button id="jsPDFButton">Use jsPDF</button>

CSS

.html2canvas-container {
    visibility: visible !important;
    position: unset !important;
    margin-top: 16px !important;
    border: 1px solid #ccc !important;
}

JavaScript

const testClonedDocContent = 'I am the cloned doc and what you should see in the generated PDF!';

function delay(t, v) {
  return new Promise(function(resolve) {
    setTimeout(resolve.bind(null, v), t)
  });
}

window.addEventListener('DOMContentLoaded', (event) => {
  document.getElementById('jsPDFButton').addEventListener('click', (event) => {
    const {
      jsPDF
    } = window.jspdf;
    const doc = new jsPDF('portrait', 'pt', 'a4');

    doc.html(document.getElementById('myContainer'), {
      html2canvas: {
        scale: 0.75,
        removeContainer: false,
        onclone: async function(htmldoc, arg2, arg3) {
          console.log(htmldoc);
          console.log(arg2);
          console.log(arg3);
          // OK, I think this is broken in jspdf
          // onclone is blocked, and the jspdf html callback waits as expected
          //...but jspdf seems to have generated the document before this even happens!
          // ...or it's not correctly using the cloned doc??
          await delay(1000);
          htmldoc.innerHTML = testClonedDocContent;
          await delay(1000);
        }
      },
      callback: function(doc) {
        //doc.save('myPage');
      }
    });
  });

  document.getElementById('html2canvasButton').addEventListener('click', (event) => {
    const {
      jsPDF
    } = window.jspdf;
    const doc = new jsPDF('portrait', 'pt', 'a4');

    // Try the manual html2canvas => PDF route
    // This works, but doesn't honor CSS as well?
    html2canvas(document.getElementById('myContainer'), {
      removeContainer: false,
      onclone: async function(htmldoc, arg2, arg3) {
        console.log(htmldoc);
        console.log(arg2);
        console.log(arg3);

        await delay(1000);
        htmldoc.getElementById('myContainer').innerHTML = testClonedDocContent;
        await delay(1000);
      }
    }).then(function(canvas) {
      console.log('Canvas rendered!');
      const img = canvas.toDataURL('image/png');
     ...