@onesy/utils
Version:
163 lines (128 loc) • 7.43 kB
JavaScript
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;