polotno-node 2.13.0 → 2.14.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/README.md +31 -0
- package/dist/assets/html2canvas.esm-DXEQVQnt.js +5 -0
- package/dist/assets/{index-vFr48NCL.js → index-CeWB3Frt.js} +115 -115
- package/dist/assets/index-JEDO0Skc.js +65 -0
- package/dist/assets/{index.es-Bm4liNaR.js → index.es-BvYTbih-.js} +2 -2
- package/dist/assets/purify.es-Bzr520pe.js +2 -0
- package/dist/index.html +1 -1
- package/index.d.ts +16 -0
- package/instance.js +171 -16
- package/package.json +10 -7
- package/video-parallel.js +1 -1
- package/dist/assets/html2canvas.esm-Ge7aVWlp.js +0 -5
- package/dist/assets/purify.es-C65SP4u9.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const{entries:_t,setPrototypeOf:ct,isFrozen:Yt,getPrototypeOf:Xt,getOwnPropertyDescriptor:jt}=Object;let{freeze:S,seal:L,create:ve}=Object,{apply:ke,construct:Ue}=typeof Reflect<"u"&&Reflect;S||(S=function(o){return o});L||(L=function(o){return o});ke||(ke=function(o,l){for(var a=arguments.length,c=new Array(a>2?a-2:0),O=2;O<a;O++)c[O-2]=arguments[O];return o.apply(l,c)});Ue||(Ue=function(o){for(var l=arguments.length,a=new Array(l>1?l-1:0),c=1;c<l;c++)a[c-1]=arguments[c];return new o(...a)});const ce=R(Array.prototype.forEach),Vt=R(Array.prototype.lastIndexOf),ft=R(Array.prototype.pop),q=R(Array.prototype.push),$t=R(Array.prototype.splice),ue=R(String.prototype.toLowerCase),Ie=R(String.prototype.toString),Ce=R(String.prototype.match),K=R(String.prototype.replace),qt=R(String.prototype.indexOf),Kt=R(String.prototype.trim),y=R(Object.prototype.hasOwnProperty),h=R(RegExp.prototype.test),Z=Zt(TypeError);function R(s){return function(o){o instanceof RegExp&&(o.lastIndex=0);for(var l=arguments.length,a=new Array(l>1?l-1:0),c=1;c<l;c++)a[c-1]=arguments[c];return ke(s,o,a)}}function Zt(s){return function(){for(var o=arguments.length,l=new Array(o),a=0;a<o;a++)l[a]=arguments[a];return Ue(s,l)}}function r(s,o){let l=arguments.length>2&&arguments[2]!==void 0?arguments[2]:ue;ct&&ct(s,null);let a=o.length;for(;a--;){let c=o[a];if(typeof c=="string"){const O=l(c);O!==c&&(Yt(o)||(o[a]=O),c=O)}s[c]=!0}return s}function Jt(s){for(let o=0;o<s.length;o++)y(s,o)||(s[o]=null);return s}function I(s){const o=ve(null);for(const[l,a]of _t(s))y(s,l)&&(Array.isArray(a)?o[l]=Jt(a):a&&typeof a=="object"&&a.constructor===Object?o[l]=I(a):o[l]=a);return o}function J(s,o){for(;s!==null;){const a=jt(s,o);if(a){if(a.get)return R(a.get);if(typeof a.value=="function")return R(a.value)}s=Xt(s)}function l(){return null}return l}const ut=S(["a","abbr","acronym","address","area","article","aside","audio","b","bdi","bdo","big","blink","blockquote","body","br","button","canvas","caption","center","cite","code","col","colgroup","content","data","datalist","dd","decorator","del","details","dfn","dialog","dir","div","dl","dt","element","em","fieldset","figcaption","figure","font","footer","form","h1","h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","img","input","ins","kbd","label","legend","li","main","map","mark","marquee","menu","menuitem","meter","nav","nobr","ol","optgroup","option","output","p","picture","pre","progress","q","rp","rt","ruby","s","samp","search","section","select","shadow","slot","small","source","spacer","span","strike","strong","style","sub","summary","sup","table","tbody","td","template","textarea","tfoot","th","thead","time","tr","track","tt","u","ul","var","video","wbr"]),Me=S(["svg","a","altglyph","altglyphdef","altglyphitem","animatecolor","animatemotion","animatetransform","circle","clippath","defs","desc","ellipse","enterkeyhint","exportparts","filter","font","g","glyph","glyphref","hkern","image","inputmode","line","lineargradient","marker","mask","metadata","mpath","part","path","pattern","polygon","polyline","radialgradient","rect","stop","style","switch","symbol","text","textpath","title","tref","tspan","view","vkern"]),we=S(["feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDistantLight","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussianBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence"]),Qt=S(["animate","color-profile","cursor","discard","font-face","font-face-format","font-face-name","font-face-src","font-face-uri","foreignobject","hatch","hatchpath","mesh","meshgradient","meshpatch","meshrow","missing-glyph","script","set","solidcolor","unknown","use"]),xe=S(["math","menclose","merror","mfenced","mfrac","mglyph","mi","mlabeledtr","mmultiscripts","mn","mo","mover","mpadded","mphantom","mroot","mrow","ms","mspace","msqrt","mstyle","msub","msup","msubsup","mtable","mtd","mtext","mtr","munder","munderover","mprescripts"]),en=S(["maction","maligngroup","malignmark","mlongdiv","mscarries","mscarry","msgroup","mstack","msline","msrow","semantics","annotation","annotation-xml","mprescripts","none"]),mt=S(["#text"]),pt=S(["accept","action","align","alt","autocapitalize","autocomplete","autopictureinpicture","autoplay","background","bgcolor","border","capture","cellpadding","cellspacing","checked","cite","class","clear","color","cols","colspan","controls","controlslist","coords","crossorigin","datetime","decoding","default","dir","disabled","disablepictureinpicture","disableremoteplayback","download","draggable","enctype","enterkeyhint","exportparts","face","for","headers","height","hidden","high","href","hreflang","id","inert","inputmode","integrity","ismap","kind","label","lang","list","loading","loop","low","max","maxlength","media","method","min","minlength","multiple","muted","name","nonce","noshade","novalidate","nowrap","open","optimum","part","pattern","placeholder","playsinline","popover","popovertarget","popovertargetaction","poster","preload","pubdate","radiogroup","readonly","rel","required","rev","reversed","role","rows","rowspan","spellcheck","scope","selected","shape","size","sizes","slot","span","srclang","start","src","srcset","step","style","summary","tabindex","title","translate","type","usemap","valign","value","width","wrap","xmlns","slot"]),Pe=S(["accent-height","accumulate","additive","alignment-baseline","amplitude","ascent","attributename","attributetype","azimuth","basefrequency","baseline-shift","begin","bias","by","class","clip","clippathunits","clip-path","clip-rule","color","color-interpolation","color-interpolation-filters","color-profile","color-rendering","cx","cy","d","dx","dy","diffuseconstant","direction","display","divisor","dur","edgemode","elevation","end","exponent","fill","fill-opacity","fill-rule","filter","filterunits","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","fx","fy","g1","g2","glyph-name","glyphref","gradientunits","gradienttransform","height","href","id","image-rendering","in","in2","intercept","k","k1","k2","k3","k4","kerning","keypoints","keysplines","keytimes","lang","lengthadjust","letter-spacing","kernelmatrix","kernelunitlength","lighting-color","local","marker-end","marker-mid","marker-start","markerheight","markerunits","markerwidth","maskcontentunits","maskunits","max","mask","mask-type","media","method","mode","min","name","numoctaves","offset","operator","opacity","order","orient","orientation","origin","overflow","paint-order","path","pathlength","patterncontentunits","patterntransform","patternunits","points","preservealpha","preserveaspectratio","primitiveunits","r","rx","ry","radius","refx","refy","repeatcount","repeatdur","restart","result","rotate","scale","seed","shape-rendering","slope","specularconstant","specularexponent","spreadmethod","startoffset","stddeviation","stitchtiles","stop-color","stop-opacity","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke","stroke-width","style","surfacescale","systemlanguage","tabindex","tablevalues","targetx","targety","transform","transform-origin","text-anchor","text-decoration","text-rendering","textlength","type","u1","u2","unicode","values","viewbox","visibility","version","vert-adv-y","vert-origin-x","vert-origin-y","width","word-spacing","wrap","writing-mode","xchannelselector","ychannelselector","x","x1","x2","xmlns","y","y1","y2","z","zoomandpan"]),Tt=S(["accent","accentunder","align","bevelled","close","columnsalign","columnlines","columnspan","denomalign","depth","dir","display","displaystyle","encoding","fence","frame","height","href","id","largeop","length","linethickness","lspace","lquote","mathbackground","mathcolor","mathsize","mathvariant","maxsize","minsize","movablelimits","notation","numalign","open","rowalign","rowlines","rowspacing","rowspan","rspace","rquote","scriptlevel","scriptminsize","scriptsizemultiplier","selection","separator","separators","stretchy","subscriptshift","supscriptshift","symmetric","voffset","width","xmlns"]),fe=S(["xlink:href","xml:id","xlink:title","xml:space","xmlns:xlink"]),tn=L(/\{\{[\w\W]*|[\w\W]*\}\}/gm),nn=L(/<%[\w\W]*|[\w\W]*%>/gm),on=L(/\$\{[\w\W]*/gm),an=L(/^data-[\-\w.\u00B7-\uFFFF]+$/),rn=L(/^aria-[\-\w]+$/),gt=L(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),sn=L(/^(?:\w+script|data):/i),ln=L(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),At=L(/^html$/i),cn=L(/^[a-z][.\w]*(-[.\w]+)+$/i);var dt=Object.freeze({__proto__:null,ARIA_ATTR:rn,ATTR_WHITESPACE:ln,CUSTOM_ELEMENT:cn,DATA_ATTR:an,DOCTYPE_NAME:At,ERB_EXPR:nn,IS_ALLOWED_URI:gt,IS_SCRIPT_OR_DATA:sn,MUSTACHE_EXPR:tn,TMPLIT_EXPR:on});const Q={element:1,text:3,progressingInstruction:7,comment:8,document:9},fn=function(){return typeof window>"u"?null:window},un=function(o,l){if(typeof o!="object"||typeof o.createPolicy!="function")return null;let a=null;const c="data-tt-policy-suffix";l&&l.hasAttribute(c)&&(a=l.getAttribute(c));const O="dompurify"+(a?"#"+a:"");try{return o.createPolicy(O,{createHTML(v){return v},createScriptURL(v){return v}})}catch{return console.warn("TrustedTypes policy "+O+" could not be created."),null}},Et=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function ht(){let s=arguments.length>0&&arguments[0]!==void 0?arguments[0]:fn();const o=i=>ht(i);if(o.version="3.3.1",o.removed=[],!s||!s.document||s.document.nodeType!==Q.document||!s.Element)return o.isSupported=!1,o;let{document:l}=s;const a=l,c=a.currentScript,{DocumentFragment:O,HTMLTemplateElement:v,Node:me,Element:Fe,NodeFilter:B,NamedNodeMap:St=s.NamedNodeMap||s.MozNamedAttrMap,HTMLFormElement:Rt,DOMParser:Ot,trustedTypes:ee}=s,Y=Fe.prototype,Dt=J(Y,"cloneNode"),Lt=J(Y,"remove"),yt=J(Y,"nextSibling"),bt=J(Y,"childNodes"),te=J(Y,"parentNode");if(typeof v=="function"){const i=l.createElement("template");i.content&&i.content.ownerDocument&&(l=i.content.ownerDocument)}let g,X="";const{implementation:pe,createNodeIterator:Nt,createDocumentFragment:It,getElementsByTagName:Ct}=l,{importNode:Mt}=a;let A=Et();o.isSupported=typeof _t=="function"&&typeof te=="function"&&pe&&pe.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:Te,ERB_EXPR:de,TMPLIT_EXPR:Ee,DATA_ATTR:wt,ARIA_ATTR:xt,IS_SCRIPT_OR_DATA:Pt,ATTR_WHITESPACE:He,CUSTOM_ELEMENT:vt}=dt;let{IS_ALLOWED_URI:ze}=dt,T=null;const Ge=r({},[...ut,...Me,...we,...xe,...mt]);let d=null;const We=r({},[...pt,...Pe,...Tt,...fe]);let u=Object.seal(ve(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),j=null,_e=null;const k=Object.seal(ve(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let Be=!0,ge=!0,Ye=!1,Xe=!0,U=!1,ne=!0,x=!1,Ae=!1,he=!1,F=!1,oe=!1,ie=!1,je=!0,Ve=!1;const kt="user-content-";let Se=!0,V=!1,H={},b=null;const Re=r({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let $e=null;const qe=r({},["audio","video","img","source","image","track"]);let Oe=null;const Ke=r({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),ae="http://www.w3.org/1998/Math/MathML",re="http://www.w3.org/2000/svg",C="http://www.w3.org/1999/xhtml";let z=C,De=!1,Le=null;const Ut=r({},[ae,re,C],Ie);let se=r({},["mi","mo","mn","ms","mtext"]),le=r({},["annotation-xml"]);const Ft=r({},["title","style","font","a","script"]);let $=null;const Ht=["application/xhtml+xml","text/html"],zt="text/html";let p=null,G=null;const Gt=l.createElement("form"),Ze=function(e){return e instanceof RegExp||e instanceof Function},ye=function(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(!(G&&G===e)){if((!e||typeof e!="object")&&(e={}),e=I(e),$=Ht.indexOf(e.PARSER_MEDIA_TYPE)===-1?zt:e.PARSER_MEDIA_TYPE,p=$==="application/xhtml+xml"?Ie:ue,T=y(e,"ALLOWED_TAGS")?r({},e.ALLOWED_TAGS,p):Ge,d=y(e,"ALLOWED_ATTR")?r({},e.ALLOWED_ATTR,p):We,Le=y(e,"ALLOWED_NAMESPACES")?r({},e.ALLOWED_NAMESPACES,Ie):Ut,Oe=y(e,"ADD_URI_SAFE_ATTR")?r(I(Ke),e.ADD_URI_SAFE_ATTR,p):Ke,$e=y(e,"ADD_DATA_URI_TAGS")?r(I(qe),e.ADD_DATA_URI_TAGS,p):qe,b=y(e,"FORBID_CONTENTS")?r({},e.FORBID_CONTENTS,p):Re,j=y(e,"FORBID_TAGS")?r({},e.FORBID_TAGS,p):I({}),_e=y(e,"FORBID_ATTR")?r({},e.FORBID_ATTR,p):I({}),H=y(e,"USE_PROFILES")?e.USE_PROFILES:!1,Be=e.ALLOW_ARIA_ATTR!==!1,ge=e.ALLOW_DATA_ATTR!==!1,Ye=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Xe=e.ALLOW_SELF_CLOSE_IN_ATTR!==!1,U=e.SAFE_FOR_TEMPLATES||!1,ne=e.SAFE_FOR_XML!==!1,x=e.WHOLE_DOCUMENT||!1,F=e.RETURN_DOM||!1,oe=e.RETURN_DOM_FRAGMENT||!1,ie=e.RETURN_TRUSTED_TYPE||!1,he=e.FORCE_BODY||!1,je=e.SANITIZE_DOM!==!1,Ve=e.SANITIZE_NAMED_PROPS||!1,Se=e.KEEP_CONTENT!==!1,V=e.IN_PLACE||!1,ze=e.ALLOWED_URI_REGEXP||gt,z=e.NAMESPACE||C,se=e.MATHML_TEXT_INTEGRATION_POINTS||se,le=e.HTML_INTEGRATION_POINTS||le,u=e.CUSTOM_ELEMENT_HANDLING||{},e.CUSTOM_ELEMENT_HANDLING&&Ze(e.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(u.tagNameCheck=e.CUSTOM_ELEMENT_HANDLING.tagNameCheck),e.CUSTOM_ELEMENT_HANDLING&&Ze(e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(u.attributeNameCheck=e.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),e.CUSTOM_ELEMENT_HANDLING&&typeof e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(u.allowCustomizedBuiltInElements=e.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),U&&(ge=!1),oe&&(F=!0),H&&(T=r({},mt),d=[],H.html===!0&&(r(T,ut),r(d,pt)),H.svg===!0&&(r(T,Me),r(d,Pe),r(d,fe)),H.svgFilters===!0&&(r(T,we),r(d,Pe),r(d,fe)),H.mathMl===!0&&(r(T,xe),r(d,Tt),r(d,fe))),e.ADD_TAGS&&(typeof e.ADD_TAGS=="function"?k.tagCheck=e.ADD_TAGS:(T===Ge&&(T=I(T)),r(T,e.ADD_TAGS,p))),e.ADD_ATTR&&(typeof e.ADD_ATTR=="function"?k.attributeCheck=e.ADD_ATTR:(d===We&&(d=I(d)),r(d,e.ADD_ATTR,p))),e.ADD_URI_SAFE_ATTR&&r(Oe,e.ADD_URI_SAFE_ATTR,p),e.FORBID_CONTENTS&&(b===Re&&(b=I(b)),r(b,e.FORBID_CONTENTS,p)),e.ADD_FORBID_CONTENTS&&(b===Re&&(b=I(b)),r(b,e.ADD_FORBID_CONTENTS,p)),Se&&(T["#text"]=!0),x&&r(T,["html","head","body"]),T.table&&(r(T,["tbody"]),delete j.tbody),e.TRUSTED_TYPES_POLICY){if(typeof e.TRUSTED_TYPES_POLICY.createHTML!="function")throw Z('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof e.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw Z('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');g=e.TRUSTED_TYPES_POLICY,X=g.createHTML("")}else g===void 0&&(g=un(ee,c)),g!==null&&typeof X=="string"&&(X=g.createHTML(""));S&&S(e),G=e}},Je=r({},[...Me,...we,...Qt]),Qe=r({},[...xe,...en]),Wt=function(e){let t=te(e);(!t||!t.tagName)&&(t={namespaceURI:z,tagName:"template"});const n=ue(e.tagName),f=ue(t.tagName);return Le[e.namespaceURI]?e.namespaceURI===re?t.namespaceURI===C?n==="svg":t.namespaceURI===ae?n==="svg"&&(f==="annotation-xml"||se[f]):!!Je[n]:e.namespaceURI===ae?t.namespaceURI===C?n==="math":t.namespaceURI===re?n==="math"&&le[f]:!!Qe[n]:e.namespaceURI===C?t.namespaceURI===re&&!le[f]||t.namespaceURI===ae&&!se[f]?!1:!Qe[n]&&(Ft[n]||!Je[n]):!!($==="application/xhtml+xml"&&Le[e.namespaceURI]):!1},N=function(e){q(o.removed,{element:e});try{te(e).removeChild(e)}catch{Lt(e)}},P=function(e,t){try{q(o.removed,{attribute:t.getAttributeNode(e),from:t})}catch{q(o.removed,{attribute:null,from:t})}if(t.removeAttribute(e),e==="is")if(F||oe)try{N(t)}catch{}else try{t.setAttribute(e,"")}catch{}},et=function(e){let t=null,n=null;if(he)e="<remove></remove>"+e;else{const m=Ce(e,/^[\r\n\t ]+/);n=m&&m[0]}$==="application/xhtml+xml"&&z===C&&(e='<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>'+e+"</body></html>");const f=g?g.createHTML(e):e;if(z===C)try{t=new Ot().parseFromString(f,$)}catch{}if(!t||!t.documentElement){t=pe.createDocument(z,"template",null);try{t.documentElement.innerHTML=De?X:f}catch{}}const _=t.body||t.documentElement;return e&&n&&_.insertBefore(l.createTextNode(n),_.childNodes[0]||null),z===C?Ct.call(t,x?"html":"body")[0]:x?t.documentElement:_},tt=function(e){return Nt.call(e.ownerDocument||e,e,B.SHOW_ELEMENT|B.SHOW_COMMENT|B.SHOW_TEXT|B.SHOW_PROCESSING_INSTRUCTION|B.SHOW_CDATA_SECTION,null)},be=function(e){return e instanceof Rt&&(typeof e.nodeName!="string"||typeof e.textContent!="string"||typeof e.removeChild!="function"||!(e.attributes instanceof St)||typeof e.removeAttribute!="function"||typeof e.setAttribute!="function"||typeof e.namespaceURI!="string"||typeof e.insertBefore!="function"||typeof e.hasChildNodes!="function")},nt=function(e){return typeof me=="function"&&e instanceof me};function M(i,e,t){ce(i,n=>{n.call(o,e,t,G)})}const ot=function(e){let t=null;if(M(A.beforeSanitizeElements,e,null),be(e))return N(e),!0;const n=p(e.nodeName);if(M(A.uponSanitizeElement,e,{tagName:n,allowedTags:T}),ne&&e.hasChildNodes()&&!nt(e.firstElementChild)&&h(/<[/\w!]/g,e.innerHTML)&&h(/<[/\w!]/g,e.textContent)||e.nodeType===Q.progressingInstruction||ne&&e.nodeType===Q.comment&&h(/<[/\w]/g,e.data))return N(e),!0;if(!(k.tagCheck instanceof Function&&k.tagCheck(n))&&(!T[n]||j[n])){if(!j[n]&&at(n)&&(u.tagNameCheck instanceof RegExp&&h(u.tagNameCheck,n)||u.tagNameCheck instanceof Function&&u.tagNameCheck(n)))return!1;if(Se&&!b[n]){const f=te(e)||e.parentNode,_=bt(e)||e.childNodes;if(_&&f){const m=_.length;for(let D=m-1;D>=0;--D){const w=Dt(_[D],!0);w.__removalCount=(e.__removalCount||0)+1,f.insertBefore(w,yt(e))}}}return N(e),!0}return e instanceof Fe&&!Wt(e)||(n==="noscript"||n==="noembed"||n==="noframes")&&h(/<\/no(script|embed|frames)/i,e.innerHTML)?(N(e),!0):(U&&e.nodeType===Q.text&&(t=e.textContent,ce([Te,de,Ee],f=>{t=K(t,f," ")}),e.textContent!==t&&(q(o.removed,{element:e.cloneNode()}),e.textContent=t)),M(A.afterSanitizeElements,e,null),!1)},it=function(e,t,n){if(je&&(t==="id"||t==="name")&&(n in l||n in Gt))return!1;if(!(ge&&!_e[t]&&h(wt,t))){if(!(Be&&h(xt,t))){if(!(k.attributeCheck instanceof Function&&k.attributeCheck(t,e))){if(!d[t]||_e[t]){if(!(at(e)&&(u.tagNameCheck instanceof RegExp&&h(u.tagNameCheck,e)||u.tagNameCheck instanceof Function&&u.tagNameCheck(e))&&(u.attributeNameCheck instanceof RegExp&&h(u.attributeNameCheck,t)||u.attributeNameCheck instanceof Function&&u.attributeNameCheck(t,e))||t==="is"&&u.allowCustomizedBuiltInElements&&(u.tagNameCheck instanceof RegExp&&h(u.tagNameCheck,n)||u.tagNameCheck instanceof Function&&u.tagNameCheck(n))))return!1}else if(!Oe[t]){if(!h(ze,K(n,He,""))){if(!((t==="src"||t==="xlink:href"||t==="href")&&e!=="script"&&qt(n,"data:")===0&&$e[e])){if(!(Ye&&!h(Pt,K(n,He,"")))){if(n)return!1}}}}}}}return!0},at=function(e){return e!=="annotation-xml"&&Ce(e,vt)},rt=function(e){M(A.beforeSanitizeAttributes,e,null);const{attributes:t}=e;if(!t||be(e))return;const n={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:d,forceKeepAttr:void 0};let f=t.length;for(;f--;){const _=t[f],{name:m,namespaceURI:D,value:w}=_,W=p(m),Ne=w;let E=m==="value"?Ne:Kt(Ne);if(n.attrName=W,n.attrValue=E,n.keepAttr=!0,n.forceKeepAttr=void 0,M(A.uponSanitizeAttribute,e,n),E=n.attrValue,Ve&&(W==="id"||W==="name")&&(P(m,e),E=kt+E),ne&&h(/((--!?|])>)|<\/(style|title|textarea)/i,E)){P(m,e);continue}if(W==="attributename"&&Ce(E,"href")){P(m,e);continue}if(n.forceKeepAttr)continue;if(!n.keepAttr){P(m,e);continue}if(!Xe&&h(/\/>/i,E)){P(m,e);continue}U&&ce([Te,de,Ee],lt=>{E=K(E,lt," ")});const st=p(e.nodeName);if(!it(st,W,E)){P(m,e);continue}if(g&&typeof ee=="object"&&typeof ee.getAttributeType=="function"&&!D)switch(ee.getAttributeType(st,W)){case"TrustedHTML":{E=g.createHTML(E);break}case"TrustedScriptURL":{E=g.createScriptURL(E);break}}if(E!==Ne)try{D?e.setAttributeNS(D,m,E):e.setAttribute(m,E),be(e)?N(e):ft(o.removed)}catch{P(m,e)}}M(A.afterSanitizeAttributes,e,null)},Bt=function i(e){let t=null;const n=tt(e);for(M(A.beforeSanitizeShadowDOM,e,null);t=n.nextNode();)M(A.uponSanitizeShadowNode,t,null),ot(t),rt(t),t.content instanceof O&&i(t.content);M(A.afterSanitizeShadowDOM,e,null)};return o.sanitize=function(i){let e=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},t=null,n=null,f=null,_=null;if(De=!i,De&&(i="<!-->"),typeof i!="string"&&!nt(i))if(typeof i.toString=="function"){if(i=i.toString(),typeof i!="string")throw Z("dirty is not a string, aborting")}else throw Z("toString is not a function");if(!o.isSupported)return i;if(Ae||ye(e),o.removed=[],typeof i=="string"&&(V=!1),V){if(i.nodeName){const w=p(i.nodeName);if(!T[w]||j[w])throw Z("root node is forbidden and cannot be sanitized in-place")}}else if(i instanceof me)t=et("<!---->"),n=t.ownerDocument.importNode(i,!0),n.nodeType===Q.element&&n.nodeName==="BODY"||n.nodeName==="HTML"?t=n:t.appendChild(n);else{if(!F&&!U&&!x&&i.indexOf("<")===-1)return g&&ie?g.createHTML(i):i;if(t=et(i),!t)return F?null:ie?X:""}t&&he&&N(t.firstChild);const m=tt(V?i:t);for(;f=m.nextNode();)ot(f),rt(f),f.content instanceof O&&Bt(f.content);if(V)return i;if(F){if(oe)for(_=It.call(t.ownerDocument);t.firstChild;)_.appendChild(t.firstChild);else _=t;return(d.shadowroot||d.shadowrootmode)&&(_=Mt.call(a,_,!0)),_}let D=x?t.outerHTML:t.innerHTML;return x&&T["!doctype"]&&t.ownerDocument&&t.ownerDocument.doctype&&t.ownerDocument.doctype.name&&h(At,t.ownerDocument.doctype.name)&&(D="<!DOCTYPE "+t.ownerDocument.doctype.name+`>
|
|
2
|
+
`+D),U&&ce([Te,de,Ee],w=>{D=K(D,w," ")}),g&&ie?g.createHTML(D):D},o.setConfig=function(){let i=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};ye(i),Ae=!0},o.clearConfig=function(){G=null,Ae=!1},o.isValidAttribute=function(i,e,t){G||ye({});const n=p(i),f=p(e);return it(n,f,t)},o.addHook=function(i,e){typeof e=="function"&&q(A[i],e)},o.removeHook=function(i,e){if(e!==void 0){const t=Vt(A[i],e);return t===-1?void 0:$t(A[i],t,1)[0]}return ft(A[i])},o.removeHooks=function(i){A[i]=[]},o.removeAllHooks=function(){A=Et()},o}var mn=ht();export{mn as default};
|
package/dist/index.html
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
}
|
|
9
9
|
</style>
|
|
10
10
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-CeWB3Frt.js"></script>
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="root"></div>
|
package/index.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ declare module 'polotno-node' {
|
|
|
18
18
|
mimeType?: string;
|
|
19
19
|
pageId?: string;
|
|
20
20
|
onProgress?: (progress: number) => void;
|
|
21
|
+
/** Path to save CPU profile (.cpuprofile) - loadable in Chrome DevTools */
|
|
22
|
+
profilePath?: string;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export interface PDFRenderOptions extends RenderOptions {
|
|
@@ -28,6 +30,12 @@ declare module 'polotno-node' {
|
|
|
28
30
|
cropMarkSize?: number;
|
|
29
31
|
}
|
|
30
32
|
|
|
33
|
+
export interface VideoRenderOptions extends RenderOptions {
|
|
34
|
+
fps?: number;
|
|
35
|
+
pixelRatio?: number;
|
|
36
|
+
onProgress?: (progress: number, frameTime?: number) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
// JSON Structure for Rendering
|
|
32
40
|
export interface RenderJSON {
|
|
33
41
|
[key: string]: any;
|
|
@@ -85,6 +93,14 @@ declare module 'polotno-node' {
|
|
|
85
93
|
json: RenderJSON,
|
|
86
94
|
options?: RenderOptions
|
|
87
95
|
) => Promise<string>;
|
|
96
|
+
jsonToVideoDataURL: (
|
|
97
|
+
json: RenderJSON,
|
|
98
|
+
options?: VideoRenderOptions
|
|
99
|
+
) => Promise<string>;
|
|
100
|
+
jsonToVideoBase64: (
|
|
101
|
+
json: RenderJSON,
|
|
102
|
+
options?: VideoRenderOptions
|
|
103
|
+
) => Promise<string>;
|
|
88
104
|
createPage: () => Promise<Page>;
|
|
89
105
|
}
|
|
90
106
|
|
package/instance.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
2
3
|
const DEFAULT_CLIENT = `file:${path.join(__dirname, 'dist', 'index.html')}`;
|
|
3
4
|
|
|
4
5
|
module.exports.createPage = async (browser, url, requestInterceptor) => {
|
|
@@ -105,6 +106,57 @@ module.exports.createInstance = async ({
|
|
|
105
106
|
? null
|
|
106
107
|
: await module.exports.createPage(browser, visitPage, requestInterceptor);
|
|
107
108
|
|
|
109
|
+
async function ensureAssetErrorHelpers(page) {
|
|
110
|
+
await page.evaluate(() => {
|
|
111
|
+
// Define helpers once per page. They unify asset-loading error handling
|
|
112
|
+
// across all exports (dataURL/image/pdf/video).
|
|
113
|
+
if (!window.__polotnoConsumeAssetError) {
|
|
114
|
+
window.__polotnoConsumeAssetError = (attrs) => {
|
|
115
|
+
const error = window._polotnoError;
|
|
116
|
+
if (!error) return null;
|
|
117
|
+
|
|
118
|
+
// Clear immediately to avoid double-reporting.
|
|
119
|
+
window._polotnoError = null;
|
|
120
|
+
|
|
121
|
+
const message = String(error);
|
|
122
|
+
const isFontError = message.indexOf('Timeout for loading font') >= 0;
|
|
123
|
+
const skipFontError = isFontError && attrs && attrs.skipFontError;
|
|
124
|
+
|
|
125
|
+
const isImageError = message.indexOf('image ') >= 0;
|
|
126
|
+
const skipImageError = isImageError && attrs && attrs.skipImageError;
|
|
127
|
+
|
|
128
|
+
if (skipFontError || skipImageError) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return message;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (!window.__polotnoThrowAssetErrorIfAny) {
|
|
136
|
+
window.__polotnoThrowAssetErrorIfAny = (attrs) => {
|
|
137
|
+
const message = window.__polotnoConsumeAssetError(attrs);
|
|
138
|
+
if (message) {
|
|
139
|
+
throw new Error('Asset loading error: ' + message);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
async function consumeAssetLoadingErrorMessage(page, attrs) {
|
|
147
|
+
try {
|
|
148
|
+
return await page.evaluate((attrs) => {
|
|
149
|
+
if (window.__polotnoConsumeAssetError) {
|
|
150
|
+
return window.__polotnoConsumeAssetError(attrs);
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}, attrs);
|
|
154
|
+
} catch (e) {
|
|
155
|
+
// If the page is already crashed/unavailable, we can't inspect the error.
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
108
160
|
const run = async (func, ...args) => {
|
|
109
161
|
const page = useParallelPages
|
|
110
162
|
? await module.exports.createPage(browser, visitPage, requestInterceptor)
|
|
@@ -118,6 +170,16 @@ module.exports.createInstance = async ({
|
|
|
118
170
|
|
|
119
171
|
busyPages.push(page);
|
|
120
172
|
|
|
173
|
+
// Setup profiling if profilePath is provided
|
|
174
|
+
let cdpSession = null;
|
|
175
|
+
const profilePath = args[1]?.profilePath;
|
|
176
|
+
console.log('profilePath', profilePath);
|
|
177
|
+
if (profilePath) {
|
|
178
|
+
cdpSession = await page.target().createCDPSession();
|
|
179
|
+
await cdpSession.send('Profiler.enable');
|
|
180
|
+
await cdpSession.send('Profiler.start');
|
|
181
|
+
}
|
|
182
|
+
|
|
121
183
|
try {
|
|
122
184
|
if (args[1]?.assetLoadTimeout) {
|
|
123
185
|
await page.evaluate((timeout) => {
|
|
@@ -176,8 +238,8 @@ module.exports.createInstance = async ({
|
|
|
176
238
|
}
|
|
177
239
|
if (args[1]?.onProgress) {
|
|
178
240
|
const originalProgress = args[1].onProgress;
|
|
179
|
-
await page.exposeFunction('onProgress', async (progress) => {
|
|
180
|
-
originalProgress(progress);
|
|
241
|
+
await page.exposeFunction('onProgress', async (progress, frameTime) => {
|
|
242
|
+
originalProgress(progress, frameTime);
|
|
181
243
|
});
|
|
182
244
|
}
|
|
183
245
|
if (args[1]?.textOverflow) {
|
|
@@ -202,23 +264,22 @@ module.exports.createInstance = async ({
|
|
|
202
264
|
);
|
|
203
265
|
}
|
|
204
266
|
});
|
|
267
|
+
await ensureAssetErrorHelpers(page);
|
|
205
268
|
const result = await page.evaluate(func, ...args);
|
|
206
|
-
const error = await page.evaluate(() => window._polotnoError);
|
|
207
|
-
if (error) {
|
|
208
|
-
// clear error
|
|
209
|
-
await page.evaluate(() => {
|
|
210
|
-
window._polotnoError = null;
|
|
211
|
-
});
|
|
212
|
-
const message = error.toString();
|
|
213
|
-
const isFontError = message.indexOf('Timeout for loading font') >= 0;
|
|
214
|
-
const skipError = isFontError && args[1]?.skipFontError;
|
|
215
269
|
|
|
216
|
-
|
|
217
|
-
|
|
270
|
+
// Stop profiler and save profile if enabled
|
|
271
|
+
if (cdpSession && profilePath) {
|
|
272
|
+
const { profile } = await cdpSession.send('Profiler.stop');
|
|
273
|
+
fs.writeFileSync(profilePath, JSON.stringify(profile));
|
|
274
|
+
console.log(`CPU profile saved to: ${profilePath}`);
|
|
275
|
+
}
|
|
218
276
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
277
|
+
const assetErrorMessage = await consumeAssetLoadingErrorMessage(
|
|
278
|
+
page,
|
|
279
|
+
args[1]
|
|
280
|
+
);
|
|
281
|
+
if (assetErrorMessage) {
|
|
282
|
+
throw new Error('Asset loading error: ' + assetErrorMessage);
|
|
222
283
|
}
|
|
223
284
|
// remove busy page
|
|
224
285
|
busyPages.splice(busyPages.indexOf(page), 1);
|
|
@@ -227,11 +288,32 @@ module.exports.createInstance = async ({
|
|
|
227
288
|
}
|
|
228
289
|
return result;
|
|
229
290
|
} catch (e) {
|
|
291
|
+
// Stop profiler and save profile even on error
|
|
292
|
+
if (cdpSession && profilePath) {
|
|
293
|
+
console.log('saving profile');
|
|
294
|
+
try {
|
|
295
|
+
const { profile } = await cdpSession.send('Profiler.stop');
|
|
296
|
+
fs.writeFileSync(profilePath, JSON.stringify(profile));
|
|
297
|
+
console.log(`CPU profile saved to: ${profilePath}`);
|
|
298
|
+
} catch (profileError) {
|
|
299
|
+
console.error('Failed to save profile:', profileError.message);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// If `page.evaluate()` failed (e.g. thrown during onProgress), still prefer
|
|
304
|
+
// a captured Polotno asset-loading error when available.
|
|
305
|
+
const assetErrorMessage = await consumeAssetLoadingErrorMessage(
|
|
306
|
+
page,
|
|
307
|
+
args[1]
|
|
308
|
+
);
|
|
230
309
|
// remove busy page
|
|
231
310
|
busyPages.splice(busyPages.indexOf(page), 1);
|
|
232
311
|
if (useParallelPages) {
|
|
233
312
|
await page.close();
|
|
234
313
|
}
|
|
314
|
+
if (assetErrorMessage) {
|
|
315
|
+
throw new Error('Asset loading error: ' + assetErrorMessage);
|
|
316
|
+
}
|
|
235
317
|
throw e;
|
|
236
318
|
}
|
|
237
319
|
};
|
|
@@ -299,6 +381,77 @@ module.exports.createInstance = async ({
|
|
|
299
381
|
return blob;
|
|
300
382
|
};
|
|
301
383
|
|
|
384
|
+
const jsonToVideoDataURL = async (json, attrs) => {
|
|
385
|
+
return await run(
|
|
386
|
+
async (json, attrs) => {
|
|
387
|
+
const pixelRatio = attrs.pixelRatio || 1;
|
|
388
|
+
store.loadJSON(json);
|
|
389
|
+
await store.waitLoading();
|
|
390
|
+
window.__polotnoThrowAssetErrorIfAny(attrs);
|
|
391
|
+
|
|
392
|
+
// keep store internals consistent with image/pdf exports
|
|
393
|
+
store.setElementsPixelRatio(pixelRatio);
|
|
394
|
+
|
|
395
|
+
// loop through all pages and wait for loading for all layout calculations
|
|
396
|
+
// (this helps stabilize text/layout across multi-page designs)
|
|
397
|
+
for (const page of store.pages) {
|
|
398
|
+
store.selectPage(page.id);
|
|
399
|
+
await store.waitLoading();
|
|
400
|
+
window.__polotnoThrowAssetErrorIfAny(attrs);
|
|
401
|
+
}
|
|
402
|
+
if (store.pages.length > 0) {
|
|
403
|
+
store.selectPage(store.pages[0].id);
|
|
404
|
+
await store.waitLoading();
|
|
405
|
+
window.__polotnoThrowAssetErrorIfAny(attrs);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// For video export, we always use 'resize' text overflow mode
|
|
409
|
+
// to ensure text fits properly in animations. User preferences are ignored for now.
|
|
410
|
+
window.config.setTextOverflow('resize');
|
|
411
|
+
|
|
412
|
+
if (!window.loadVideoExportModule) {
|
|
413
|
+
throw new Error(
|
|
414
|
+
'Video export module loader is not defined in the client. Expected window.loadVideoExportModule().'
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const { storeToVideo } = await window.loadVideoExportModule();
|
|
419
|
+
|
|
420
|
+
// Use exposed progress callback if available
|
|
421
|
+
const progressCallback = window.onProgress
|
|
422
|
+
? (progress, frameTime) => {
|
|
423
|
+
// Check for asset-loading errors during render
|
|
424
|
+
window.__polotnoThrowAssetErrorIfAny(attrs);
|
|
425
|
+
return window.onProgress(progress, frameTime);
|
|
426
|
+
}
|
|
427
|
+
: undefined;
|
|
428
|
+
|
|
429
|
+
const videoBlob = await storeToVideo({
|
|
430
|
+
store,
|
|
431
|
+
fps: attrs.fps,
|
|
432
|
+
pixelRatio,
|
|
433
|
+
onProgress: progressCallback,
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Convert Blob to data URL
|
|
437
|
+
const dataUrl = await new Promise((resolve, reject) => {
|
|
438
|
+
const reader = new FileReader();
|
|
439
|
+
reader.onloadend = () => resolve(reader.result);
|
|
440
|
+
reader.onerror = reject;
|
|
441
|
+
reader.readAsDataURL(videoBlob);
|
|
442
|
+
});
|
|
443
|
+
return dataUrl;
|
|
444
|
+
},
|
|
445
|
+
json,
|
|
446
|
+
attrs || {}
|
|
447
|
+
);
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
const jsonToVideoBase64 = async (json, attrs) => {
|
|
451
|
+
const url = await jsonToVideoDataURL(json, attrs);
|
|
452
|
+
return url.split('base64,')[1];
|
|
453
|
+
};
|
|
454
|
+
|
|
302
455
|
const instance = {
|
|
303
456
|
close: async () => {
|
|
304
457
|
createdInstances.splice(createdInstances.indexOf(instance), 1);
|
|
@@ -314,6 +467,8 @@ module.exports.createInstance = async ({
|
|
|
314
467
|
jsonToBlob,
|
|
315
468
|
jsonToGIFDataURL,
|
|
316
469
|
jsonToGIFBase64,
|
|
470
|
+
jsonToVideoDataURL,
|
|
471
|
+
jsonToVideoBase64,
|
|
317
472
|
createPage: async () =>
|
|
318
473
|
await module.exports.createPage(browser, visitPage, requestInterceptor),
|
|
319
474
|
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polotno-node",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.14.0",
|
|
4
4
|
"description": "Polotno workflow from NodeJS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"test": "
|
|
8
|
+
"test": "npm run build && vitest run test/static/static.test.mjs",
|
|
9
|
+
"test:video": "npm run build && vitest run test/video/video.test.mjs",
|
|
10
|
+
"test:all": "npm run build && vitest run test/static/static.test.mjs test/video/video.test.mjs",
|
|
9
11
|
"build": "rm -rf ./dist && npx vite build ./client/ --base=./ --outDir ../dist",
|
|
10
12
|
"dev": "vite ./client.html"
|
|
11
13
|
},
|
|
@@ -19,7 +21,7 @@
|
|
|
19
21
|
],
|
|
20
22
|
"browserslist": "> 0.5%, last 2 versions, not dead",
|
|
21
23
|
"devDependencies": {
|
|
22
|
-
"
|
|
24
|
+
"@polotno/video-export": "^0.0.4",
|
|
23
25
|
"axios": "^1.13.2",
|
|
24
26
|
"dotenv": "^17.2.3",
|
|
25
27
|
"fluent-ffmpeg": "^2.1.3",
|
|
@@ -29,15 +31,16 @@
|
|
|
29
31
|
"polotno": "2.34.0",
|
|
30
32
|
"react": "^18.3.1",
|
|
31
33
|
"react-dom": "^18.3.1",
|
|
32
|
-
"vite": "^7.
|
|
34
|
+
"vite": "^7.3.0",
|
|
35
|
+
"vitest": "^4.0.16",
|
|
36
|
+
"web-audio-api": "^0.2.2"
|
|
33
37
|
},
|
|
34
38
|
"author": "Anton Lavrenov",
|
|
35
39
|
"license": "MIT",
|
|
36
40
|
"dependencies": {
|
|
37
41
|
"@sparticuz/chromium": "^143.0.0",
|
|
38
|
-
"
|
|
39
|
-
"puppeteer": "24.
|
|
40
|
-
"puppeteer-core": "24.32.1",
|
|
42
|
+
"puppeteer": "24.33.0",
|
|
43
|
+
"puppeteer-core": "24.33.0",
|
|
41
44
|
"tmp": "^0.2.5"
|
|
42
45
|
},
|
|
43
46
|
"bugs": {
|
package/video-parallel.js
CHANGED
|
@@ -265,7 +265,7 @@ module.exports.jsonToVideo = async function jsonToVideo(
|
|
|
265
265
|
const skipImageError = isImageError && attrs.skipImageError;
|
|
266
266
|
|
|
267
267
|
if (!skipError && !skipImageError) {
|
|
268
|
-
throw new Error(error);
|
|
268
|
+
throw new Error('Asset loading error: ' + error);
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
// TODO: add error handling!!!!
|