'use strict'; (function () { var out$ = typeof exports != 'undefined' && exports || typeof define != 'undefined' && {} || this || window; if (typeof define !== 'undefined') define(function () { return out$; }); var xmlns = 'http://www.w3.org/2000/xmlns/'; var doctype = ']>'; var urlRegex = /url\(["']?(.+?)["']?\)/; var fontFormats = { woff2: 'font/woff2', woff: 'font/woff', otf: 'application/x-font-opentype', ttf: 'application/x-font-ttf', eot: 'application/vnd.ms-fontobject', sfnt: 'application/font-sfnt', svg: 'image/svg+xml' }; var isElement = function isElement(obj) { return obj instanceof HTMLElement || obj instanceof SVGElement; }; var requireDomNode = function requireDomNode(el) { if (!isElement(el)) throw new Error('an HTMLElement or SVGElement is required; got ' + el); }; var isExternal = function isExternal(url) { return url && url.lastIndexOf('http', 0) === 0 && url.lastIndexOf(window.location.host) === -1; }; var getFontMimeTypeFromUrl = function getFontMimeTypeFromUrl(fontUrl) { var formats = Object.keys(fontFormats).filter(function (extension) { return fontUrl.indexOf('.' + extension) > 0; }).map(function (extension) { return fontFormats[extension]; }); if (formats) return formats[0]; console.error('Unknown font format for ' + fontUrl + '. Fonts may not be working correctly.'); return 'application/octet-stream'; }; var arrayBufferToBase64 = function arrayBufferToBase64(buffer) { var binary = ''; var bytes = new Uint8Array(buffer); for (var i = 0; i < bytes.byteLength; i++) { binary += String.fromCharCode(bytes[i]); }return window.btoa(binary); }; var getDimension = function getDimension(el, clone, dim) { var v = el.viewBox && el.viewBox.baseVal && el.viewBox.baseVal[dim] || clone.getAttribute(dim) !== null && !clone.getAttribute(dim).match(/%$/) && parseInt(clone.getAttribute(dim)) || el.getBoundingClientRect()[dim] || parseInt(clone.style[dim]) || parseInt(window.getComputedStyle(el).getPropertyValue(dim)); return typeof v === 'undefined' || v === null || isNaN(parseFloat(v)) ? 0 : v; }; var getDimensions = function getDimensions(el, clone, width, height) { if (el.tagName === 'svg') return { width: width || getDimension(el, clone, 'width'), height: height || getDimension(el, clone, 'height') };else if (el.getBBox) { var _el$getBBox = el.getBBox(); var x = _el$getBBox.x; var y = _el$getBBox.y; var _width = _el$getBBox.width; var _height = _el$getBBox.height; return { width: x + _width, height: y + _height }; } }; var reEncode = function reEncode(data) { return decodeURIComponent(encodeURIComponent(data).replace(/%([0-9A-F]{2})/g, function (match, p1) { var c = String.fromCharCode('0x' + p1); return c === '%' ? '%25' : c; })); }; var uriToBlob = function uriToBlob(uri) { var byteString = window.atob(uri.split(',')[1]); var mimeString = uri.split(',')[0].split(':')[1].split(';')[0]; var buffer = new ArrayBuffer(byteString.length); var intArray = new Uint8Array(buffer); for (var i = 0; i < byteString.length; i++) { intArray[i] = byteString.charCodeAt(i); } return new Blob([buffer], { type: mimeString }); }; var query = function query(el, selector) { if (!selector) return; try { return el.querySelector(selector) || el.parentNode && el.parentNode.querySelector(selector); } catch (err) { //console.warn('Invalid CSS selector "' + selector + '"', err); } }; var detectCssFont = function detectCssFont(rule) { // Match CSS font-face rules to external links. // @font-face { // src: local('Abel'), url(https://fonts.gstatic.com/s/abel/v6/UzN-iejR1VoXU2Oc-7LsbvesZW2xOQ-xsNqO47m55DA.woff2); // } var match = rule.cssText.match(urlRegex); var url = match && match[1] || ''; if (!url || url.match(/^data:/) || url === 'about:blank') return; var fullUrl = url.startsWith('../') ? rule.href + '/../' + url : url.startsWith('./') ? rule.href + '/.' + url : url; return { text: rule.cssText, format: getFontMimeTypeFromUrl(fullUrl), url: fullUrl }; }; var inlineImages = function inlineImages(el) { return Promise.all(Array.from(el.querySelectorAll('image')).map(function (image) { var href = image.getAttributeNS('http://www.w3.org/1999/xlink', 'href') || image.getAttribute('href'); if (!href) return Promise.resolve(null); if (isExternal(href)) { href += (href.indexOf('?') === -1 ? '?' : '&') + 't=' + new Date().valueOf(); } return new Promise(function (resolve, reject) { var canvas = document.createElement('canvas'); var img = new Image(); img.crossOrigin = 'anonymous'; img.src = href; img.onerror = function () { return reject(new Error('Could not load ' + href)); }; img.onload = function () { canvas.width = img.width; canvas.height = img.height; canvas.getContext('2d').drawImage(img, 0, 0); image.setAttributeNS('http://www.w3.org/1999/xlink', 'href', canvas.toDataURL('image/png')); resolve(true); }; }); })); }; var cachedFonts = {}; var inlineFonts = function inlineFonts(fonts) { return Promise.all(fonts.map(function (font) { return new Promise(function (resolve, reject) { if (cachedFonts[font.url]) return resolve(cachedFonts[font.url]); var req = new XMLHttpRequest(); req.addEventListener('load', function () { // TODO: it may also be worth it to wait until fonts are fully loaded before // attempting to rasterize them. (e.g. use https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet) var fontInBase64 = arrayBufferToBase64(req.response); var fontUri = font.text.replace(urlRegex, 'url("data:' + font.format + ';base64,' + fontInBase64 + '")') + '\n'; cachedFonts[font.url] = fontUri; resolve(fontUri); }); req.addEventListener('error', function (e) { console.warn('Failed to load font from: ' + font.url, e); cachedFonts[font.url] = null; resolve(null); }); req.addEventListener('abort', function (e) { console.warn('Aborted loading font from: ' + font.url, e); resolve(null); }); req.open('GET', font.url); req.responseType = 'arraybuffer'; req.send(); }); })).then(function (fontCss) { return fontCss.filter(function (x) { return x; }).join(''); }); }; var cachedRules = null; var styleSheetRules = function styleSheetRules() { if (cachedRules) return cachedRules; return cachedRules = Array.from(document.styleSheets).map(function (sheet) { try { return sheet.cssRules; } catch (e) { console.warn('Stylesheet could not be loaded: ' + sheet.href); } }); }; var inlineCss = function inlineCss(el, options) { var _ref = options || {}; var selectorRemap = _ref.selectorRemap; var modifyStyle = _ref.modifyStyle; var modifyCss = _ref.modifyCss; var fonts = _ref.fonts; var generateCss = modifyCss || function (selector, properties) { var sel = selectorRemap ? selectorRemap(selector) : selector; var props = modifyStyle ? modifyStyle(properties) : properties; return sel + '{' + props + '}\n'; }; var css = []; var detectFonts = typeof fonts === 'undefined'; var fontList = fonts || []; styleSheetRules().forEach(function (rules) { if (!rules) return; Array.from(rules).forEach(function (rule) { if (typeof rule.style != 'undefined') { try { if (query(el, rule.selectorText)){ css.push(generateCss(rule.selectorText, rule.style.cssText)); } else if (detectFonts && rule.cssText.match(/^@font-face/)) { var font = detectCssFont(rule); if (font) fontList.push(font); } else { css.push(rule.cssText); } } catch (e){ } } }); }); return inlineFonts(fontList).then(function (fontCss) { return css.join('\n') + fontCss; }); }; out$.prepareSvg = function (el, options, done) { requireDomNode(el); var _ref2 = options || {}; var _ref2$left = _ref2.left; var left = _ref2$left === undefined ? 0 : _ref2$left; var _ref2$top = _ref2.top; var top = _ref2$top === undefined ? 0 : _ref2$top; var w = _ref2.width; var h = _ref2.height; var _ref2$scale = _ref2.scale; var scale = _ref2$scale === undefined ? 1 : _ref2$scale; var _ref2$responsive = _ref2.responsive; var responsive = _ref2$responsive === undefined ? false : _ref2$responsive; return inlineImages(el).then(function () { var clone = el.cloneNode(true); var _getDimensions = getDimensions(el, clone, w, h); var width = _getDimensions.width; var height = _getDimensions.height; if (el.tagName !== 'svg') { if (el.getBBox) { clone.setAttribute('transform', clone.getAttribute('transform').replace(/translate\(.*?\)/, '')); var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.appendChild(clone); clone = svg; } else { console.error('Attempted to render non-SVG element', el); return; } } clone.setAttribute('version', '1.1'); clone.setAttribute('viewBox', [left, top, width, height].join(' ')); if (!clone.getAttribute('xmlns')) clone.setAttributeNS(xmlns, 'xmlns', 'http://www.w3.org/2000/svg'); if (!clone.getAttribute('xmlns:xlink')) clone.setAttributeNS(xmlns, 'xmlns:xlink', 'http://www.w3.org/1999/xlink'); if (responsive) { clone.removeAttribute('width'); clone.removeAttribute('height'); clone.setAttribute('preserveAspectRatio', 'xMinYMin meet'); } else { clone.setAttribute('width', width * scale); clone.setAttribute('height', height * scale); } Array.from(clone.querySelectorAll('foreignObject > *')).forEach(function (foreignObject) { if (!foreignObject.getAttribute('xmlns')) foreignObject.setAttributeNS(xmlns, 'xmlns', 'http://www.w3.org/1999/xhtml'); }); return inlineCss(el, options).then(function (css) { var style = document.createElement('style'); style.setAttribute('type', 'text/css'); style.innerHTML = ''; var defs = document.createElement('defs'); defs.appendChild(style); clone.insertBefore(defs, clone.firstChild); var outer = document.createElement('div'); outer.appendChild(clone); var src = outer.innerHTML.replace(/NS\d+:href/gi, 'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href'); if (typeof done === 'function') done(src, width, height);else return { src: src, width: width, height: height }; }); }); }; out$.svgAsDataUri = function (el, options, done) { requireDomNode(el); var result = out$.prepareSvg(el, options).then(function (_ref3) { var src = _ref3.src; return 'data:image/svg+xml;base64,' + window.btoa(reEncode(doctype + src)); }); if (typeof done === 'function') return result.then(done); return result; }; out$.svgAsPngUri = function (el, options, done) { requireDomNode(el); var _ref4 = options || {}; var _ref4$encoderType = _ref4.encoderType; var encoderType = _ref4$encoderType === undefined ? 'image/png' : _ref4$encoderType; var _ref4$encoderOptions = _ref4.encoderOptions; var encoderOptions = _ref4$encoderOptions === undefined ? 0.8 : _ref4$encoderOptions; var backgroundColor = _ref4.backgroundColor; var canvg = _ref4.canvg; var convertToPng = function convertToPng(_ref5) { var src = _ref5.src; var width = _ref5.width; var height = _ref5.height; var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var pixelRatio = window.devicePixelRatio || 1; canvas.width = width * pixelRatio; canvas.height = height * pixelRatio; canvas.style.width = canvas.width + 'px'; canvas.style.height = canvas.height + 'px'; context.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0); /*if (canvg && (navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf('Trident') > 0)) { canvg(canvas, src); }*/ if (canvg) { canvg(canvas, src); } else { context.drawImage(src, 0, 0); } if (backgroundColor) { context.globalCompositeOperation = 'destination-over'; context.fillStyle = backgroundColor; context.fillRect(0, 0, canvas.width, canvas.height); } var png = void 0; try { png = canvas.toDataURL(encoderType, encoderOptions); } catch (e) { if (typeof SecurityError !== 'undefined' && e instanceof SecurityError || e.name === 'SecurityError') { console.error('Rendered SVG images cannot be downloaded in this browser.'); return; } else throw e; } if (typeof done === 'function') done(png); return Promise.resolve(png); }; /*if (canvg && (navigator.userAgent.indexOf('MSIE') > 0 || navigator.userAgent.indexOf('Trident') > 0)) {*/ if (canvg) { return out$.prepareSvg(el, options).then(convertToPng); } else { return out$.svgAsDataUri(el, options).then(function (uri) { return new Promise(function (resolve, reject) { var image = new Image(); image.onload = function () { return resolve(convertToPng({ src: image, width: image.width, height: image.height })); }; image.onerror = function () { reject('There was an error loading the data URI as an image on the following SVG\n' + window.atob(uri.slice(26)) + 'Open the following link to see browser\'s diagnosis\n' + uri); }; image.src = uri; }); }); } }; out$.download = function (name, uri) { if (navigator.msSaveOrOpenBlob) navigator.msSaveOrOpenBlob(uriToBlob(uri), name);else { var saveLink = document.createElement('a'); if ('download' in saveLink) { saveLink.download = name; saveLink.style.display = 'none'; document.body.appendChild(saveLink); try { (function () { var blob = uriToBlob(uri); var url = URL.createObjectURL(blob); saveLink.href = url; saveLink.onclick = function () { return requestAnimationFrame(function () { return URL.revokeObjectURL(url); }); }; })(); } catch (e) { console.warn('This browser does not support object URLs. Falling back to string URL.'); saveLink.href = uri; } saveLink.click(); document.body.removeChild(saveLink); } else { window.open(uri, '_temp', 'menubar=no,toolbar=no,status=no'); } } }; out$.saveSvg = function (el, name, options) { requireDomNode(el); out$.svgAsDataUri(el, options || {}, function (uri) { return out$.download(name, uri); }); }; out$.saveSvgAsPng = function (el, name, options) { requireDomNode(el); out$.svgAsPngUri(el, options || {}, function (uri) { return out$.download(name, uri); }); }; })();