@d3plus/export 3.0.16 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +23 -11
- package/es/src/saveElement.js +16 -15
- package/package.json +17 -9
- package/types/index.d.ts +1 -0
- package/types/src/saveElement.d.ts +25 -0
- package/umd/d3plus-export.full.js +16 -119
- package/umd/d3plus-export.full.js.map +1 -1
- package/umd/d3plus-export.full.min.js +48 -42
- package/umd/d3plus-export.js +16 -119
- package/umd/d3plus-export.js.map +1 -1
- package/umd/d3plus-export.min.js +10 -11
|
@@ -4,50 +4,54 @@
|
|
|
4
4
|
Copyright (c) 2026 D3plus - https://d3plus.org
|
|
5
5
|
@license MIT
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("@d3plus/export",["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).d3plus={})}(this,function(e){const t=(()=>{
|
|
8
8
|
// generate uuid for className of pseudo elements.
|
|
9
9
|
// We should not use GUIDs, otherwise pseudo elements sometimes cannot be captured.
|
|
10
10
|
let e=0;
|
|
11
11
|
// ref: http://stackoverflow.com/a/6248722/2519373
|
|
12
|
-
return()=>(e+=1
|
|
13
|
-
|
|
12
|
+
return()=>(e+=1,`u${// eslint-disable-next-line no-bitwise
|
|
13
|
+
`0000${(Math.random()*36**4|0).toString(36)}`.slice(-4)}${e}`)})();function n(e){const t=[];for(let n=0,r=e.length;n<r;n++)t.push(e[n]);return t}let r=null;function o(e={}){return r||(e.includeStyleProperties?(r=e.includeStyleProperties,r):(r=n(window.getComputedStyle(document.documentElement)),r))}function i(e,t){const n=(e.ownerDocument.defaultView||window).getComputedStyle(e).getPropertyValue(t);return n?parseFloat(n.replace("px","")):0}function a(e,t={}){return{width:t.width||function(e){const t=i(e,"border-left-width"),n=i(e,"border-right-width");return e.clientWidth+t+n}(e),height:t.height||function(e){const t=i(e,"border-top-width"),n=i(e,"border-bottom-width");return e.clientHeight+t+n}(e)}}
|
|
14
14
|
// @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size
|
|
15
|
-
|
|
15
|
+
const c=16384;function s(e){return new Promise((t,n)=>{const r=new Image;r.onload=()=>{r.decode().then(()=>{requestAnimationFrame(()=>t(r))})},r.onerror=n,r.crossOrigin="anonymous",r.decoding="async",r.src=e})}async function l(e,t,n){const r="http://www.w3.org/2000/svg",o=document.createElementNS(r,"svg"),i=document.createElementNS(r,"foreignObject");return o.setAttribute("width",`${t}`),o.setAttribute("height",`${n}`),o.setAttribute("viewBox",`0 0 ${t} ${n}`),i.setAttribute("width","100%"),i.setAttribute("height","100%"),i.setAttribute("x","0"),i.setAttribute("y","0"),i.setAttribute("externalResourcesRequired","true"),o.appendChild(i),i.appendChild(e),async function(e){return Promise.resolve().then(()=>(new XMLSerializer).serializeToString(e)).then(encodeURIComponent).then(e=>`data:image/svg+xml;charset=utf-8,${e}`)}(o)}const u=(e,t)=>{if(e instanceof t)return!0;const n=Object.getPrototypeOf(e);return null!==n&&(n.constructor.name===t.name||u(n,t))};function d(e,t,n,r){const i=`.${e}:${t}`,a=n.cssText?function(e){const t=e.getPropertyValue("content");return`${e.cssText} content: '${t.replace(/'|"/g,"")}';`}(n):function(e,t){return o(t).map(t=>`${t}: ${e.getPropertyValue(t)}${e.getPropertyPriority(t)?" !important":""};`).join(" ")}(n,r);return document.createTextNode(`${i}{${a}}`)}function f(e,n,r,o){const i=window.getComputedStyle(e,r),a=i.getPropertyValue("content");if(""===a||"none"===a)return;const c=t();try{n.className=`${n.className} ${c}`}catch(e){return}const s=document.createElement("style");s.appendChild(d(c,r,i,o)),n.appendChild(s)}const h="application/font-woff",p="image/jpeg",m={woff:h,woff2:h,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:p,jpeg:p,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml",webp:"image/webp"};function g(e){const t=function(e){const t=/\.([^./]*?)$/g.exec(e);return t?t[1]:""}(e).toLowerCase();return m[t]||""}function w(e){return-1!==e.search(/^(data:)/)}async function y(e,t,n){const r=await fetch(e,t);if(404===r.status)throw new Error(`Resource "${r.url}" not found`);const o=await r.blob();return new Promise((e,t)=>{const i=new FileReader;i.onerror=t,i.onloadend=()=>{try{e(n({res:r,result:i.result}))}catch(e){t(e)}},i.readAsDataURL(o)})}const b={};async function v(e,t,n){const r=function(e,t,n){let r=e.replace(/\?.*/,"");return n&&(r=e),
|
|
16
16
|
// font resource
|
|
17
|
-
/ttf|otf|eot|woff2?/i.test(
|
|
17
|
+
/ttf|otf|eot|woff2?/i.test(r)&&(r=r.replace(/.*\//,"")),t?`[${t}]${r}`:r}(e,t,n.includeQueryParams);if(null!=b[r])return b[r];
|
|
18
18
|
// ref: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache
|
|
19
|
-
|
|
19
|
+
let o;n.cacheBust&&(
|
|
20
20
|
// eslint-disable-next-line no-param-reassign
|
|
21
|
-
|
|
21
|
+
e+=(/\?/.test(e)?"&":"?")+(new Date).getTime());try{const r=await y(e,n.fetchRequestInit,({res:e,result:n})=>(t||(
|
|
22
|
+
// eslint-disable-next-line no-param-reassign
|
|
23
|
+
t=e.headers.get("Content-Type")||""),function(e){return e.split(/,/)[1]}(n)));o=function(e,t){return`data:${t};base64,${e}`}(r,t)}catch(t){o=n.imagePlaceholder||"";let r=`Failed to fetch resource: ${e}`;t&&(r="string"==typeof t?t:t.message),r&&console.warn(r)}return b[r]=o,o}async function S(e,t){return u(e,HTMLCanvasElement)?async function(e){const t=e.toDataURL();return"data:,"===t?e.cloneNode(!1):s(t)}(e):u(e,HTMLVideoElement)?async function(e,t){if(e.currentSrc){const t=document.createElement("canvas"),n=t.getContext("2d");return t.width=e.clientWidth,t.height=e.clientHeight,null==n||n.drawImage(e,0,0,t.width,t.height),s(t.toDataURL())}const n=e.poster,r=g(n);return s(await v(n,r,t))}(e,t):u(e,HTMLIFrameElement)?async function(e,t){var n;try{if(null===(n=null==e?void 0:e.contentDocument)||void 0===n?void 0:n.body)return await C(e.contentDocument.body,t,!0)}catch(e){
|
|
22
24
|
// Failed to clone iframe
|
|
23
|
-
}return e.cloneNode(!1)}
|
|
25
|
+
}return e.cloneNode(!1)}(e,t):e.cloneNode(x(e))}const E=e=>null!=e.tagName&&"SLOT"===e.tagName.toUpperCase(),x=e=>null!=e.tagName&&"SVG"===e.tagName.toUpperCase();function $(e,t,n){return u(t,Element)&&(function(e,t,n){const r=t.style;if(!r)return;const i=window.getComputedStyle(e);i.cssText?(r.cssText=i.cssText,r.transformOrigin=i.transformOrigin):o(n).forEach(n=>{let o=i.getPropertyValue(n);if("font-size"===n&&o.endsWith("px")){const e=Math.floor(parseFloat(o.substring(0,o.length-2)))-.1;o=`${e}px`}u(e,HTMLIFrameElement)&&"display"===n&&"inline"===o&&(o="block"),"d"===n&&t.getAttribute("d")&&(o=`path(${t.getAttribute("d")})`),r.setProperty(n,o,i.getPropertyPriority(n))})}(e,t,n),function(e,t,n){f(e,t,":before",n),f(e,t,":after",n)}(e,t,n),function(e,t){u(e,HTMLTextAreaElement)&&(t.innerHTML=e.value),u(e,HTMLInputElement)&&t.setAttribute("value",e.value)}(e,t),function(e,t){if(u(e,HTMLSelectElement)){const n=t,r=Array.from(n.children).find(t=>e.value===t.getAttribute("value"));r&&r.setAttribute("selected","")}}(e,t)),t}async function C(e,t,r){return r||!t.filter||t.filter(e)?Promise.resolve(e).then(e=>S(e,t)).then(r=>async function(e,t,r){var o,i;if(x(t))return t;let a=[];return a=E(e)&&e.assignedNodes?n(e.assignedNodes()):u(e,HTMLIFrameElement)&&(null===(o=e.contentDocument)||void 0===o?void 0:o.body)?n(e.contentDocument.body.childNodes):n((null!==(i=e.shadowRoot)&&void 0!==i?i:e).childNodes),0===a.length||u(e,HTMLVideoElement)||await a.reduce((e,n)=>e.then(()=>C(n,r)).then(e=>{e&&t.appendChild(e)}),Promise.resolve()),t}(e,r,t)).then(n=>$(e,n,t)).then(e=>async function(e,t){const n=e.querySelectorAll?e.querySelectorAll("use"):[];if(0===n.length)return e;const r={};for(let o=0;o<n.length;o++){const i=n[o].getAttribute("xlink:href");if(i){const n=e.querySelector(i),o=document.querySelector(i);n||!o||r[i]||(
|
|
24
26
|
// eslint-disable-next-line no-await-in-loop
|
|
25
|
-
|
|
27
|
+
r[i]=await C(o,t,!0))}}const o=Object.values(r);if(o.length){const t="http://www.w3.org/1999/xhtml",n=document.createElementNS(t,"svg");n.setAttribute("xmlns",t),n.style.position="absolute",n.style.width="0",n.style.height="0",n.style.overflow="hidden",n.style.display="none";const r=document.createElementNS(t,"defs");n.appendChild(r);for(let e=0;e<o.length;e++)r.appendChild(o[e]);e.appendChild(n)}return e}(e,t)):null}const R=/url\((['"]?)([^'"]+?)\1\)/g,T=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,P=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;async function N(e,t,n,r,o){try{const i=n?function(e,t){
|
|
26
28
|
// url is absolute already
|
|
27
|
-
(
|
|
29
|
+
if(e.match(/^[a-z]+:\/\//i))return e;
|
|
28
30
|
// url is absolute already, without protocol
|
|
29
|
-
|
|
31
|
+
if(e.match(/^\/\//))return window.location.protocol+e;
|
|
30
32
|
// dataURI, mailto:, tel:, etc.
|
|
31
|
-
|
|
33
|
+
if(e.match(/^[a-z]+:/i))return e;const n=document.implementation.createHTMLDocument(),r=n.createElement("base"),o=n.createElement("a");return n.head.appendChild(r),n.body.appendChild(o),t&&(r.href=t),o.href=e,o.href}(t,n):t,a=g(t);let c;return o||(c=await v(i,a,r)),e.replace(function(e){
|
|
34
|
+
// eslint-disable-next-line no-useless-escape
|
|
35
|
+
const t=e.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1");return new RegExp(`(url\\(['"]?)(${t})(['"]?\\))`,"g")}(t),`$1${c}$3`)}catch(e){
|
|
32
36
|
// pass
|
|
33
|
-
}
|
|
37
|
+
}return e}function A(e){return-1!==e.search(R)}async function L(e,t,n){if(!A(e))return e;const r=function(e,{preferredFontFormat:t}){return t?e.replace(P,e=>{
|
|
34
38
|
// eslint-disable-next-line no-constant-condition
|
|
35
|
-
for(;;){
|
|
39
|
+
for(;;){const[n,,r]=T.exec(e)||[];if(!r)return"";if(r===t)return`src: ${n};`}}):e}(e,n),o=function(e){const t=[];return e.replace(R,(e,n,r)=>(t.push(r),e)),t.filter(e=>!w(e))}(r);return o.reduce((e,r)=>e.then(e=>N(e,r,t,n)),Promise.resolve(r))}async function k(e,t,n){var r;const o=null===(r=t.style)||void 0===r?void 0:r.getPropertyValue(e);if(o){const r=await L(o,null,n);return t.style.setProperty(e,r,t.style.getPropertyPriority(e)),!0}return!1}async function I(e,t){u(e,Element)&&(await async function(e,t){await k("background",e,t)||await k("background-image",e,t),await k("mask",e,t)||await k("-webkit-mask",e,t)||await k("mask-image",e,t)||await k("-webkit-mask-image",e,t)}(e,t),await async function(e,t){const n=u(e,HTMLImageElement);if((!n||w(e.src))&&(!u(e,SVGImageElement)||w(e.href.baseVal)))return;const r=n?e.src:e.href.baseVal,o=await v(r,g(r),t);await new Promise((r,i)=>{e.onload=r,e.onerror=t.onImageErrorHandler?(...e)=>{try{r(t.onImageErrorHandler(...e))}catch(e){i(e)}}:i;const a=e;a.decode&&(a.decode=r),"lazy"===a.loading&&(a.loading="eager"),n?(e.srcset="",e.src=o):e.href.baseVal=o})}(e,t),await async function(e,t){const r=n(e.childNodes).map(e=>I(e,t));await Promise.all(r).then(()=>e)}(e,t))}const O={};async function M(e){let t=O[e];if(null!=t)return t;const n=await fetch(e);return t={url:e,cssText:await n.text()},O[e]=t,t}async function H(e,t){let n=e.cssText;const r=/url\(["']?([^"')]+)["']?\)/g,o=(n.match(/url\([^)]+\)/g)||[]).map(async o=>{let i=o.replace(r,"$1");return i.startsWith("https://")||(i=new URL(i,e.url).href),y(i,t.fetchRequestInit,({result:e})=>(n=n.replace(o,`url(${e})`),[o,e]))});return Promise.all(o).then(()=>n)}function D(e){if(null==e)return[];const t=[];
|
|
36
40
|
// strip out comments
|
|
37
|
-
let
|
|
41
|
+
let n=e.replace(/(\/\*[\s\S]*?\*\/)/gi,"");
|
|
38
42
|
// eslint-disable-next-line prefer-regex-literals
|
|
43
|
+
const r=new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})","gi");
|
|
39
44
|
// eslint-disable-next-line no-constant-condition
|
|
40
|
-
for(
|
|
41
|
-
// eslint-disable-next-line no-constant-condition
|
|
42
|
-
for(var o=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i=new RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi")
|
|
45
|
+
for(;;){const e=r.exec(n);if(null===e)break;t.push(e[0])}n=n.replace(r,"");const o=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i=new RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})","gi");
|
|
43
46
|
// to match css & media queries together
|
|
44
|
-
|
|
47
|
+
// eslint-disable-next-line no-constant-condition
|
|
48
|
+
for(;;){let e=o.exec(n);if(null===e){if(e=i.exec(n),null===e)break;o.lastIndex=i.lastIndex}else i.lastIndex=o.lastIndex;t.push(e[0])}return t}async function F(e,t){if(null==e.ownerDocument)throw new Error("Provided element is not within a Document");const r=n(e.ownerDocument.styleSheets),o=await async function(e,t){const r=[],o=[];
|
|
45
49
|
// First loop inlines imports
|
|
46
|
-
return
|
|
50
|
+
return e.forEach(r=>{if("cssRules"in r)try{n(r.cssRules||[]).forEach((e,n)=>{if(e.type===CSSRule.IMPORT_RULE){let i=n+1;const a=M(e.href).then(e=>H(e,t)).then(e=>D(e).forEach(e=>{try{r.insertRule(e,e.startsWith("@import")?i+=1:r.cssRules.length)}catch(t){console.error("Error inserting rule from remote css",{rule:e,error:t})}})).catch(e=>{console.error("Error loading remote css",e.toString())});o.push(a)}})}catch(n){const i=e.find(e=>null==e.href)||document.styleSheets[0];null!=r.href&&o.push(M(r.href).then(e=>H(e,t)).then(e=>D(e).forEach(e=>{i.insertRule(e,i.cssRules.length)})).catch(e=>{console.error("Error loading remote stylesheet",e)})),console.error("Error inlining remote css file",n)}}),Promise.all(o).then(()=>(
|
|
47
51
|
// Second loop parses rules
|
|
48
|
-
|
|
52
|
+
e.forEach(e=>{if("cssRules"in e)try{n(e.cssRules||[]).forEach(e=>{r.push(e)})}catch(t){console.error(`Error while reading CSS rules from ${e.href}`,t)}}),r))}(r,t);return function(e){return e.filter(e=>e.type===CSSRule.FONT_FACE_RULE).filter(e=>A(e.style.getPropertyValue("src")))}(o)}function U(e){return e.trim().replace(/["']/g,"")}async function j(e,t){const n=await F(e,t),r=function(e){const t=new Set;return function e(n){(n.style.fontFamily||getComputedStyle(n).fontFamily).split(",").forEach(e=>{t.add(U(e))}),Array.from(n.children).forEach(t=>{t instanceof HTMLElement&&e(t)})}(e),t}(e);return(await Promise.all(n.filter(e=>r.has(U(e.style.fontFamily))).map(e=>{const n=e.parentStyleSheet?e.parentStyleSheet.href:null;return L(e.cssText,n,t)}))).join("\n")}async function V(e,t={}){const{width:n,height:r}=a(e,t),o=await C(e,t,!0);await async function(e,t){const n=null!=t.fontEmbedCSS?t.fontEmbedCSS:t.skipFonts?null:await j(e,t);if(n){const t=document.createElement("style"),r=document.createTextNode(n);t.appendChild(r),e.firstChild?e.insertBefore(t,e.firstChild):e.appendChild(t)}}(o,t),await I(o,t),function(e,t){const{style:n}=e;t.backgroundColor&&(n.backgroundColor=t.backgroundColor),t.width&&(n.width=`${t.width}px`),t.height&&(n.height=`${t.height}px`);const r=t.style;null!=r&&Object.keys(r).forEach(e=>{n[e]=r[e]})}(o,t);return await l(o,n,r)}async function q(e,t={}){const{width:n,height:r}=a(e,t),o=await V(e,t),i=await s(o),l=document.createElement("canvas"),u=l.getContext("2d"),d=t.pixelRatio||function(){let e,t;try{t=process}catch(e){
|
|
49
53
|
// pass
|
|
50
|
-
}
|
|
54
|
+
}const n=t&&t.env?t.env.devicePixelRatio:null;return n&&(e=parseInt(n,10),Number.isNaN(e)&&(e=1)),e||window.devicePixelRatio||1}(),f=t.canvasWidth||n,h=t.canvasHeight||r;return l.width=f*d,l.height=h*d,t.skipAutoScale||function(e){(e.width>c||e.height>c)&&(e.width>c&&e.height>c?e.width>e.height?(e.height*=c/e.width,e.width=c):(e.width*=c/e.height,e.height=c):e.width>c?(e.height*=c/e.width,e.width=c):(e.width*=c/e.height,e.height=c))}(l),l.style.width=`${f}`,l.style.height=`${h}`,t.backgroundColor&&(u.fillStyle=t.backgroundColor,u.fillRect(0,0,l.width,l.height)),u.drawImage(i,0,0,l.width,l.height),l}async function B(e,t={}){const n=await q(e,t),r=await function(e,t={}){return e.toBlob?new Promise(n=>{e.toBlob(n,t.type?t.type:"image/png",t.quality?t.quality:1)}):new Promise(n=>{const r=window.atob(e.toDataURL(t.type?t.type:void 0,t.quality?t.quality:void 0).split(",")[1]),o=r.length,i=new Uint8Array(o);for(let e=0;e<o;e+=1)i[e]=r.charCodeAt(e);n(new Blob([i],{type:t.type?t.type:"image/png"}))})}(n);return r}var W,z={exports:{}},_=z.exports;
|
|
51
55
|
/* FileSaver.js
|
|
52
56
|
* A saveAs() FileSaver implementation.
|
|
53
57
|
* 1.3.2
|
|
@@ -56,35 +60,37 @@ r.forEach(t=>{if("cssRules"in t)try{s(t.cssRules||[]).forEach(e=>{n.push(e)})}ca
|
|
|
56
60
|
* By Eli Grey, http://eligrey.com
|
|
57
61
|
* License: MIT
|
|
58
62
|
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
|
|
59
|
-
*/
|
|
63
|
+
*/var G=(W||(W=1,function(e){
|
|
64
|
+
/*global self */ /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */var t=t||function(e){
|
|
60
65
|
// IE <10 is explicitly unsupported
|
|
61
|
-
|
|
62
|
-
// IE 10+ (native saveAs)
|
|
63
|
-
return e=l.document,s=function(){return l.URL||l.webkitURL||l},c=e.createElementNS("http://www.w3.org/1999/xhtml","a"),u="download"in c,d=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},h=/constructor/i.test(l.HTMLElement)||l.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),o=function(e){(l.setImmediate||l.setTimeout)(function(){throw e},0)},p="application/octet-stream",t=4e4,m=function(e){setTimeout(function(){"string"==typeof e?s().revokeObjectURL(e):e.remove()},t)},g=function(e,t,r){for(var n=(t=[].concat(t)).length;n--;){var a=e["on"+t[n]];if("function"==typeof a)try{a.call(e,r||e)}catch(e){o(e)}}},w=function(e){
|
|
66
|
+
if(!(void 0===e||"undefined"!=typeof navigator&&/MSIE [1-9]\./.test(navigator.userAgent))){var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,i=/constructor/i.test(e.HTMLElement)||e.safari,a=/CriOS\/[\d]+/.test(navigator.userAgent),c=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s=function(e){setTimeout(function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()},4e4)},l=function(e){
|
|
64
67
|
// prepend BOM for UTF-8 XML and text/* types (including HTML)
|
|
65
68
|
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
|
|
66
|
-
return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob([String.fromCharCode(65279),e],{type:e.type}):e},
|
|
69
|
+
return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob([String.fromCharCode(65279),e],{type:e.type}):e},u=function(t,u,d){d||(t=l(t));
|
|
67
70
|
// First try a.download, then web filesystem, then object URLs
|
|
68
|
-
var
|
|
69
|
-
|
|
71
|
+
var f,h=this,p="application/octet-stream"===t.type,m=function(){!function(e,t,n){for(var r=(t=[].concat(t)).length;r--;){var o=e["on"+t[r]];if("function"==typeof o)try{o.call(e,n||e)}catch(e){c(e)}}}(h,"writestart progress write writeend".split(" "))};if(h.readyState=h.INIT,o)return f=n().createObjectURL(t),void setTimeout(function(){var e,t;r.href=f,r.download=u,e=r,t=new MouseEvent("click"),e.dispatchEvent(t),m(),s(f),h.readyState=h.DONE});!function(){if((a||p&&i)&&e.FileReader){
|
|
72
|
+
// Safari doesn't allow downloading of blob urls
|
|
73
|
+
var r=new FileReader;return r.onloadend=function(){var t=a?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");e.open(t,"_blank")||(e.location.href=t),t=void 0,// release reference before dispatching
|
|
74
|
+
h.readyState=h.DONE,m()},r.readAsDataURL(t),void(h.readyState=h.INIT)}
|
|
70
75
|
// don't create more object URLs than needed
|
|
71
|
-
|
|
76
|
+
f||(f=n().createObjectURL(t)),p?e.location.href=f:e.open(f,"_blank")||(
|
|
72
77
|
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
|
|
73
|
-
|
|
78
|
+
e.location.href=f),h.readyState=h.DONE,m(),s(f)}()},d=u.prototype;
|
|
79
|
+
// IE 10+ (native saveAs)
|
|
80
|
+
return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t,n){return t=t||e.name||"download",n||(e=l(e)),navigator.msSaveOrOpenBlob(e,t)}:(d.abort=function(){},d.readyState=d.INIT=0,d.WRITING=1,d.DONE=2,d.error=d.onwritestart=d.onprogress=d.onwrite=d.onabort=d.onerror=d.onwriteend=null,function(e,t,n){return new u(e,t||e.name||"download",n)})}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||_.content);
|
|
74
81
|
// `self` is undefined in Firefox for Android content script context
|
|
75
82
|
// while `this` is nsIContentFrameMessageManager
|
|
76
83
|
// with an attribute `content` that corresponds to the window
|
|
77
|
-
|
|
84
|
+
e.exports&&(e.exports.saveAs=t)}(z)),z.exports);const X={filename:"download",type:"png"};
|
|
78
85
|
/**
|
|
79
|
-
|
|
80
|
-
@
|
|
81
|
-
@param
|
|
82
|
-
@param
|
|
83
|
-
@param
|
|
84
|
-
@param
|
|
85
|
-
@param
|
|
86
|
-
|
|
87
|
-
*/e.saveElement=function(e,t={},r={}){function n(e){z.saveAs(e,t.filename+"."+t.type),t.callback&&t.callback()}e&&(t=Object.assign({},_,t),
|
|
86
|
+
Downloads an HTML Element as a bitmap PNG image.
|
|
87
|
+
@param elem The DOM element or d3 selection to export.
|
|
88
|
+
@param options Additional options to specify.
|
|
89
|
+
@param options .filename = "download"] Filename for the downloaded file, without the extension.
|
|
90
|
+
@param options .type = "png"] File type of the saved document. Accepted values are `"png"` and `"jpg"`.
|
|
91
|
+
@param options .callback] Function to be invoked after saving is complete.
|
|
92
|
+
@param renderOptions Custom options to be passed to the html-to-image function.
|
|
93
|
+
*/e.saveElement=function(e,t={},n={}){if(!e)return;const r=Object.assign({},X,t),o=Object.assign({backgroundColor:n.background},n);
|
|
88
94
|
// rename renderOptions.background to backgroundColor for backwards compatibility
|
|
89
|
-
|
|
95
|
+
function i(e){G.saveAs(e,`${r.filename}.${r.type}`),r.callback&&r.callback()}"svg"===r.type?V(e,o).then(e=>{const t=new XMLHttpRequest;t.open("GET",e),t.responseType="blob",t.onload=()=>i(t.response),t.send()}):B(e,o).then(e=>{e&&i(e)})}});
|
|
90
96
|
//# sourceMappingURL=d3plus-export.full.js.map
|
package/umd/d3plus-export.js
CHANGED
|
@@ -4,110 +4,6 @@
|
|
|
4
4
|
Copyright (c) 2026 D3plus - https://d3plus.org
|
|
5
5
|
@license MIT
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
(function (factory) {
|
|
9
|
-
typeof define === 'function' && define.amd ? define(factory) :
|
|
10
|
-
factory();
|
|
11
|
-
})((function () { 'use strict';
|
|
12
|
-
|
|
13
|
-
if (typeof window !== "undefined") {
|
|
14
|
-
(function () {
|
|
15
|
-
try {
|
|
16
|
-
if (typeof SVGElement === 'undefined' || Boolean(SVGElement.prototype.innerHTML)) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
} catch (e) {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function serializeNode (node) {
|
|
24
|
-
switch (node.nodeType) {
|
|
25
|
-
case 1:
|
|
26
|
-
return serializeElementNode(node);
|
|
27
|
-
case 3:
|
|
28
|
-
return serializeTextNode(node);
|
|
29
|
-
case 8:
|
|
30
|
-
return serializeCommentNode(node);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function serializeTextNode (node) {
|
|
35
|
-
return node.textContent.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function serializeCommentNode (node) {
|
|
39
|
-
return '<!--' + node.nodeValue + '-->'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function serializeElementNode (node) {
|
|
43
|
-
var output = '';
|
|
44
|
-
|
|
45
|
-
output += '<' + node.tagName;
|
|
46
|
-
|
|
47
|
-
if (node.hasAttributes()) {
|
|
48
|
-
[].forEach.call(node.attributes, function(attrNode) {
|
|
49
|
-
output += ' ' + attrNode.name + '="' + attrNode.value + '"';
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
output += '>';
|
|
54
|
-
|
|
55
|
-
if (node.hasChildNodes()) {
|
|
56
|
-
[].forEach.call(node.childNodes, function(childNode) {
|
|
57
|
-
output += serializeNode(childNode);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
output += '</' + node.tagName + '>';
|
|
62
|
-
|
|
63
|
-
return output;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
Object.defineProperty(SVGElement.prototype, 'innerHTML', {
|
|
67
|
-
get: function () {
|
|
68
|
-
var output = '';
|
|
69
|
-
|
|
70
|
-
[].forEach.call(this.childNodes, function(childNode) {
|
|
71
|
-
output += serializeNode(childNode);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return output;
|
|
75
|
-
},
|
|
76
|
-
set: function (markup) {
|
|
77
|
-
while (this.firstChild) {
|
|
78
|
-
this.removeChild(this.firstChild);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
var dXML = new DOMParser();
|
|
83
|
-
dXML.async = false;
|
|
84
|
-
|
|
85
|
-
var sXML = '<svg xmlns=\'http://www.w3.org/2000/svg\' xmlns:xlink=\'http://www.w3.org/1999/xlink\'>' + markup + '</svg>';
|
|
86
|
-
var svgDocElement = dXML.parseFromString(sXML, 'text/xml').documentElement;
|
|
87
|
-
|
|
88
|
-
[].forEach.call(svgDocElement.childNodes, function(childNode) {
|
|
89
|
-
this.appendChild(this.ownerDocument.importNode(childNode, true));
|
|
90
|
-
}.bind(this));
|
|
91
|
-
} catch (e) {
|
|
92
|
-
throw new Error('Error parsing markup string');
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
Object.defineProperty(SVGElement.prototype, 'innerSVG', {
|
|
98
|
-
get: function () {
|
|
99
|
-
return this.innerHTML;
|
|
100
|
-
},
|
|
101
|
-
set: function (markup) {
|
|
102
|
-
this.innerHTML = markup;
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
})();
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
7
|
(function (global, factory) {
|
|
112
8
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('html-to-image'), require('file-saver')) :
|
|
113
9
|
typeof define === 'function' && define.amd ? define('@d3plus/export', ['exports', 'html-to-image', 'file-saver'], factory) :
|
|
@@ -119,27 +15,26 @@
|
|
|
119
15
|
type: "png"
|
|
120
16
|
};
|
|
121
17
|
/**
|
|
122
|
-
|
|
123
|
-
@
|
|
124
|
-
@param
|
|
125
|
-
@param
|
|
126
|
-
@param
|
|
127
|
-
@param
|
|
128
|
-
@param
|
|
129
|
-
@param {Object} [renderOptions] Custom options to be passed to the html-to-image function.
|
|
18
|
+
Downloads an HTML Element as a bitmap PNG image.
|
|
19
|
+
@param elem The DOM element or d3 selection to export.
|
|
20
|
+
@param options Additional options to specify.
|
|
21
|
+
@param options .filename = "download"] Filename for the downloaded file, without the extension.
|
|
22
|
+
@param options .type = "png"] File type of the saved document. Accepted values are `"png"` and `"jpg"`.
|
|
23
|
+
@param options .callback] Function to be invoked after saving is complete.
|
|
24
|
+
@param renderOptions Custom options to be passed to the html-to-image function.
|
|
130
25
|
*/ function saveElement(elem, options = {}, renderOptions = {}) {
|
|
131
26
|
if (!elem) return;
|
|
132
|
-
|
|
27
|
+
const opts = Object.assign({}, defaultOptions, options);
|
|
133
28
|
// rename renderOptions.background to backgroundColor for backwards compatibility
|
|
134
|
-
|
|
29
|
+
const renderOpts = Object.assign({
|
|
135
30
|
backgroundColor: renderOptions.background
|
|
136
31
|
}, renderOptions);
|
|
137
32
|
function finish(blob) {
|
|
138
|
-
fileSaver.saveAs(blob, `${
|
|
139
|
-
if (
|
|
33
|
+
fileSaver.saveAs(blob, `${opts.filename}.${opts.type}`);
|
|
34
|
+
if (opts.callback) opts.callback();
|
|
140
35
|
}
|
|
141
|
-
if (
|
|
142
|
-
htmlToImage.toSvg(elem,
|
|
36
|
+
if (opts.type === "svg") {
|
|
37
|
+
htmlToImage.toSvg(elem, renderOpts).then((dataUrl)=>{
|
|
143
38
|
const xhr = new XMLHttpRequest();
|
|
144
39
|
xhr.open("GET", dataUrl);
|
|
145
40
|
xhr.responseType = "blob";
|
|
@@ -147,7 +42,9 @@
|
|
|
147
42
|
xhr.send();
|
|
148
43
|
});
|
|
149
44
|
} else {
|
|
150
|
-
htmlToImage.toBlob(elem,
|
|
45
|
+
htmlToImage.toBlob(elem, renderOpts).then((blob)=>{
|
|
46
|
+
if (blob) finish(blob);
|
|
47
|
+
});
|
|
151
48
|
}
|
|
152
49
|
}
|
|
153
50
|
|
package/umd/d3plus-export.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"d3plus-export.js","sources":["../src/saveElement.
|
|
1
|
+
{"version":3,"file":"d3plus-export.js","sources":["../src/saveElement.ts"],"sourcesContent":["import {toBlob, toSvg} from \"html-to-image\";\nimport {saveAs} from \"file-saver\";\n\nexport interface SaveElementOptions {\n /** Filename for the downloaded file, without the extension. */\n filename?: string;\n /** File type of the saved document. Accepted values are \"png\", \"jpg\", and \"svg\". */\n type?: \"png\" | \"jpg\" | \"svg\";\n /** Function to be invoked after saving is complete. */\n callback?: () => void;\n}\n\nexport interface SaveElementRenderOptions {\n /** Background color for the rendered image. */\n background?: string;\n /** Background color for the rendered image (alias). */\n backgroundColor?: string;\n [key: string]: unknown;\n}\n\nconst defaultOptions: Required<Pick<SaveElementOptions, \"filename\" | \"type\">> =\n {\n filename: \"download\",\n type: \"png\",\n };\n\n/**\n Downloads an HTML Element as a bitmap PNG image.\n @param elem The DOM element or d3 selection to export.\n @param options Additional options to specify.\n @param options .filename = \"download\"] Filename for the downloaded file, without the extension.\n @param options .type = \"png\"] File type of the saved document. Accepted values are `\"png\"` and `\"jpg\"`.\n @param options .callback] Function to be invoked after saving is complete.\n @param renderOptions Custom options to be passed to the html-to-image function.\n*/\nexport default function (\n elem: HTMLElement,\n options: SaveElementOptions = {},\n renderOptions: SaveElementRenderOptions = {},\n): void {\n if (!elem) return;\n const opts = Object.assign({}, defaultOptions, options);\n\n // rename renderOptions.background to backgroundColor for backwards compatibility\n const renderOpts = Object.assign(\n {backgroundColor: renderOptions.background},\n renderOptions,\n );\n\n function finish(blob: Blob): void {\n saveAs(blob, `${opts.filename}.${opts.type}`);\n if (opts.callback) opts.callback();\n }\n\n if (opts.type === \"svg\") {\n toSvg(elem, renderOpts).then((dataUrl: string) => {\n const xhr = new XMLHttpRequest();\n xhr.open(\"GET\", dataUrl);\n xhr.responseType = \"blob\";\n xhr.onload = () => finish(xhr.response as Blob);\n xhr.send();\n });\n } else {\n toBlob(elem, renderOpts).then((blob: Blob | null) => {\n if (blob) finish(blob);\n });\n }\n}\n"],"names":["defaultOptions","filename","type","elem","options","renderOptions","opts","Object","assign","renderOpts","backgroundColor","background","finish","blob","saveAs","callback","toSvg","then","dataUrl","xhr","XMLHttpRequest","open","responseType","onload","response","send","toBlob"],"mappings":";;;;;;;;;;;;EAoBA,MAAMA,cAAAA,GACJ;MACEC,QAAAA,EAAU,UAAA;MACVC,IAAAA,EAAM;EACR,CAAA;EAEF;;;;;;;;EAQA,GACe,oBAAA,CACbC,IAAiB,EACjBC,OAAAA,GAA8B,EAAE,EAChCC,aAAAA,GAA0C,EAAE,EAAA;EAE5C,IAAA,IAAI,CAACF,IAAAA,EAAM;EACX,IAAA,MAAMG,OAAOC,MAAAA,CAAOC,MAAM,CAAC,IAAIR,cAAAA,EAAgBI,OAAAA,CAAAA;;MAG/C,MAAMK,UAAAA,GAAaF,MAAAA,CAAOC,MAAM,CAC9B;EAACE,QAAAA,eAAAA,EAAiBL,cAAcM;OAAU,EAC1CN,aAAAA,CAAAA;EAGF,IAAA,SAASO,OAAOC,IAAU,EAAA;UACxBC,gBAAAA,CAAOD,IAAAA,EAAM,GAAGP,IAAAA,CAAKL,QAAQ,CAAC,CAAC,EAAEK,IAAAA,CAAKJ,IAAI,CAAA,CAAE,CAAA;EAC5C,QAAA,IAAII,IAAAA,CAAKS,QAAQ,EAAET,IAAAA,CAAKS,QAAQ,EAAA;EAClC,IAAA;MAEA,IAAIT,IAAAA,CAAKJ,IAAI,KAAK,KAAA,EAAO;EACvBc,QAAAA,iBAAAA,CAAMb,IAAAA,EAAMM,UAAAA,CAAAA,CAAYQ,IAAI,CAAC,CAACC,OAAAA,GAAAA;EAC5B,YAAA,MAAMC,MAAM,IAAIC,cAAAA,EAAAA;cAChBD,GAAAA,CAAIE,IAAI,CAAC,KAAA,EAAOH,OAAAA,CAAAA;EAChBC,YAAAA,GAAAA,CAAIG,YAAY,GAAG,MAAA;EACnBH,YAAAA,GAAAA,CAAII,MAAM,GAAG,IAAMX,MAAAA,CAAOO,IAAIK,QAAQ,CAAA;EACtCL,YAAAA,GAAAA,CAAIM,IAAI,EAAA;EACV,QAAA,CAAA,CAAA;MACF,CAAA,MAAO;EACLC,QAAAA,kBAAAA,CAAOvB,IAAAA,EAAMM,UAAAA,CAAAA,CAAYQ,IAAI,CAAC,CAACJ,IAAAA,GAAAA;EAC7B,YAAA,IAAIA,MAAMD,MAAAA,CAAOC,IAAAA,CAAAA;EACnB,QAAA,CAAA,CAAA;EACF,IAAA;EACF;;;;;;;;"}
|
package/umd/d3plus-export.min.js
CHANGED
|
@@ -4,17 +4,16 @@
|
|
|
4
4
|
Copyright (c) 2026 D3plus - https://d3plus.org
|
|
5
5
|
@license MIT
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("html-to-image"),require("file-saver")):"function"==typeof define&&define.amd?define("@d3plus/export",["exports","html-to-image","file-saver"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).d3plus={},e.htmlToImage,e.fileSaver)}(this,function(e,t,n){"use strict";const o={filename:"download",type:"png"};
|
|
8
8
|
/**
|
|
9
|
-
|
|
10
|
-
@
|
|
11
|
-
@param
|
|
12
|
-
@param
|
|
13
|
-
@param
|
|
14
|
-
@param
|
|
15
|
-
@param
|
|
16
|
-
|
|
17
|
-
*/e.saveElement=function(e,t={},n={}){function o(e){i.saveAs(e,t.filename+"."+t.type),t.callback&&t.callback()}e&&(t=Object.assign({},a,t),
|
|
9
|
+
Downloads an HTML Element as a bitmap PNG image.
|
|
10
|
+
@param elem The DOM element or d3 selection to export.
|
|
11
|
+
@param options Additional options to specify.
|
|
12
|
+
@param options .filename = "download"] Filename for the downloaded file, without the extension.
|
|
13
|
+
@param options .type = "png"] File type of the saved document. Accepted values are `"png"` and `"jpg"`.
|
|
14
|
+
@param options .callback] Function to be invoked after saving is complete.
|
|
15
|
+
@param renderOptions Custom options to be passed to the html-to-image function.
|
|
16
|
+
*/e.saveElement=function(e,s={},i={}){if(!e)return;const l=Object.assign({},o,s),a=Object.assign({backgroundColor:i.background},i);
|
|
18
17
|
// rename renderOptions.background to backgroundColor for backwards compatibility
|
|
19
|
-
n
|
|
18
|
+
function f(e){n.saveAs(e,`${l.filename}.${l.type}`),l.callback&&l.callback()}"svg"===l.type?t.toSvg(e,a).then(e=>{const t=new XMLHttpRequest;t.open("GET",e),t.responseType="blob",t.onload=()=>f(t.response),t.send()}):t.toBlob(e,a).then(e=>{e&&f(e)})}});
|
|
20
19
|
//# sourceMappingURL=d3plus-export.js.map
|