UNPKG

@onesy/utils

Version:
163 lines (128 loc) 7.43 kB
import is from './is'; import isEnvironment from './isEnvironment'; import fileToValue from './fileToValue'; import canvasCrop from './canvasCrop'; import download from './download'; import unique from './unique'; const serialize = node => new XMLSerializer().serializeToString(node); const image = uri => new Promise((resolve, reject) => { const img = document.createElement('img'); const method = () => resolve(img); img.onload = method; img.onerror = () => resolve(''); img.src = uri; }); const getData = async function (url) { let version = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'datauri'; try { const response = await fetch(url); const blob = await response.blob(); return await fileToValue(blob, version); } catch (error) {} }; const optionsDefault = { response: 'canvas', x: 0, y: 0, datauri: { type: 'image/png', quality: 1 }, download: { name: 'onesy-image.png', type: 'image/png', quality: 1 }, styleSheets: true, urls: true, images: true, links: true }; const elementToCanvas = async (element_, options_) => { const options = { ...optionsDefault, ...options_ }; if (isEnvironment('browser')) { if (element_ !== undefined && is('element', element_)) { var _options$image, _options$image2, _options$image3, _options$image4, _options$image5, _options$image6, _options$image7, _options$image8; const element = element_.cloneNode(true); if (is('array', options.filter)) { options.filter.forEach(item => { const items = Array.from(element.querySelectorAll(item)); items.forEach(item_ => is('function', item_.remove) && item_.remove()); }); } let elementXML = serialize(element); let urls = []; let styles = ""; let links = ""; let css = ""; const linksAdd = {}; // Element urls if (options.urls) { urls = (elementXML.match(/url\((.*?)\)/gi) || []).map(item => item.replace(/url\(|'|"|\)/gi, '')); for (const url of unique(urls)) { const value = await getData(url); if (value) elementXML = elementXML.replaceAll(url, value); } } // Images if (options.images) { urls = (elementXML.match(/src=("|'|`)(.*?)("|'|`)/gi) || []).map(item => item.replace(/src=|'|"||`/gi, '')); for (const src of unique(urls)) { const value = await getData(src); if (value) elementXML = elementXML.replaceAll(src, value); } } // Links if (options.links) { const links_ = Array.from(window.document.querySelectorAll('link')); for (const link of links_) { if (!linksAdd[link.href] && ['stylesheet'].includes(link.rel)) { const value = await getData(link.href, 'text'); if (value) { linksAdd[link.href] = true; links += "<style>".concat(value, "</style>"); } } } } // StyleSheets for (const styleSheet of window.document.styleSheets) { if (!styleSheet.href || styleSheet.href.startsWith(window.location.origin)) { for (let { cssText } of styleSheet.cssRules) css += cssText; } } styles = "\n <style>\n noscript {\n display: none;\n }\n </style>\n\n ".concat(links, "\n\n <style>").concat(css, "</style>\n "); // Styles urls if (options.urls) { urls = (styles.match(/url\((.*?)\)/gi) || []).map(item => item.replace(/url\(|'|"|\)/gi, '')); for (const url of unique(urls)) { const value = await getData(url); if (value) styles = styles.replaceAll(url, value); } } const width = options.width !== undefined ? options.width : element_.offsetWidth; const height = options.height !== undefined ? options.height : element_.offsetHeight; const svg = "<svg xmlns='http://www.w3.org/2000/svg' width='".concat(((_options$image = options.image) === null || _options$image === void 0 ? void 0 : _options$image.width) !== undefined ? (_options$image2 = options.image) === null || _options$image2 === void 0 ? void 0 : _options$image2.width : width, "' height='").concat(((_options$image3 = options.image) === null || _options$image3 === void 0 ? void 0 : _options$image3.height) !== undefined ? (_options$image4 = options.image) === null || _options$image4 === void 0 ? void 0 : _options$image4.height : height, "'>\n ").concat(styles, "\n\n <foreignObject x='0' y='0' width='").concat(((_options$image5 = options.image) === null || _options$image5 === void 0 ? void 0 : _options$image5.width) !== undefined ? (_options$image6 = options.image) === null || _options$image6 === void 0 ? void 0 : _options$image6.width : width, "' height='").concat(((_options$image7 = options.image) === null || _options$image7 === void 0 ? void 0 : _options$image7.height) !== undefined ? (_options$image8 = options.image) === null || _options$image8 === void 0 ? void 0 : _options$image8.height : height, "'>\n ").concat(elementXML, "\n </foreignObject>\n </svg>"); if (options.response === 'svg') return svg; const uri = "data:image/svg+xml;base64,".concat(btoa(unescape(encodeURIComponent(svg)))); if (options.response === 'svg-datauri') return uri; const img = await image(uri); if (img) { var _options$image9, _options$image10, _options$image11, _options$image12, _options$datauri, _options$datauri2; let canvas = window.document.createElement('canvas'); canvas.width = width; canvas.height = height; const context = canvas.getContext('2d'); context.drawImage(img, options.x, options.y, ((_options$image9 = options.image) === null || _options$image9 === void 0 ? void 0 : _options$image9.width) !== undefined ? (_options$image10 = options.image) === null || _options$image10 === void 0 ? void 0 : _options$image10.width : img.width, ((_options$image11 = options.image) === null || _options$image11 === void 0 ? void 0 : _options$image11.height) !== undefined ? (_options$image12 = options.image) === null || _options$image12 === void 0 ? void 0 : _options$image12.height : img.height); if (options.crop) canvas = canvasCrop(canvas, options.crop.x, options.crop.y, options.crop.width, options.crop.height); if (options.response === 'canvas') return canvas; if (options.response === 'datauri') return canvas.toDataURL((_options$datauri = options.datauri) === null || _options$datauri === void 0 ? void 0 : _options$datauri.type, (_options$datauri2 = options.datauri) === null || _options$datauri2 === void 0 ? void 0 : _options$datauri2.quality); if (options.response === 'download') { var _options$download, _options$download2, _options$download3; const value = canvas.toDataURL((_options$download = options.download) === null || _options$download === void 0 ? void 0 : _options$download.type, (_options$download2 = options.download) === null || _options$download2 === void 0 ? void 0 : _options$download2.quality); // Image download((_options$download3 = options.download) === null || _options$download3 === void 0 ? void 0 : _options$download3.name, value); } } } } }; export default elementToCanvas;