UNPKG

prntr

Version:

A tiny javascript library to help printing from the web. Print.js but modern and maintained.

852 lines (638 loc) 28.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var Bowser = require('bowser'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var Bowser__default = /*#__PURE__*/_interopDefault(Bowser); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; } function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); } var browser = typeof window !== 'undefined' ? Bowser__default["default"].getParser(window.navigator.userAgent) : undefined; var browserName = browser === null || browser === void 0 ? void 0 : browser.getBrowserName(); var platform = browser === null || browser === void 0 ? void 0 : browser.getPlatformType(); var engine = browser === null || browser === void 0 ? void 0 : browser.getEngine().name; var Browser = { /* Firefox */ isFirefox: browserName === 'Firefox', /* Internet Explorer */ isIE: browserName === 'Internet Explorer', /* Edge */ isEdge: browserName === 'Microsoft Edge', /* Edge HTML Engine detection */ isEdgeHTML: browserName === 'Microsoft Edge' && engine === 'EdgeHTML', /* Chrome */ isChrome: browserName === 'Chrome', /* Safari */ isSafari: browserName === 'Safari', /* ipad */ isIpad: typeof window !== 'undefined' && navigator.maxTouchPoints && navigator.maxTouchPoints > 2 && navigator.platform.includes('MacIntel'), /* iphone */ isIphone: browserName === 'Safari' && platform === 'mobile', /* Chrome mobile */ isChromeMobile: browserName === 'Chrome' && platform === 'mobile', /* Chrome on iOs */ isIosChrome: browserName === 'Chrome' && typeof window !== 'undefined' && navigator.userAgent.includes('CriOS') }; var Browser$1 = Browser; function removeIframe(frameId) { var delay = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 300; var iframe = document.getElementById(frameId); setTimeout(function () { return iframe === null || iframe === void 0 ? void 0 : iframe.remove(); }, delay); } function cleanupFast(config) { var onLoadingStart = config.onLoadingStart, onLoadingEnd = config.onLoadingEnd, printable = config.printable, frameId = config.frameId, iframeRemovalDelay = config.iframeRemovalDelay; // Check for a finished loading hook function onLoadingEnd === null || onLoadingEnd === void 0 ? void 0 : onLoadingEnd(); // If preloading pdf files, clean blob url if (onLoadingStart && typeof printable === 'string') window.URL.revokeObjectURL(printable); // Remove Iframe removeIframe(frameId, iframeRemovalDelay); } function cleanUp(config) { var onLoadingEnd = config.onLoadingEnd, onLoadingStart = config.onLoadingStart, onPrintDialogClose = config.onPrintDialogClose, frameId = config.frameId, printable = config.printable, iframeRemovalDelay = config.iframeRemovalDelay; // Check for a finished loading hook function onLoadingEnd === null || onLoadingEnd === void 0 ? void 0 : onLoadingEnd(); // If preloading pdf files, clean blob url if (onLoadingStart && typeof printable === 'string') window.URL.revokeObjectURL(printable); var event = 'mouseover'; if (Browser$1.isChrome || Browser$1.isEdge && !Browser$1.isEdgeHTML || Browser$1.isFirefox) { // Ps.: Firefox will require an extra click in the document to fire the focus event. event = 'focus'; } var handler = function handler() { // Make sure the event only happens once. window.removeEventListener(event, handler); // Run onPrintDialogClose callback onPrintDialogClose === null || onPrintDialogClose === void 0 ? void 0 : onPrintDialogClose(); // Remove iframe from the DOM removeIframe(frameId, iframeRemovalDelay); }; window.addEventListener(event, handler); } function print(config, printFrame, printableElement) { var type = config.type, frameId = config.frameId, style = config.style; // Append iframe element to document body document.getElementsByTagName('body')[0].appendChild(printFrame); // Get iframe element var iframeElement = document.getElementById(frameId); if (!iframeElement) return; // Wait for iframe to load all content iframeElement.onload = function () { if (type === 'pdf') { // Add a delay for Firefox. In my tests, 1000ms was sufficient but 100ms was not if (Browser$1.isFirefox) { setTimeout(function () { return performPrint(iframeElement, config); }, 1000); } else { performPrint(iframeElement, config); } return; } // Get iframe element document var printDocument = getPrintDocument(iframeElement); if (!printDocument) return; // Append printable element to the iframe body if (printableElement) printDocument.body.appendChild(printableElement); // Add custom style addStyle(style, printDocument); // If printing images, wait for them to load inside the iframe var images = printDocument.getElementsByTagName('img'); if (images.length > 0) { loadIframeImages(Array.from(images)).then(function () { return performPrint(iframeElement, config); }); } else { performPrint(iframeElement, config); } }; } function performPrint(iframeElement, config) { var onError = config.onError; try { // Probably allowing to make this work in Firefox without needing to focus the window again if (!Browser$1.isFirefox) { iframeElement.focus(); } // If Edge or IE, try catch with execCommand if (Browser$1.isEdgeHTML || Browser$1.isIE) { try { var _iframeElement$conten; (_iframeElement$conten = iframeElement.contentWindow) === null || _iframeElement$conten === void 0 ? void 0 : _iframeElement$conten.document.execCommand('print', true); } catch (e) { var _iframeElement$conten2; (_iframeElement$conten2 = iframeElement.contentWindow) === null || _iframeElement$conten2 === void 0 ? void 0 : _iframeElement$conten2.print(); } } else { var _iframeElement$conten3; // Other browsers (_iframeElement$conten3 = iframeElement.contentWindow) === null || _iframeElement$conten3 === void 0 ? void 0 : _iframeElement$conten3.print(); } } catch (error) { onError === null || onError === void 0 ? void 0 : onError(error); } finally { if (Browser$1.isFirefox) { // Move the iframe element off-screen and make it invisible iframeElement.style.visibility = 'hidden'; iframeElement.style.left = '-1px'; } setTimeout(function () { return cleanUp(config); }, 100); } } function loadIframeImages(images) { var promises = images.map(function (image) { if (!image.src || image.src === window.location.href) return undefined; return loadIframeImage(image); }); return Promise.all(promises); } function loadIframeImage(image) { return new Promise(function (resolve) { var pollImage = function pollImage() { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition !image || typeof image.naturalWidth === 'undefined' || image.naturalWidth === 0 || !image.complete ? setTimeout(pollImage, 500) : resolve(image); }; pollImage(); }); } function addStyle(style, printDocument) { if (!style) return; // Create style element var styleEl = document.createElement('style'); styleEl.innerHTML = style; // Append style element to iframe's head printDocument.head.appendChild(styleEl); } function getPrintDocument(iframe) { var printDocumentWindow = iframe.contentWindow || iframe.contentDocument; var printDocument = printDocumentWindow && 'document' in printDocumentWindow ? printDocumentWindow.document : null; return printDocument; } function addHeader(printElement, header, headerStyle) { // Create the header container div var headerContainer = document.createElement('div'); if (!header) { return printElement.insertBefore(headerContainer, printElement.childNodes[0]); } // Check if the header is text or raw html if (isRawHTML(header)) { headerContainer.innerHTML = header; } else { // Create header element var headerElement = document.createElement('h1'); // Create header text node var headerNode = document.createTextNode(header); // Build and style headerElement.appendChild(headerNode); if (headerStyle) headerElement.setAttribute('style', headerStyle); headerContainer.appendChild(headerElement); } printElement.insertBefore(headerContainer, printElement.childNodes[0]); } function isRawHTML(raw) { // eslint-disable-next-line prefer-regex-literals var regexHtml = new RegExp('<([A-Za-z][A-Za-z0-9]*)\\b[^>]*>(.*?)</\\1>'); return regexHtml.test(raw); } function html(config, printFrame) { var printable = config.printable, header = config.header, headerStyle = config.headerStyle; // Get the DOM printable element var printElement = document.getElementById(printable); // Check if the element exists if (!printElement) { window.console.error('Invalid HTML element id: ' + printable); return; } // Clone the target element including its children (if available) var clonedPrintable = cloneElement(printElement, config); // Add header if (header) { addHeader(clonedPrintable, header, headerStyle); } // Print html element contents print(config, printFrame, clonedPrintable); } function collectStyles(element, config) { var targetStyle = config.targetStyle, targetStyles = config.targetStyles; var win = document.defaultView || window; // String variable to hold styling for each element var elementStyle = ''; // Loop over computed styles var styles = win.getComputedStyle(element, ''); for (var key = 0; key < styles.length; key++) { // Check if style should be processed if (targetStyles !== null && targetStyles !== void 0 && targetStyles.includes('*') || targetStyle !== null && targetStyle !== void 0 && targetStyle.includes(styles[key]) || targetStylesMatch(targetStyles || [], styles[key])) { if (styles.getPropertyValue(styles[key])) { elementStyle += "".concat(styles[key], ":").concat(styles.getPropertyValue(styles[key]), ";"); } } } return elementStyle; } function targetStylesMatch(styles, value) { for (var i = 0; i < styles.length; i++) { if (_typeof(value) === 'object' && value.includes(styles[i])) return true; } return false; } function cloneElement(element, config) { var _getContext; var _config$ignoreElement = config.ignoreElements, ignoreElements = _config$ignoreElement === void 0 ? [] : _config$ignoreElement, shouldScanStyles = config.scanStyles; // Clone the main node (if not already inside the recursion process) var clone = element.cloneNode(); // Loop over and process the children elements / nodes (including text nodes) var childNodesArray = Array.prototype.slice.call(element.childNodes); for (var i = 0; i < childNodesArray.length; i++) { // Check if we are skipping the current element if (ignoreElements.includes(childNodesArray[i].id)) { continue; } // Clone the child element var clonedChild = cloneElement(childNodesArray[i], config); // Attach the cloned child to the cloned parent node clone.appendChild(clonedChild); } // Get all styling for print element (for nodes of type element only) if (shouldScanStyles && element.nodeType === 1) { clone.setAttribute('style', collectStyles(element, config)); } // Check if the element needs any state processing (copy user input data) switch (element.tagName) { case 'SELECT': // Copy the current selection value to its clone clone.value = element.value; break; case 'CANVAS': // Copy the canvas content to its clone (_getContext = clone.getContext('2d')) === null || _getContext === void 0 ? void 0 : _getContext.drawImage(element, 0, 0); break; } return clone; } function image(config, printFrame) { var printable = config.printable, header = config.header, headerStyle = config.headerStyle; // Check if we are printing one image or multiple images // Create array with one image var images = Array.isArray(printable) ? printable : [printable]; // Create printable element (container) var printableElement = document.createElement('div'); // Create all image elements and append them to the printable container appendImages(images, printableElement); // Check if we are adding a print header if (header) { addHeader(printableElement, header, headerStyle); } // Print image print(config, printFrame, printableElement); } function appendImages(images, printableElement) { images.forEach(function (src) { // Create the image element var img = document.createElement('img'); // Set image src with the file url img.src = src; // The following block is for Firefox, which for some reason requires the image's src to be fully qualified in // order to print it if (Browser$1.isFirefox) { var fullyQualifiedSrc = img.src; img.src = fullyQualifiedSrc; } // Create the image wrapper var imageWrapper = document.createElement('div'); // Append image to the wrapper element imageWrapper.appendChild(img); // Append wrapper to the printable element printableElement.appendChild(imageWrapper); }); } function json(config, printFrame) { var printable = config.printable, shouldRepeatTableHeader = config.repeatTableHeader, properties = config.properties, header = config.header, headerStyle = config.headerStyle; // Check if we received proper data if (_typeof(printable) !== 'object') { throw new Error('Invalid javascript data object (JSON).'); } // Validate repeatTableHeader if (typeof shouldRepeatTableHeader !== 'boolean') { throw new Error('Invalid value for repeatTableHeader attribute (JSON).'); } // Validate properties if (!properties || !Array.isArray(properties)) { throw new Error('Invalid properties array for your JSON data.'); } // We will format the property objects var mappedConfig = getConfigWithMappedProperties(config, properties); // Create a print container element var printableElement = document.createElement('div'); // Build the printable html data printableElement.innerHTML += jsonToHTML(mappedConfig); // Check if we are adding a print header if (header) { addHeader(printableElement, header, headerStyle); } // Print the json data print(mappedConfig, printFrame, printableElement); } function capitalizePrint(str) { return str.charAt(0).toUpperCase() + str.slice(1); } function getConfigWithMappedProperties(config, properties) { var mappedProperties = properties.map(function (property) { return { field: _typeof(property) === 'object' ? property.field : property, displayName: _typeof(property) === 'object' ? property.displayName : property, columnSize: _typeof(property) === 'object' && property.columnSize ? "".concat(property.columnSize, ";") : "".concat(100 / properties.length, "%;") }; }); return _objectSpread2(_objectSpread2({}, config), {}, { properties: mappedProperties }); } function jsonToHTML(_ref) { var printable = _ref.printable, properties = _ref.properties, repeatTableHeader = _ref.repeatTableHeader, gridHeaderStyle = _ref.gridHeaderStyle, gridStyle = _ref.gridStyle; // Get the row and column data var data = printable; // Create a html table var htmlData = '<table style="border-collapse: collapse; width: 100%;">'; // Check if the header should be repeated if (repeatTableHeader) { htmlData += '<thead>'; } // Add the table header row htmlData += '<tr>'; // Add the table header columns for (var a = 0; a < properties.length; a++) { // eslint-disable-next-line max-len htmlData += '<th style="width:' + properties[a].columnSize + ';' + gridHeaderStyle + '">' + capitalizePrint(properties[a].displayName) + '</th>'; } // Add the closing tag for the table header row htmlData += '</tr>'; // If the table header is marked as repeated, add the closing tag if (repeatTableHeader) { htmlData += '</thead>'; } // Create the table body htmlData += '<tbody>'; // Add the table data rows for (var i = 0; i < data.length; i++) { // Add the row starting tag htmlData += '<tr>'; // Print selected properties only // Not the nicest piece of code.. for (var n = 0; n < properties.length; n++) { var stringData = data[i]; // Support nested objects var property = properties[n].field.split('.'); if (property.length > 1) { for (var p = 0; p < property.length; p++) { // @ts-ignore stringData = stringData[property[p]]; } } else { // @ts-ignore stringData = stringData[properties[n].field]; } // Add the row contents and styles htmlData += '<td style="width:' + properties[n].columnSize + gridStyle + '">' + stringData + '</td>'; } // Add the row closing tag htmlData += '</tr>'; } // Add the table and body closing tags htmlData += '</tbody></table>'; return htmlData; } function pdf(config, printFrame) { var hasBase64 = config.base64, printable = config.printable; // Check if we have base64 data if (hasBase64) { var bytesArray = Uint8Array.from(window.atob(printable), function (c) { return c.charCodeAt(0); }); createBlobAndPrint$1(config, printFrame, bytesArray); return; } // Get the file through a http request (Preload) createPdfRequest(config, printFrame); } function createPdfRequest(config, printFrame) { var printable = config.printable, onError = config.onError; // Format pdf url var pdfUrl = getPdfUrl(printable); // Request pdf url var req = new window.XMLHttpRequest(); req.responseType = 'arraybuffer'; req.addEventListener('error', function () { cleanUp(_objectSpread2(_objectSpread2({}, config), {}, { printable: pdfUrl })); onError === null || onError === void 0 ? void 0 : onError(req.statusText, req); // Since we don't have a pdf document available, we will stop the print job }); req.addEventListener('load', function () { // Check for errors if (![200, 201].includes(req.status)) { cleanUp(config); onError === null || onError === void 0 ? void 0 : onError(req.statusText, req); // Since we don't have a pdf document available, we will stop the print job return; } // Print requested document createBlobAndPrint$1(config, printFrame, req.response); }); req.open('GET', printable, true); req.send(); } function getPdfUrl(printable) { return /^(blob|http|\/\/)/i.test(printable) ? printable : window.location.origin + (!printable.startsWith('/') ? '/' + printable : printable); } function createBlobAndPrint$1(config, printFrame, data) { // Pass response or base64 data to a blob and create a local object url var localPdfBlb = new window.Blob([data], { type: 'application/pdf' }); var localPdf = window.URL.createObjectURL(localPdfBlb); // Set iframe src with pdf document url printFrame.setAttribute('src', localPdf); print(config, printFrame, undefined); } function rawHtml(config, printFrame) { var printable = config.printable; // Create printable element (container) var printableElement = document.createElement('div'); printableElement.setAttribute('style', 'width:100%'); // Set our raw html as the printable element inner html content printableElement.innerHTML = printable; // Print html contents print(config, printFrame, printableElement); } var printTypes = ['pdf', 'html', 'image', 'json', 'raw-html']; // Define default configs var baseConfig = { type: 'pdf', documentTitle: 'Document', frameId: 'prntr', iframeRemovalDelay: 300, onError: function onError(error) { throw new Error(error); } }; var baseIPdfConfig = { base64: false }; var baseIHtmlConfig = { targetStyle: ['clear', 'display', 'width', 'min-width', 'height', 'min-height', 'max-height'], targetStyles: ['border', 'box', 'break', 'text-decoration'], ignoreElements: [], scanStyles: true }; var baseJsonConfig = { gridHeaderStyle: 'font-weight: bold; padding: 5px; border: 1px solid #dddddd;', gridStyle: 'border: 1px solid lightgray; margin-bottom: -1px;', repeatTableHeader: true }; // Main initializer function prntr(config) { var printConfig = _objectSpread2(_objectSpread2({}, baseConfig), config); // Process parameters validateConfig(printConfig); // Start start(printConfig); } function validateConfig(_ref) { var type = _ref.type, printable = _ref.printable; // Validate printable if (!printable) { throw new Error('Missing printable information.'); } // Validate type if (typeof type !== 'string' || !printTypes.includes(type.toLowerCase())) { throw new Error('Invalid print type. Available types are: pdf, html, raw-html, image and json.'); } } function start(config) { var onLoadingStart = config.onLoadingStart, frameId = config.frameId; // Check for a print start hook function onLoadingStart === null || onLoadingStart === void 0 ? void 0 : onLoadingStart(); // To prevent duplication and issues, remove any used printFrame from the DOM clearPrintFrames(frameId); // Create a new iframe for the print job var printFrame = getPrintFrame(config); // Check printable type switch (config.type) { case 'pdf': startPdf(_objectSpread2(_objectSpread2({}, baseIPdfConfig), config), printFrame); break; case 'image': startOther(config, image(config, printFrame)); break; case 'html': startOther(config, html(_objectSpread2(_objectSpread2({}, baseIHtmlConfig), config), printFrame)); break; case 'raw-html': startOther(config, rawHtml(config, printFrame)); break; case 'json': startOther(config, json(_objectSpread2(_objectSpread2({}, baseJsonConfig), config), printFrame)); break; } } function createBlobAndPrint(data) { // Pass response or base64 data to a blob and create a local object url var localPdfBlb = new window.Blob([data], { type: 'application/pdf' }); return window.URL.createObjectURL(localPdfBlb); } function getBlob(printable) { return Uint8Array.from(window.atob(printable), function (c) { return c.charCodeAt(0); }); } function getFallbackPrintable(_ref2) { var printable = _ref2.printable, fallbackPrintable = _ref2.fallbackPrintable, base64 = _ref2.base64; if (fallbackPrintable) { return base64 ? createBlobAndPrint(getBlob(fallbackPrintable)) : fallbackPrintable; } return base64 ? createBlobAndPrint(getBlob(printable)) : printable; } function printFallback(config, hasHref) { var fallbackPrintable = getFallbackPrintable(config); if (hasHref) { window.location.href = fallbackPrintable; return; } var win = window.open(fallbackPrintable, '_blank', 'toolbar=yes,scrollbars=yes,menubar=no,location=no,resizable=yes'); win === null || win === void 0 ? void 0 : win.focus(); } function startOther(config, callback) { var onLoadingEnd = config.onLoadingEnd, onIncompatibleBrowser = config.onIncompatibleBrowser, onError = config.onError, frameId = config.frameId; // Check browser support for pdf and if not supported we will just open the pdf file instead if (Browser$1.isChromeMobile || Browser$1.isIosChrome) { try { console.info('Prntr doesn\'t support printing of Image elements in Chrome mobile'); clearPrintFrames(frameId); onIncompatibleBrowser === null || onIncompatibleBrowser === void 0 ? void 0 : onIncompatibleBrowser(); } catch (error) { onError === null || onError === void 0 ? void 0 : onError(error); } finally { onLoadingEnd === null || onLoadingEnd === void 0 ? void 0 : onLoadingEnd(); } return; } return callback; } function startPdf(config, printFrame) { var onLoadingEnd = config.onLoadingEnd, onIncompatibleBrowser = config.onIncompatibleBrowser, onError = config.onError; // Check browser support for pdf and if not supported we will just open the pdf file instead if (Browser$1.isIE || Browser$1.isSafari || Browser$1.isChromeMobile || Browser$1.isIosChrome) { try { if (Browser$1.isIE) console.info('Prntr doesn\'t support PDF printing in Internet Explorer'); if (Browser$1.isChromeMobile || Browser$1.isIosChrome) console.info('Prntr doesn\'t support PDF printing in Chrome on Mobile'); if (Browser$1.isSafari && !config.base64) console.info('Prntr doesn\'t support PDF printing in Safari'); if (Browser$1.isSafari && !Browser$1.isIpad && config.base64) console.info('Prntr doesn\'t support PDF Base64 printing in Safari on Desktop or Iphone'); var hasHref = !!Browser$1.isChromeMobile || config.base64; printFallback(config, hasHref); cleanupFast(config); onIncompatibleBrowser === null || onIncompatibleBrowser === void 0 ? void 0 : onIncompatibleBrowser(); } catch (error) { onError === null || onError === void 0 ? void 0 : onError(error); } finally { onLoadingEnd === null || onLoadingEnd === void 0 ? void 0 : onLoadingEnd(); } return; } pdf(config, printFrame); } function clearPrintFrames(frameId) { var _usedFrame$parentNode; var usedFrame = document.getElementById(frameId); if (!usedFrame) return; (_usedFrame$parentNode = usedFrame.parentNode) === null || _usedFrame$parentNode === void 0 ? void 0 : _usedFrame$parentNode.removeChild(usedFrame); } function getPrintFrame(_ref3) { var type = _ref3.type, documentTitle = _ref3.documentTitle, css = _ref3.css, frameId = _ref3.frameId; // Create a new iframe for the print job var printFrame = document.createElement('iframe'); // Set iframe element id printFrame.setAttribute('id', frameId); if (Browser$1.isFirefox) { // Set the iframe to be is visible on the page (guaranteed by fixed position) but hidden using opacity 0, because // this works in Firefox. The height needs to be sufficient for some part of the document other than the PDF // viewer's toolbar to be visible in the page // eslint-disable-next-line max-len printFrame.setAttribute('style', 'width: 1px; height: 100px; position: fixed; left: 0; top: 0; opacity: 0; border-width: 0; margin: 0; padding: 0'); } else { // Hide the iframe in other browsers printFrame.setAttribute('style', 'visibility: hidden; height: 0; width: 0; position: absolute; border: 0'); } // For non pdf printing, pass an html document string to srcdoc (force onload callback) if (type !== 'pdf') { printFrame.srcdoc = "<html><head><title>".concat(documentTitle, "</title>"); // Attach css files if (css) { var styles = Array.isArray(css) ? css : [css]; // Create link tags for each css file styles.forEach(function (file) { printFrame.srcdoc += "<link rel=\"stylesheet\" href=\"".concat(file, "\">"); }); } printFrame.srcdoc += '</head><body></body></html>'; } return printFrame; } if (typeof window !== 'undefined') { window.prntr = prntr; } exports["default"] = prntr;