// copyrighted by CodelessPDF (Ab Advany) if(!window.codelesspdf) window.codelesspdf = async (server, token, path, options = {}) => { const iframe = document.createElement('iframe'); const overlay = document.createElement('div'); const debugBar = document.createElement('div'); if (options.debug) { Object.assign(overlay.style, { position: 'fixed', top: '0', left: '0', width: '100%', height: '100%', background: 'rgba(255, 255, 255, 0.7)', backdropFilter: 'blur(5px)', zIndex: '9998', visibility: options.debug ? 'visible' : 'hidden', }); document.body.appendChild(overlay); } const apply_iframe_style = (iframe, options) => { const base_style = { position: 'fixed', visibility: options.debug ? 'visible' : 'hidden', zIndex: '9999', }; const debug_style = options.debug ? { top: '40px', left: '40px', width: 'calc(100% - 80px)', height: 'calc(100% - 80px)', border: '1px solid black', } : { top: '0', left: '0', width: '100%', height: '100%', }; Object.assign(iframe.style, { ...base_style, ...debug_style }); }; apply_iframe_style(iframe, options); if (options.debug) { Object.assign(debugBar.style, { position: 'fixed', top: '0', left: '0', width: '100%', height: '30px', backgroundColor: 'red', color: 'white', textAlign: 'center', lineHeight: '30px', zIndex: '10000', }); debugBar.textContent = 'Generating PDF - Debug Mode - ' + path; document.body.appendChild(debugBar); } iframe.src = path ? window.location.origin + path : window.location.href; document.body.appendChild(iframe); iframe.onload = async () => { const scrollToBottomAndCheck = async (iframe) => { var lastHeight = -1; var intervalId = setInterval(async function () { var scrollHeight = iframe.contentWindow.document.body.scrollHeight; iframe.contentWindow.scrollTo(0, scrollHeight); if (scrollHeight === lastHeight) { clearInterval(intervalId); console.log('Reached the bottom or no more content is loading.'); } else { lastHeight = scrollHeight; } }, 1000); }; options.addScript && (() => { const script = document.createElement('script'); script.textContent = options.addScript; iframe.contentDocument.body.appendChild(script); })(); options.addStyle && (() => { const style = document.createElement('style'); style.textContent = options.style; iframe.contentDocument.head.appendChild(style); })(); if (options.scrollToBottom) { await scrollToBottomAndCheck(iframe); } if (options.pause) { console.log('pausing', options.pause) await new Promise((resolve) => setTimeout(resolve, options.pause)); } let dom_content = iframe.contentWindow.document.documentElement; const pdf_name = options.pdf_name || `output_${Date.now()}.pdf`; var response = await send_dom_content_to_server(server, dom_content, token, pdf_name, options.pdf_options, options.debug, options.onSuccess, options.onError); document.body.removeChild(iframe); document.body.removeChild(debugBar); document.body.removeChild(overlay); return response; }; const send_dom_content_to_server = async (server, dom_content, token, pdf_name, pdf_options = {}, debug = false, onSuccess, onError) => { var canvas_count = dom_content.querySelectorAll('canvas').length; const convert_canvases_to_images = (dom) => { dom.querySelectorAll('canvas').forEach((canvas) => { const img = document.createElement('img'); img.src = canvas.toDataURL(); console.log('changing canvas element to ', img.src); const canvasStyle = window.getComputedStyle(canvas); for (let property of canvasStyle) { img.style[property] = canvasStyle[property]; } img.classList.add('renderpdf_canvas_to_image'); img.width = canvas.width; img.height = canvas.height; canvas.parentNode.replaceChild(img, canvas); }); return dom; }; const add_app_query_flag = (dom) => { const script = document.createElement('script'); script.textContent = 'window.appQuery = true;'; dom.querySelector('head').insertBefore(script, dom.querySelector('head').firstChild); return dom; }; dom_content = add_app_query_flag(dom_content); if(canvas_count > 0) { await new Promise((resolve) => setTimeout(resolve, 2000)); dom_content = convert_canvases_to_images(dom_content); await new Promise((resolve) => setTimeout(resolve, 2000)); } dom_html = dom_content.outerHTML; if(debug) console.log('dom_html', dom_html); const pdf_content = btoa(encodeURIComponent(dom_html)); console.log('sending to server for pdf generation'); const url = `${server}/generate/html?token=${token}`; const root_url = `${window.location.protocol}//${window.location.host}`; const bodyContent = { pdf_content, pdf_options, pdf_name, root_url }; var response; try { response = await fetch(url, { method: 'POST', body: JSON.stringify(bodyContent) }); if (response.ok) { const json = await response.json(); if (onSuccess) onSuccess(json); return true } else { throw new Error('Failed to generate PDF'); } } catch (error) { try{ const json = await response.json(); console.error('Error generating PDF:', error); if (onError) onError(json.message); return false } catch(e) { console.error('Error executing CodelessPDF:', e); if (onError) onError('Error executing CodelessPDF'); } } }; }; if(!window.codelesspdf_page_break) window.codelesspdf_page_break = (option, element, debug) => { if(debug) console.log('CodelessPDF Debug handling page break', option, element, debug); add_codeless_pdf_css(); add_codeless_pdf_listener(); handle_page_break(option, element, debug); function handle_page_break(option, element, debug) { element.innerHTML = ''; element.style.visibility = 'hidden'; element.classList.remove('codelesspdf-page-break-force', 'codelesspdf-page-break-avoid'); if (option === 'force') { element.classList.add('codelesspdf-page-break-force'); element.style.pageBreakAfter = 'always'; } else if (option === 'avoid') { element.classList.add('codelesspdf-page-break-avoid'); element.parentNode.style.pageBreakInside = 'avoid'; } if (option === 'force' && debug) { element.classList.add('codelesspdf-debug-force'); } else if (option === 'avoid' && debug) { element.parentNode.classList.add('codelesspdf-debug-avoid'); } } function add_codeless_pdf_css() { const cssId = 'codeless_pdf_css'; if (!document.getElementById(cssId)) { const head = document.head || document.getElementsByTagName('head')[0]; const style = document.createElement('style'); style.id = cssId; style.type = 'text/css'; style.innerHTML = ` @media not print { .codelesspdf-debug-force { height: 0; width: 100%; border: none; border-top: 2px dotted #FC4C55; display: block !important; visibility: visible !important; } .codelesspdf-debug-avoid { border: 2px dashed #00CDFE; display: block !important; visibility: visible !important; } } `; head.appendChild(style); } } function add_codeless_pdf_listener() { const listenerId = 'codeless_pdf_listener'; if (!window[listenerId]) { window.addEventListener('beforeprint', function() { document.querySelectorAll('.codelesspdf-page-break-force, .codelesspdf-page-break-avoid').forEach(function(el) { el.classList.remove('codelesspdf-debug-force', 'codelesspdf-debug-avoid'); el.parentNode.classList.remove('codelesspdf-debug-force', 'codelesspdf-debug-avoid'); }); }); window[listenerId] = true; } } }