diff --git a/dist/dom-to-image-more.min.js b/dist/dom-to-image-more.min.js index 90384d15..2544ce5c 100644 --- a/dist/dom-to-image-more.min.js +++ b/dist/dom-to-image-more.min.js @@ -1,3 +1,3 @@ -/*! dom-to-image-more 15-01-2023 */ -!function(n){"use strict";const a=function(){let e=0;return{escape:function(e){return e.replace(/([.*+?^${}()|[]\/\\])/g,"\\$1")},isDataUrl:function(e){return-1!==e.search(/^(data:)/)},canvasToBlob:function(t){if(t.toBlob)return new Promise(function(e){t.toBlob(e)});return function(o){return new Promise(function(e){var t=c(o.toDataURL().split(",")[1]),n=t.length,r=new Uint8Array(n);for(let e=0;et.style.removeProperty(e)),["left","right","top","bottom"].forEach(e=>{t.style.getPropertyValue(e)&&t.style.setProperty(e,"0px")})))}e(c,s)}function t(){const l=a.uid();function t(o){const i=f(c,o),u=i.getPropertyValue("content");if(""!==u&&"none"!==u){const t=s.getAttribute("class")||"",n=(s.setAttribute("class",t+" "+l),document.createElement("style"));function e(){const e=`.${l}:`+o,t=(i.cssText?n:r)();return document.createTextNode(e+`{${t}}`);function n(){return`${i.cssText} content: ${u};`}function r(){const e=a.asArray(i).map(t).join("; ");return e+";";function t(e){const t=i.getPropertyValue(e),n=i.getPropertyPriority(e)?" !important":"";return e+": "+t+n}}}n.appendChild(e()),s.appendChild(n)}}[":before",":after"].forEach(function(e){t(e)})}function n(){a.isHTMLTextAreaElement(c)&&(s.innerHTML=c.value),a.isHTMLInputElement(c)&&s.setAttribute("value",c.value)}function r(){a.isSVGElement(s)&&(s.setAttribute("xmlns","http://www.w3.org/2000/svg"),a.isSVGRectElement(s))&&["width","height"].forEach(function(e){const t=s.getAttribute(e);t&&s.style.setProperty(e,t)})}}}(e,o.filter,null,t)}).then(d).then(p).then(function(t){o.bgcolor&&(t.style.backgroundColor=o.bgcolor);o.width&&(t.style.width=o.width+"px");o.height&&(t.style.height=o.height+"px");o.style&&Object.keys(o.style).forEach(function(e){t.style[e]=o.style[e]});let e=null;"function"==typeof o.onclone&&(e=o.onclone(t));return Promise.resolve(e).then(function(){return t})}).then(function(e){return e=e,t=o.width||a.width(r),n=o.height||a.height(r),Promise.resolve(e).then(function(e){return e.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(e)}).then(a.escapeXhtml).then(function(e){return`${e}`}).then(function(e){return`${e}`}).then(function(e){return"data:image/svg+xml;charset=utf-8,"+e});var t,n}).then(function(e){return l.impl.urlCache=[],e})}function h(o,i){return s(o,i=i||{}).then(a.makeImage).then(function(e){var t="number"!=typeof i.scale?1:i.scale,n=function(e,t){var n=document.createElement("canvas");n.width=(i.width||a.width(e))*t,n.height=(i.height||a.height(e))*t,i.bgcolor&&((e=n.getContext("2d")).fillStyle=i.bgcolor,e.fillRect(0,0,n.width,n.height));return n}(o,t),r=n.getContext("2d");return r.mozImageSmoothingEnabled=!1,r.msImageSmoothingEnabled=!1,r.imageSmoothingEnabled=!1,e&&(r.scale(t,t),r.drawImage(e,0,0)),m&&(document.body.removeChild(m),m=null),y&&clearTimeout(y),y=setTimeout(()=>{y=null,v={}},2e4),n})}let m=null;function d(n){return e.resolveAll().then(function(e){var t;return""!==e&&(t=document.createElement("style"),n.appendChild(t),t.appendChild(document.createTextNode(e))),n})}function p(e){return r.inlineAll(e).then(function(){return e})}function g(i,u,e){const l=function(e){if(v[e])return v[e];{var t;m||((m=document.createElement("iframe")).style.visibility="hidden",m.style.position="fixed",document.body.appendChild(m),(t=document.createElement("meta")).setAttribute("charset",document.characterSet||"UTF-8"),m.contentDocument.head.appendChild(t),m.contentDocument.title="sandbox")}const n=m.contentWindow,r=n.document,o=r.createElement(e),i=(n.document.body.appendChild(o),o.textContent="​",n.getComputedStyle(o)),u={};return a.asArray(i).forEach(function(e){u[e]="width"===e||"height"===e?"auto":i.getPropertyValue(e)}),r.body.removeChild(o),v[e]=u}(e.tagName),c=e.style;a.asArray(i).forEach(function(e){var t,n=i.getPropertyValue(e),r=l[e],o=u?u.getPropertyValue(e):void 0;(n!==r||u&&n!==o)&&(r=i.getPropertyPriority(e),o=c,n=n,r=r,t=0<=["background-clip"].indexOf(e=e),r?(o.setProperty(e,n,r),t&&o.setProperty("-webkit-"+e,n,r)):(o.setProperty(e,n),t&&o.setProperty("-webkit-"+e,n)))})}let y=null,v={}}(this); +/*! dom-to-image-more 18-01-2023 */ +!function(n){"use strict";const s=function(){let e=0;return{escape:function(e){return e.replace(/([.*+?^${}()|[]\/\\])/g,"\\$1")},isDataUrl:function(e){return-1!==e.search(/^(data:)/)},canvasToBlob:function(t){if(t.toBlob)return new Promise(function(e){t.toBlob(e)});return function(o){return new Promise(function(e){var t=c(o.toDataURL().split(",")[1]),n=t.length,r=new Uint8Array(n);for(let e=0;et.style.removeProperty(e)),["left","right","top","bottom"].forEach(e=>{t.style.getPropertyValue(e)&&t.style.setProperty(e,"0px")})))}e(c,a)}function t(){const l=s.uid();function t(o){const i=f(c,o),u=i.getPropertyValue("content");if(""!==u&&"none"!==u){const t=a.getAttribute("class")||"",n=(a.setAttribute("class",t+" "+l),document.createElement("style"));function e(){const e=`.${l}:`+o,t=(i.cssText?n:r)();return document.createTextNode(e+`{${t}}`);function n(){return`${i.cssText} content: ${u};`}function r(){const e=s.asArray(i).map(t).join("; ");return e+";";function t(e){const t=i.getPropertyValue(e),n=i.getPropertyPriority(e)?" !important":"";return e+": "+t+n}}}n.appendChild(e()),a.appendChild(n)}}[":before",":after"].forEach(function(e){t(e)})}function n(){s.isHTMLTextAreaElement(c)&&(a.innerHTML=c.value),s.isHTMLInputElement(c)&&a.setAttribute("value",c.value)}function r(){s.isSVGElement(a)&&(a.setAttribute("xmlns","http://www.w3.org/2000/svg"),s.isSVGRectElement(a))&&["width","height"].forEach(function(e){const t=a.getAttribute(e);t&&a.style.setProperty(e,t)})}}}(e,o.filter,null,t)}).then(d).then(p).then(function(t){o.bgcolor&&(t.style.backgroundColor=o.bgcolor);o.width&&(t.style.width=o.width+"px");o.height&&(t.style.height=o.height+"px");o.style&&Object.keys(o.style).forEach(function(e){t.style[e]=o.style[e]});let e=null;"function"==typeof o.onclone&&(e=o.onclone(t));return Promise.resolve(e).then(function(){return t})}).then(function(e){return e=e,t=o.width||s.width(r),n=o.height||s.height(r),Promise.resolve(e).then(function(e){return e.setAttribute("xmlns","http://www.w3.org/1999/xhtml"),(new XMLSerializer).serializeToString(e)}).then(s.escapeXhtml).then(function(e){return`${e}`}).then(function(e){return`${e}`}).then(function(e){return"data:image/svg+xml;charset=utf-8,"+e});var t,n}).then(function(e){return l.impl.urlCache=[],e})}function h(o,i){return a(o,i=i||{}).then(s.makeImage).then(function(e){var t="number"!=typeof i.scale?1:i.scale,n=function(e,t){var n=document.createElement("canvas");n.width=(i.width||s.width(e))*t,n.height=(i.height||s.height(e))*t,i.bgcolor&&((e=n.getContext("2d")).fillStyle=i.bgcolor,e.fillRect(0,0,n.width,n.height));return n}(o,t),r=n.getContext("2d");return r.mozImageSmoothingEnabled=!1,r.msImageSmoothingEnabled=!1,r.imageSmoothingEnabled=!1,e&&(r.scale(t,t),r.drawImage(e,0,0)),m&&(document.body.removeChild(m),m=null),y&&clearTimeout(y),y=setTimeout(()=>{y=null,v={}},2e4),n})}let m=null;function d(n){return e.resolveAll().then(function(e){var t;return""!==e&&(t=document.createElement("style"),n.appendChild(t),t.appendChild(document.createTextNode(e))),n})}function p(e){return r.inlineAll(e).then(function(){return e})}function g(e,i,u,t){const l=function(e){var e=function(e){var t=[];do{if(1===e.nodeType){var n=e.tagName;if(t.push(n),E.includes(n))break}}while(e=e.parentNode,e);return t}(e),t=e.join(">");if(v[t])return v[t];var n=function(){{var e;m||((m=document.createElement("iframe")).style.visibility="hidden",m.style.position="fixed",document.body.appendChild(m),(e=document.createElement("meta")).setAttribute("charset",document.characterSet||"UTF-8"),m.contentDocument.head.appendChild(e),m.contentDocument.title="sandbox")}return m.contentWindow}(),e=function(e,t){let n=e.body;do{var r=t.pop(),r=e.createElement(r);n.appendChild(r),n=r}while(0 renderToSvg(node, { styleCaching: 'strict' }))]) + .then( + (promises) => promises[0].value + ); + let two = Promise.allSettled([ + loadTestPage('padding/dom-node.html', 'padding/style.css', 'padding/control-image') + .then((node) => renderToSvg(node, { styleCaching: 'relaxed' }))]) + .then( + (promises) => promises[0].value + ); + + Promise.allSettled([one, two]) + .then(function (promises) { + const strict = promises[0].value; + const relaxed = promises[1].value; + if (strict !== relaxed) { + console.log(`\n\nstrict: ${strict}\n\nrelaxed: ${relaxed}\n\n`); + } + assert.equal(strict, relaxed, 'SVG rendered be same'); + }) + .then(done) + .catch(done); + }); + }); + function loadTestPage(html, css, controlImage) { return loadPage() - .then(function () { - return getResource(html).then(function (html) { - $('#dom-node').html(html); - }); + .then(function (document) { + if (!html) + return document; + + return getResource(html) + .then(function (html) { + $('#dom-node').html(html); + return document; + }); }) - .then(function () { - if (css) { - return getResource(css).then(function (css) { + .then(function (document) { + if (!css) + return document; + + return getResource(css) + .then(function (css) { $('#style').append(document.createTextNode(css)); + return document; }); - } }) - .then(function () { - if (controlImage) { - return getResource(controlImage).then(function (image) { + .then(function (document) { + if (!controlImage) + return document; + + return getResource(controlImage) + .then(function (image) { $('#control-image').attr('src', image); + return document; }); - } }); } function loadPage() { - return getResource('page.html').then(function (html) { - const root = document.createElement('div'); - root.id = 'test-root'; - root.innerHTML = html; - document.body.appendChild(root); - }); + return getResource('page.html') + .then(function (html) { + const root = document.createElement('div'); + root.id = 'test-root'; + root.innerHTML = html; + document.body.appendChild(root); + return document; + }); } function purgePage() { @@ -925,5 +991,19 @@ request.send(); }); } + + function renderToPng() { + return domtoimage.toPng(domNode(), { onclone: cloneCatcher }); + } + + function renderToSvg(options) { + const debugOptions = { onclone: cloneCatcher, debugCache: true }; + return domtoimage.toSvg(domNode(), Object.assign(debugOptions, options)); + } + + function cloneCatcher(clone) { + clonedNode().replaceChildren(clone); + return clone; + } }); })(this); diff --git a/spec/resources/math/control-image b/spec/resources/math/control-image new file mode 100644 index 00000000..b76adb26 --- /dev/null +++ b/spec/resources/math/control-image @@ -0,0 +1 @@ +data:image/png;base64,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 \ No newline at end of file diff --git a/spec/resources/math/dom-node.html b/spec/resources/math/dom-node.html new file mode 100644 index 00000000..1067834d --- /dev/null +++ b/spec/resources/math/dom-node.html @@ -0,0 +1,34 @@ +
+ The infinite sum + + + + + n + = + 1 + + + + + + + + + 1 + + n + 2 + + + + +
Is equal to the real number + + + π + 2 + + 6 + + +
\ No newline at end of file diff --git a/spec/resources/padding/control-image b/spec/resources/padding/control-image index f5f53a4c..3082dd49 100644 --- a/spec/resources/padding/control-image +++ b/spec/resources/padding/control-image @@ -1 +1 @@ -data:image/png;base64,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 \ No newline at end of file +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABooAAABCCAYAAABgiYT+AAAAAXNSR0IArs4c6QAAEp5JREFUeF7t3Xuw3+OdB/D3SSIiCZGQRIR1C0pR3Vp2tUq1XSytmVWrraN0Kdalbm0RlzWxW9Zl7Baru4sa+dGj06CLKl1WdVxWq+6EdYuNJK5xF7nufL/5nTNH22Sec2Tm5HfO6zdj5JzP8/1+n+f1Ob+/3vM837avtrcvic+AE+hoNNoG3KItmAABAgQIECBAgAABAgQIECBAgAABAgQIEPiQQJugaGD+RQiKBmbfrZoAAQIECBAgQIAAAQIECBAgQIAAAQIECHQX6AqKVsbgoDPE6uu5dc7jhEaj5f96zm9vr9fQ16YtD2kBBAgQIECAAAECBAgQIECAAAECBAgQIECgHwgIigqaKCgqQDKEAAECBAgQIECAAAECBAgQIECAAAECBAgQaDkBQVFBywRFBUiGECBAgAABAgQIECBAgAABAgQIECBAgAABAi0nICgqaJmgqADJEAIECBAgQIAAAQIECBAgQIAAAQIECBAgQKDlBARFBS0TFBUgGUKAAAECBAgQIECAAAECBAgQIECAAAECBAi0nICgqKBlgqICJEMIECBAgAABAgQIECBAgAABAgQIECBAgACBlhMQFBW0rKdB0W+SnJlkjSRzkwxK8vUkX2s+qy/r57e317PoaDTaCpZuCAECBAgQIECAAAECBAgQIECAAAECBAgQINCPBQRFBc3taVB0a5IPknwpyatJ9mg+49ok6yfpy/pPBEUFHTeEAAECBAgQIECAAAECBAgQIECAAAECBAgMDAFBUUGfexoULWzuIqp2ElWfHZIsTvKDJH+RpC/rdwuKCjpuCAECBAgQIECAAAECBAgQIECAAAECBAgQGBgCgqKCPvc0KHoiyZVJXmweP3dfkiXdgqK+rAuKChpuCAECBAgQIECAAAECBAgQIECAAAECBAgQGCACgqKCRvckKHo3yZeTvJXkouZuou47irbp47qgqKDhhhAgQIAAAQIECBAgQIAAAQIECBAgQIAAgQEiICgqaHRPgqLHkxzYvOevkwz7vaPnRvVxXVBU0HBDCBAgQIAAAQIECBAgQIAAAQIECBAgQIDAABEQFBU0uidB0StJ9mq+k+jHSSYm2aXbO4om9XFdUFTQcEMIECBAgAABAgQIECBAgAABAgQIECBAgMAAERAUFTS6J0FRdbupzf+qf2+XpHon0cwkWye5NMlVfVjfcv/909bWlo5Go61g6YYQIECAAAECBAgQIECAAAECBAgQIECAAAEC/VhAUFTQ3J4GRQW37LMh57e3188WFPVZCzyYAAECBAgQIECAAAECBAgQIECAAAECBAisNAKCooJWCIoKkAwhQIAAAQIECBAgQIAAAQIECBAgQIAAAQIEWk5AUFTQMkFRAZIhBAgQIECAAAECBAgQIECAAAECBAgQIECAQMsJCIoKWiYoKkAyhAABAgQIECBAgAABAgQIECBAgAABAgQIEGg5ga6gqOVmbsIfScA7ij4Sn4sJECBAgAABAgQIECBAgAABAgQIECBAgEC/EBAU9Ys29nwRgqKem7mCAAECBAgQIECAAAECBAgQIECAAAECBAj0NwFHzxV01NFzBUiGECBAgAABAgQIECBAgAABAgQIECBAgAABAi0nICgqaJmgqADJEAIECBAgQIAAAQIECBAgQIAAAQIECBAgQKDlBARFBS0TFBUgGUKAAAECBAgQIECAAAECBAgQIECAAAECBAi0nICgqKBlgqICJEMIECBAgAABAgQIECBAgAABAgQIECBAgACBlhMQFBW0TFBUgGQIAQIECBAgQIAAAQIECBAgQIAAAQIECBAg0HICgqKClgmKCpAMIUCAAAECBAgQIECAAAECBAgQIECAAAECBFpOQFBU0LKSoOitJEcnmZik+vfQJGclWbV5/5OTfND8+cUkU5JsWFCbmuTuJGsneSbJIUl2bV7Xm9r57e311R2NRlvB0g0hQIAAAQIECBAgQIAAAQIECBAgQIAAAQIE+rGAoKiguSVB0dwktyX5SpLFSXZPcmySv2re/9JmyFP9eGKSkUlOK6j9KMk3kgxO8pMkVye5vnldb2qCooKGG0KAAAECBAgQIECAAAECBAgQIECAAAECBAaIgKCooNElQdHv32a/Zkh04B+5/zlJZib5QQ9rVRB1epK7/sh1pTVBUUHDDSFAgAABAgQIECBAgAABAgQIECBAgAABAgNEQFBU0OiSoOjNJNUOn+rYuRFJbk5SHfJ2UHOHUbUT6Kkko5Lc3zxKrgqKqt1Hy6pVU/tVkv9KskaSWUnu6xYU9aYmKCpouCEECBAgQIAAAQIECBAgQIAAAQIECBAgQGCACAiKChpdEhQdn2R0t+Pkqh1FezSDokaSnyW5qvnuou47ipZXeyLJN5NMa777qPuuod7WBEUFDTeEAAECBAgQIECAAAECBAgQIECAAAECBAgMEAFBUUGjS4Ki3ZIckWTv5v26B0WTkwxJMqVZ6x4ULa9WBUSXJ7mpeV33oKi3NUFRQcMNIUCAAAECBAgQIECAAAECBAgQIECAAAECA0RAUFTQ6JKg6KtJPpHk5CRzkhycZN/mjqJzkzyQ5IokC5OckmRR8x1Fy6vdnuTUJNcmGds82q463q56R1Fva4KigoYbQoAAAQIECBAgQIAAAQIECBAgQIAAAQIEBoiAoKig0SVB0R1Jzk4yKMkuSZ5PUr236LQkw5N8N8mrzTBpnSTV7qDquLotllP7XJLvJXkwyYZJdk1ycTN8qoKo3tTea6/enJR0NBptBUs3hAABAgQIECBAgAABAgQIECBAgAABAgQIEOjHAoKiguaWBEUFt1kphthRtFK0wSQIECBAgAABAgQIECBAgAABAgQIECBAgMBKISAoKmiDoKgAyRACBAgQIECAAAECBAgQIECAAAECBAgQIECg5QQERQUtExQVIBlCgAABAgQIECBAgAABAgQIECBAgAABAgQItJyAoKigZYKiAiRDCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZYT6AqKWm7mJvyRBDoajbaPdAMXEyBAgAABAgQIECBAgAABAgQIECBAgAABAi0vIChq+Rb2bgGCot65uYoAAQIECBAgQIAAAQIECBAgQIAAAQIECPQnga6gaHjj6JVuXe+1X1jPqa/ntrLMY0U0qHMtgqIVoekeBAgQIECAAAECBAgQIECAAAECBAgQIECgtQUERQX9ExQVIBlCgAABAgQIECBAgAABAgQIECBAgAABAgQItJyAoKigZYKiAiRDCBAgQIAAAQIECBAgQIAAAQIECBAgQIAAgZYTEBQVtExQVIBkCAECBAgQIECAAAECBAgQIECAAAECBAgQINByAoKigpYJigqQDCFAgAABAgQIECBAgAABAgQIECBAgAABAgRaTkBQVNAyQVEBkiEECBAgQIAAAQIECBAgQIAAAQIECBAgQIBAywl8KCjac/K6+dguq+eDdxdn3KRhOf+L0/PmnAXZZs81s9sJ6+Sd1xbWv7/u1Jl5+KY3Mn6zYWm/aIO898aijF5v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 \ No newline at end of file diff --git a/spec/resources/scroll/control-image b/spec/resources/scroll/control-image index 77e7950b..5918844f 100644 --- a/spec/resources/scroll/control-image +++ b/spec/resources/scroll/control-image @@ -1 +1 @@ -data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAABa0lEQVR4Xu3VwQkAQAjEQO2/aA+uijzGCkLC4s7cjcsYWEEyLT6IIK0egsR6CCJIzUCMxw8RJGYghmMhgsQMxHAsRJCYgRiOhQgSMxDDsRBBYgZiOBYiSMxADMdCBIkZiOFYiCAxAzEcCxEkZiCGYyGCxAzEcCxEkJiBGI6FCBIzEMOxEEFiBmI4FiJIzEAMx0IEiRmI4ViIIDEDMRwLESRmIIZjIYLEDMRwLESQmIEYjoUIEjMQw7EQQWIGYjgWIkjMQAzHQgSJGYjhWIggMQMxHAsRJGYghmMhgsQMxHAsRJCYgRiOhQgSMxDDsRBBYgZiOBYiSMxADMdCBIkZiOFYiCAxAzEcCxEkZiCGYyGCxAzEcCxEkJiBGI6FCBIzEMOxEEFiBmI4FiJIzEAMx0IEiRmI4ViIIDEDMRwLESRmIIZjIYLEDMRwLESQmIEYjoUIEjMQw7EQQWIGYjgWIkjMQAzHQgSJGYjhPE5Hx53K44yoAAAAAElFTkSuQmCC +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAAXNSR0IArs4c6QAAAUpJREFUaEPtmdERwyAIhslGmSQrZLaskEncI092gfTs1bskJyJUr5iQV7H14wfkZADYd1Dyef8Sn2QwELHv8I2mCABYaDWILHhEaK3rCtM0of7rIrQCRPwwGPUgR4gcjGqQFAQGoxqEU1AMhOOtUttHlF/KGRZalIck6zG0nHPF28dx/NiqVMRAinVsbGihpTVHJMKrTHYDkXigxR5rUbQn+zzPqPDLspzW1Cd7CuYKobZFucpwhElBdAMSDhpgMIiuQKgqqT5HKIC4biClnuLY2YWo/ULkqDl479WM3rZt45z9fLMbCACkHgniq4bEtX9TpCuQ3ICFA0K1GEHBZorEZ31suMIFCYfN9UtNQEqmRBKQHEx1kOuApaYisQiklKkOEv7sFopEr90iR44wtUIrl+hNqxZ1qXGSnfotA/l6yJrGklDh2vxSft/tDX2VNbDgQAAAAABJRU5ErkJggg== \ No newline at end of file diff --git a/spec/resources/test.html b/spec/resources/test.html deleted file mode 100644 index b6b3734d..00000000 --- a/spec/resources/test.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - -
Image: - -
Control: - -
diff --git a/src/dom-to-image-more.js b/src/dom-to-image-more.js index 9709904c..cdc6e7c6 100644 --- a/src/dom-to-image-more.js +++ b/src/dom-to-image-more.js @@ -16,6 +16,8 @@ useCredentials: false, // Default resolve timeout httpTimeout: 30000, + // Style computation cache tag rules (options are strict, relaxed) + styleCaching: 'strict', }; const domtoimage = { @@ -62,6 +64,7 @@ * @param {Number} options.scale - a Number multiplier to scale up the canvas before rendering to reduce fuzzy images, defaults to 1.0. * @param {String} options.imagePlaceholder - dataURL to use as a placeholder for failed images, default behaviour is to fail fast on images we can't fetch * @param {Boolean} options.cacheBust - set to true to cache bust by appending the time to the request url + * @param {String} options.styleCaching - set to 'strict', 'relaxed' to select style caching rules * @return {Promise} - A promise that is fulfilled with a SVG image data URL * */ function toSvg(node, options) { @@ -70,7 +73,7 @@ copyOptions(options); return Promise.resolve(node) .then(function (clonee) { - return cloneNode(clonee, options.filter, null, ownerWindow); + return cloneNode(clonee, options, null, ownerWindow); }) .then(embedFonts) .then(inlineImages) @@ -99,7 +102,6 @@ if (options.height) { clone.style.height = `${options.height}px`; } - if (options.style) { Object.keys(options.style).forEach(function (property) { clone.style[property] = options.style[property]; @@ -199,6 +201,12 @@ } else { domtoimage.impl.options.httpTimeout = options.httpTimeout; } + + if (typeof options.styleCaching === 'undefined') { + domtoimage.impl.options.styleCaching = defaultOptions.styleCaching; + } else { + domtoimage.impl.options.styleCaching = options.styleCaching; + } } function draw(domNode, options) { @@ -237,7 +245,8 @@ let sandbox = null; - function cloneNode(node, filter, parentComputedStyles, ownerWindow) { + function cloneNode(node, options, parentComputedStyles, ownerWindow) { + const filter = options.filter; if ( node === sandbox || (parentComputedStyles !== null && filter && !filter(node)) @@ -271,7 +280,7 @@ done = done.then(function () { return cloneNode( originalChild, - filter, + options, originalComputedStyles, ownerWindow ).then(function (clonedChild) { @@ -329,6 +338,8 @@ copyFont(sourceComputedStyles, targetElement.style); // here we re-assign the font props. } else { copyUserComputedStyleFast( + options, + sourceElement, sourceComputedStyles, parentComputedStyles, targetElement @@ -720,6 +731,7 @@ function width(node) { var width = px(node, 'width'); + if (isNaN(width)) { const leftBorder = px(node, 'border-left-width'); const rightBorder = px(node, 'border-right-width'); @@ -730,6 +742,7 @@ function height(node) { var height = px(node, 'height'); + if (isNaN(height)) { const topBorder = px(node, 'border-top-width'); const bottomBorder = px(node, 'border-bottom-width'); @@ -870,8 +883,8 @@ cssRules.push.bind(cssRules) ); } catch (e) { - console.log( - `Error while reading CSS rules from ${sheet.href}`, + console.error( + `domtoimage: Error while reading CSS rules from ${sheet.href}`, e.toString() ); } @@ -981,11 +994,13 @@ } function copyUserComputedStyleFast( + options, + sourceElement, sourceComputedStyles, parentComputedStyles, targetElement ) { - const defaultStyle = getDefaultStyle(targetElement.tagName); + const defaultStyle = getDefaultStyle(options, sourceElement); const targetStyle = targetElement.style; util.asArray(sourceComputedStyles).forEach(function (name) { @@ -1010,45 +1025,158 @@ let removeDefaultStylesTimeoutId = null; let tagNameDefaultStyles = {}; - function getDefaultStyle(tagName) { - if (tagNameDefaultStyles[tagName]) { - return tagNameDefaultStyles[tagName]; + const ascentStoppers = [ + // these come from https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements + 'ADDRESS', + 'ARTICLE', + 'ASIDE', + 'BLOCKQUOTE', + 'DETAILS', + 'DIALOG', + 'DD', + 'DIV', + 'DL', + 'DT', + 'FIELDSET', + 'FIGCAPTION', + 'FIGURE', + 'FOOTER', + 'FORM', + 'H1', + 'H2', + 'H3', + 'H4', + 'H5', + 'H6', + 'HEADER', + 'HGROUP', + 'HR', + 'LI', + 'MAIN', + 'NAV', + 'OL', + 'P', + 'PRE', + 'SECTION', + 'TABLE', + 'UL', + // this is some non-standard ones + 'math', // intentionally lowercase, thanks Safari + // these are ultimate stoppers in case something drastic changes in how the DOM works + 'SVG', + 'BODY', + 'HEAD', + 'HTML', + ]; + + function getDefaultStyle(options, sourceElement) { + const tagHierarchy = computeTagHierarchy(sourceElement); + const tagKey = computeTagKey(tagHierarchy); + if (tagNameDefaultStyles[tagKey]) { + return tagNameDefaultStyles[tagKey]; } - if (!sandbox) { - // Create a hidden sandbox