polotno-node 2.13.1 → 2.14.1

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.
@@ -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-vFr48NCL.js"></script>
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,15 @@ 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
+ if (profilePath) {
177
+ cdpSession = await page.target().createCDPSession();
178
+ await cdpSession.send('Profiler.enable');
179
+ await cdpSession.send('Profiler.start');
180
+ }
181
+
121
182
  try {
122
183
  if (args[1]?.assetLoadTimeout) {
123
184
  await page.evaluate((timeout) => {
@@ -176,8 +237,8 @@ module.exports.createInstance = async ({
176
237
  }
177
238
  if (args[1]?.onProgress) {
178
239
  const originalProgress = args[1].onProgress;
179
- await page.exposeFunction('onProgress', async (progress) => {
180
- originalProgress(progress);
240
+ await page.exposeFunction('onProgress', async (progress, frameTime) => {
241
+ originalProgress(progress, frameTime);
181
242
  });
182
243
  }
183
244
  if (args[1]?.textOverflow) {
@@ -202,23 +263,22 @@ module.exports.createInstance = async ({
202
263
  );
203
264
  }
204
265
  });
266
+ await ensureAssetErrorHelpers(page);
205
267
  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
268
 
216
- const isImageError = message.indexOf('image ') >= 0;
217
- const skipImageError = isImageError && args[1]?.skipImageError;
269
+ // Stop profiler and save profile if enabled
270
+ if (cdpSession && profilePath) {
271
+ const { profile } = await cdpSession.send('Profiler.stop');
272
+ fs.writeFileSync(profilePath, JSON.stringify(profile));
273
+ console.log(`CPU profile saved to: ${profilePath}`);
274
+ }
218
275
 
219
- if (!skipError && !skipImageError) {
220
- throw new Error('Asset loading error: ' + error);
221
- }
276
+ const assetErrorMessage = await consumeAssetLoadingErrorMessage(
277
+ page,
278
+ args[1]
279
+ );
280
+ if (assetErrorMessage) {
281
+ throw new Error('Asset loading error: ' + assetErrorMessage);
222
282
  }
223
283
  // remove busy page
224
284
  busyPages.splice(busyPages.indexOf(page), 1);
@@ -227,11 +287,32 @@ module.exports.createInstance = async ({
227
287
  }
228
288
  return result;
229
289
  } catch (e) {
290
+ // Stop profiler and save profile even on error
291
+ if (cdpSession && profilePath) {
292
+ console.log('saving profile');
293
+ try {
294
+ const { profile } = await cdpSession.send('Profiler.stop');
295
+ fs.writeFileSync(profilePath, JSON.stringify(profile));
296
+ console.log(`CPU profile saved to: ${profilePath}`);
297
+ } catch (profileError) {
298
+ console.error('Failed to save profile:', profileError.message);
299
+ }
300
+ }
301
+
302
+ // If `page.evaluate()` failed (e.g. thrown during onProgress), still prefer
303
+ // a captured Polotno asset-loading error when available.
304
+ const assetErrorMessage = await consumeAssetLoadingErrorMessage(
305
+ page,
306
+ args[1]
307
+ );
230
308
  // remove busy page
231
309
  busyPages.splice(busyPages.indexOf(page), 1);
232
310
  if (useParallelPages) {
233
311
  await page.close();
234
312
  }
313
+ if (assetErrorMessage) {
314
+ throw new Error('Asset loading error: ' + assetErrorMessage);
315
+ }
235
316
  throw e;
236
317
  }
237
318
  };
@@ -299,6 +380,77 @@ module.exports.createInstance = async ({
299
380
  return blob;
300
381
  };
301
382
 
383
+ const jsonToVideoDataURL = async (json, attrs) => {
384
+ return await run(
385
+ async (json, attrs) => {
386
+ const pixelRatio = attrs.pixelRatio || 1;
387
+ store.loadJSON(json);
388
+ await store.waitLoading();
389
+ window.__polotnoThrowAssetErrorIfAny(attrs);
390
+
391
+ // keep store internals consistent with image/pdf exports
392
+ store.setElementsPixelRatio(pixelRatio);
393
+
394
+ // loop through all pages and wait for loading for all layout calculations
395
+ // (this helps stabilize text/layout across multi-page designs)
396
+ for (const page of store.pages) {
397
+ store.selectPage(page.id);
398
+ await store.waitLoading();
399
+ window.__polotnoThrowAssetErrorIfAny(attrs);
400
+ }
401
+ if (store.pages.length > 0) {
402
+ store.selectPage(store.pages[0].id);
403
+ await store.waitLoading();
404
+ window.__polotnoThrowAssetErrorIfAny(attrs);
405
+ }
406
+
407
+ // For video export, we always use 'resize' text overflow mode
408
+ // to ensure text fits properly in animations. User preferences are ignored for now.
409
+ window.config.setTextOverflow('resize');
410
+
411
+ if (!window.loadVideoExportModule) {
412
+ throw new Error(
413
+ 'Video export module loader is not defined in the client. Expected window.loadVideoExportModule().'
414
+ );
415
+ }
416
+
417
+ const { storeToVideo } = await window.loadVideoExportModule();
418
+
419
+ // Use exposed progress callback if available
420
+ const progressCallback = window.onProgress
421
+ ? (progress, frameTime) => {
422
+ // Check for asset-loading errors during render
423
+ window.__polotnoThrowAssetErrorIfAny(attrs);
424
+ return window.onProgress(progress, frameTime);
425
+ }
426
+ : undefined;
427
+
428
+ const videoBlob = await storeToVideo({
429
+ store,
430
+ fps: attrs.fps,
431
+ pixelRatio,
432
+ onProgress: progressCallback,
433
+ });
434
+
435
+ // Convert Blob to data URL
436
+ const dataUrl = await new Promise((resolve, reject) => {
437
+ const reader = new FileReader();
438
+ reader.onloadend = () => resolve(reader.result);
439
+ reader.onerror = reject;
440
+ reader.readAsDataURL(videoBlob);
441
+ });
442
+ return dataUrl;
443
+ },
444
+ json,
445
+ attrs || {}
446
+ );
447
+ };
448
+
449
+ const jsonToVideoBase64 = async (json, attrs) => {
450
+ const url = await jsonToVideoDataURL(json, attrs);
451
+ return url.split('base64,')[1];
452
+ };
453
+
302
454
  const instance = {
303
455
  close: async () => {
304
456
  createdInstances.splice(createdInstances.indexOf(instance), 1);
@@ -314,6 +466,8 @@ module.exports.createInstance = async ({
314
466
  jsonToBlob,
315
467
  jsonToGIFDataURL,
316
468
  jsonToGIFBase64,
469
+ jsonToVideoDataURL,
470
+ jsonToVideoBase64,
317
471
  createPage: async () =>
318
472
  await module.exports.createPage(browser, visitPage, requestInterceptor),
319
473
  };
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "polotno-node",
3
- "version": "2.13.1",
3
+ "version": "2.14.1",
4
4
  "description": "Polotno workflow from NodeJS",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
7
7
  "scripts": {
8
- "test": "ava --timeout=30s --concurrency=2",
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
- "ava": "^6.4.1",
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,14 +31,16 @@
29
31
  "polotno": "2.34.0",
30
32
  "react": "^18.3.1",
31
33
  "react-dom": "^18.3.1",
32
- "vite": "^7.2.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
- "puppeteer": "24.32.1",
39
- "puppeteer-core": "24.32.1",
42
+ "puppeteer": "24.33.0",
43
+ "puppeteer-core": "24.33.0",
40
44
  "tmp": "^0.2.5"
41
45
  },
42
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!!!!