bug-reporterjs-lib
Version:
A lightweight and framework-agnostic JavaScript bug reporter with screenshot capture, error logging, and Axios error tracking. Designed to work seamlessly in Vue, React, and plain JavaScript projects.
214 lines (187 loc) • 28.1 kB
JavaScript
(function(y,_){typeof exports=="object"&&typeof module<"u"?_(exports):typeof define=="function"&&define.amd?define(["exports"],_):(y=typeof globalThis<"u"?globalThis:y||self,_(y.BugReporter={}))})(this,function(y){"use strict";async function _(){const e=await Promise.resolve().then(()=>Qe),t=document.body;return await e.toJpeg(t,{quality:1,pixelRatio:1,skipAutoScale:!0,width:t.clientWidth,height:t.clientHeight})}const R="CLIENT_ERROR_LOGS",v="LAST_ERROR_REQUEST",Z="http://p-c-ers.asakabank.com/report",ee={title:"Report a Bug",leave_comment:"Leave a comment",send:"Send",noClientErrors:"No client errors",noNetworkErrors:"No network errors",report_success_sent:"Message successfully sent",report_failed:"Failed to send message, please try again later",jira_creds_required:"JIRA credentials are required",username:"Username",password:"Password",continue:"Continue",enter_jira_creds:"Enter JIRA Credentials"},$={title:"Сообщить об ошибке",leave_comment:"Оставить комментарий",send:"Отправить",noClientErrors:"Нет клиентских ошибок",noNetworkErrors:"Нет сетевых ошибок",report_success_sent:"Cообщение успешно отправлено",report_failed:"Не удалось отправить сообщение, пожалуйста, попробуйте позже",jira_creds_required:"JIRA учетные данные обязательны",username:"Имя пользователя",password:"Пароль",continue:"Продолжить",enter_jira_creds:"Введите учетные данные JIRA"},te={title:"Xatolik haqida xabar berish",leave_comment:"Izoh qoldirish",send:"Jo'natish",noClientErrors:"Mijoz xatoliklari yo'q",noNetworkErrors:"Tarmoq xatoliklari yo'q",report_success_sent:"Xabar muvaffaqiyatli yuborildi",report_failed:"Xabar yuborishda xato, iltimos keyinroq qaytadan urinib ko'ring",jira_creds_required:"JIRA foydalanuvchi ma'lumotlari talab qilinadi",username:"Foydalanuvchi nomi",password:"Parol",continue:"Davom etish",enter_jira_creds:"JIRA foydalanuvchi ma'lumotlarini kiriting"},re={title:"Хатолик ҳақида хабар бериш",leave_comment:"Изоҳ қолдириш",send:"Жўнатиш",noClientErrors:"Мижоз хатоликлари йўқ",noNetworkErrors:"Тармоқ хатоликлари йўқ",report_success_sent:"Хабар муваффақиятли юборилди",report_failed:"Хабарни юборишда хатолик юз берди, илтимос, кейинроқ қайта уриниб кўринг",jira_creds_required:"JIRA фойдаланувчи маълумотлари талаб қилинади",username:"Фойдаланувчи номи",password:"Пароль",continue:"Давом этиш",enter_jira_creds:"JIRA фойдаланувчи маълумотларини киритинг"},A=e=>{let t={};switch(e){case"uz":t=re;break;case"o'z":t=te;break;case"en":t=ee;break;case"ru":t=$;default:t=$}return r=>t[r]||r};function ne(e,t,r,n){const s=A(r),o=document.createElement("div");document.body.style.overflow="hidden",o.id="bug-modal",o.innerHTML=`
<style>
#bug-modal {
position: fixed;
top: 0; left: 0;
width: 100vw;
height: 100vh;
background: rgba(0,0,0,0.6);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
#bug-modal * {
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
}
#bug-modal .modal-content {
background: #fff;
width: 80%;
max-width: 95vw;
padding: 30px;
border-radius: 30px;
box-shadow: 0px 2px 6px 0px #0000001F, 0px 0px 2px 0px #0000000F, 0px 4px 10px 0px #00000008;
font-family: sans-serif;
display: flex;
flex-direction: column;
gap:30px;
animation: fadeIn 0.2s ease-in-out;
}
#bug-modal form {
display: flex;
flex-direction: column;
gap:16px;
}
#bug-modal .modal-header {
display: flex;
justify-content: space-between;
align-items: center;
}
#bug-modal .modal-header span{
cursor: pointer;
font-size: 24px;
color: #333;
transition: all 0.2s;
line-height: 1;
}
#bug-modal h2 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #333;
}
#bug-modal h3 {
margin: 0;
font-size: 20px;
color: #065cb9;
text-align: center;
}
#bug-modal img {
width: 100%;
max-height: 400px;
object-fit: cover;
object-position: top;
border: 1px solid #CED4DA;
}
#bug-modal textarea {
padding: 15px;
font-size: 14px;
border: 1px solid #CED4DA;
border-radius: 30px;
outline: none;
resize: none;
}
#bug-modal input {
padding: 15px;
font-size: 14px;
border: 1px solid #CED4DA;
border-radius: 30px;
outline: none;
resize: none;
}
#bug-modal textarea:hover,#bug-modal textarea:focus {
border-color: #232323;
}
#bug-modal .button-container {
display: flex;
justify-content: center;
}
#bug-modal button {
padding: 12px 24px;
height: 54px;
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
background: #333333;
color: white;
border: none;
border-radius: 30px;
gap: 10px;
cursor: pointer;
transition: all 0.2s;
min-width: 150px;
}
#bug-modal button:hover {
background: #232323;
box-shadow: 0px 5px 5px 0px #00000040;
}
#bug-modal button:disabled {
background: #E5E5E5;
cursor: not-allowed;
color: #6C757D;
}
#bug-modal .loader {
width: 24px;
height: 24px;
border-radius: 50%;
position: relative;
animation: rotate 1s linear infinite
}
#bug-modal .loader.hide {
display: none;
}
#bug-modal .jira-creds {
display: flex;
flex-direction: column;
gap:16px;
}
#bug-modal .loader::before {
content: "";
box-sizing: border-box;
position: absolute;
inset: 0px;
border-radius: 50%;
border: 3px solid #6C757D;
animation: prixClipFix 2s linear infinite ;
}
@keyframes rotate {
100% {transform: rotate(360deg)}
}
@keyframes prixClipFix {
0% {clip-path:polygon(50% 50%,0 0,0 0,0 0,0 0,0 0)}
25% {clip-path:polygon(50% 50%,0 0,100% 0,100% 0,100% 0,100% 0)}
50% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,100% 100%,100% 100%)}
75% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 100%)}
100% {clip-path:polygon(50% 50%,0 0,100% 0,100% 100%,0 100%,0 0)}
}
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
</style>
<div class="modal-content">
<div class="modal-header">
<h2>${s("title")}</h2>
<span id="close-modal">×</span>
</div>
<form id="bug-modal-form" class="report-form">
<img src="${e}" alt="Screenshot"/>
<input type="tel" pattern="^+998(9[0-9]|8[1-9]|7[1-9])[0-9]{7}$" placeholder="+998901234567" id="bug-phone" />
<textarea id="bug-comment" rows="3" placeholder="${s("leave_comment")}..."></textarea>
<div class="button-container">
<button ${n?"":'id="send-btn"'} type="submit">
${n?"":'<span id="bug-loader" class="loader hide"></span>'}
<span>${s(n?"continue":"send")}</span>
</button>
</div>
</form>
${n?`
<form id="bug-jira-creds-form" class="report-form" style="display:none;">
<h3>${s("enter_jira_creds")}</h3>
<div class="jira-creds">
<input type="text" id="bug-username" required placeholder="${s("username")}" />
<input type="password" id="bug-password" required placeholder="${s("password")}" />
</div>
<div class="button-container">
<button id="send-btn" type="submit">
<span id="bug-loader" class="loader hide"></span>
<span>${s("send")}</span>
</button>
</div>
</form>
`:""}
</div>
`,document.body.appendChild(o);const i=document.querySelectorAll(".report-form");let a=!1;const c=()=>{o.remove(),sessionStorage.removeItem(R),sessionStorage.removeItem(v),document.body.style.overflow="auto"};document.getElementById("close-modal")?.addEventListener("click",()=>{c()});const l=async()=>{const u=document.getElementById("send-btn"),f=document.getElementById("bug-loader"),x=document.getElementById("bug-comment")?.value,g=document.getElementById("bug-phone")?.value,E=document.getElementById("bug-username")?.value,S=document.getElementById("bug-password")?.value;if(console.log(E,S),n&&(!E||!S)){alert(s("jira_creds_required"));return}u?.setAttribute("disabled","true"),f?.classList.remove("hide"),await t({comment:x,phone:g,...n?{username:E,password:S}:{}}),u?.removeAttribute("disabled"),f?.classList.add("hide"),c()};i.forEach(u=>{u?.addEventListener("submit",async f=>{if(f.preventDefault(),console.log(a),n&&!a){a=!0;const x=document.getElementById("bug-jira-creds-form"),g=document.getElementById("bug-modal-form");x&&(x.style.display="flex"),g&&(g.style.display="none");return}console.log(1),l()})}),document.getElementById("bug-phone")?.addEventListener("input",u=>{let f=u.target?.value.replace(/[^\d+]/g,"");f.includes("+")&&(f="+"+f.replace(/\+/g,"")),f.length>13&&(f=f.slice(0,13)),u.target&&(u.target.value=f)})}class oe{project;isJiraCredsRequired;locale;constructor(t){this.project=t.project,this.isJiraCredsRequired=t.isJiraCredsRequired||!1,this.setupErrorListeners(),this.setupGlobalErrorListeners()}setupErrorListeners(){const t=window.fetch;window.fetch=async(...o)=>{try{const i=await t(...o);if(!i.ok||!i.status){const c=await i.clone().text();this.storeNetworkError({request_url:typeof o[0]=="string"?o[0]:o[0]instanceof Request?o[0].url:o[0]instanceof URL?o[0].toString():void 0,request_header:o[1]?.headers||{},request_status_code:i.status,response_data:(()=>{try{const l=JSON.parse(c);return typeof l=="object"&&l!==null?l:{message:c}}catch{return{message:c}}})()})}return i}catch(i){throw this.storeNetworkError({request_url:typeof o[0]=="string"?o[0]:o[0]instanceof Request?o[0].url:o[0]instanceof URL?o[0].toString():void 0,response_data:{message:i?.message||i.toString()}}),i}};const r=XMLHttpRequest.prototype.open,n=XMLHttpRequest.prototype.send,s=this;XMLHttpRequest.prototype.open=function(o,i){return this._bug_report_url=i,r.apply(this,arguments)},XMLHttpRequest.prototype.send=function(o){const i=this,a=l=>{if(l){if(typeof l=="string")try{return JSON.parse(l)}catch{return l}else if(l instanceof FormData){const d={};for(const[u,f]of l.entries())d[u]=f;return d}else if(l instanceof URLSearchParams){const d={};for(const[u,f]of l.entries())d[u]=f;return d}else{if(l instanceof Blob)return"[Blob]";if(typeof l=="object")return l}return String(l)}},c=()=>{const l=i.status;if(!(l>=200&&l<300)){let d;try{const u=JSON.parse(i.responseText);u&&typeof u=="object"&&!Array.isArray(u)?d=u:d=u?{message:u}:{message:"Unknown error"}}catch{d=i.responseText?{message:i.responseText}:{message:"Unknown error"}}try{const u={};i.getAllResponseHeaders().trim().split(/[\r\n]+/).forEach(x=>{const g=x.split(": "),E=g.shift(),S=g.join(": ");E&&(u[E]=S)}),s.storeNetworkError({request_url:i._bug_report_url,request_payload:a(o),request_header:u,request_status_code:l,response_data:d})}catch{s.storeNetworkError({request_url:i._bug_report_url,request_status_code:l,response_data:{message:i.responseText}})}}i.removeEventListener("loadend",c)};return i.addEventListener("loadend",c),n.call(i,o)}}isHttpError(t){const r=t?.message||t?.toString?.()||(typeof t=="string"?t:"");return["Load failed","fetch","Network Error","Request failed","Failed to fetch","status code","timeout","axios","net::ERR","Failed to load resource","A server with the specified hostname could not be found","Failed to fetch","ERR_CONNECTION_REFUSED","ERR_NAME_NOT_RESOLVED"].some(s=>r.includes(s))}setupGlobalErrorListeners(){window.onerror=(t,r,n,s,o)=>{this.isHttpError(o||t)||this.storeConsoleError({data:{message:o?.message||String(t),source:r,line:n,column:s}})},window.onunhandledrejection=t=>{const r=t?.reason;this.isHttpError(r)||this.storeConsoleError({data:{message:r?.message||r?.toString?.()||"Unhandled rejection"}})}}storeNetworkError(t){const r={request_status_code:t.request_status_code,request_url:t.request_url||"",location_url:window.location.href,request_header:t.request_header??{},request_payload:t.request_payload??{},response_data:t.response_data??{}};sessionStorage.setItem(v,JSON.stringify(r))}storeConsoleError(t){let r=JSON.parse(sessionStorage.getItem(R)||"[]");const n={location_url:window.location.href,console_error:t.data};sessionStorage.setItem(R,JSON.stringify([...r,n].slice(-10)))}async openModal({callback:t,locale:r}){this.locale=r;const n=await _();ne(n,s=>this.sendReport({image:n,...s},t),this.locale,this.isJiraCredsRequired)}collectData({comment:t,image:r,phone:n,password:s,username:o}){const i={project_name:this.project,user_agent:navigator.userAgent,image:r,location_url:window.location.href,request_header:{},request_payload:{},response_data:{},request_status_code:0,request_url:"",console_error:{data:[]},comment:t,phone:n,username:o,password:s},a=JSON.parse(sessionStorage.getItem(R)||"[]"),c=JSON.parse(sessionStorage.getItem(v)||"{}");return a.length>0&&(i.console_error={data:a.filter(l=>l.location_url===window.location.href).map(l=>l.console_error).filter(l=>l!==void 0)}),c.location_url===window.location.href&&(i.request_url=c.request_url,i.request_header=c.request_header,i.request_status_code=c.request_status_code,i.request_payload=c.request_payload,i.response_data=c.response_data),i}async sendReport(t,r){const n=A(this.locale),s=this.collectData(t);try{const o=await fetch(Z,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)}),i=await o.json();o.ok?(r?r(!0):alert(n("report_success_sent")),sessionStorage.removeItem(v)):(console.error("Server returned error response:",i),r?r(!1):alert(n("report_failed")))}catch(o){console.error("Network or other error:",o),r?r(!1):alert(n("report_failed"))}}}function se(e,t){if(e.match(/^[a-z]+:\/\//i))return e;if(e.match(/^\/\//))return window.location.protocol+e;if(e.match(/^[a-z]+:/i))return e;const r=document.implementation.createHTMLDocument(),n=r.createElement("base"),s=r.createElement("a");return r.head.appendChild(n),r.body.appendChild(s),t&&(n.href=t),s.href=e,s.href}const ie=(()=>{let e=0;const t=()=>`0000${(Math.random()*36**4<<0).toString(36)}`.slice(-4);return()=>(e+=1,`u${t()}${e}`)})();function p(e){const t=[];for(let r=0,n=e.length;r<n;r++)t.push(e[r]);return t}let b=null;function F(e={}){return b||(e.includeStyleProperties?(b=e.includeStyleProperties,b):(b=p(window.getComputedStyle(document.documentElement)),b))}function C(e,t){const n=(e.ownerDocument.defaultView||window).getComputedStyle(e).getPropertyValue(t);return n?parseFloat(n.replace("px","")):0}function ae(e){const t=C(e,"border-left-width"),r=C(e,"border-right-width");return e.clientWidth+t+r}function ce(e){const t=C(e,"border-top-width"),r=C(e,"border-bottom-width");return e.clientHeight+t+r}function j(e,t={}){const r=t.width||ae(e),n=t.height||ce(e);return{width:r,height:n}}function le(){let e,t;try{t=process}catch{}const r=t&&t.env?t.env.devicePixelRatio:null;return r&&(e=parseInt(r,10),Number.isNaN(e)&&(e=1)),e||window.devicePixelRatio||1}const h=16384;function ue(e){(e.width>h||e.height>h)&&(e.width>h&&e.height>h?e.width>e.height?(e.height*=h/e.width,e.width=h):(e.width*=h/e.height,e.height=h):e.width>h?(e.height*=h/e.width,e.width=h):(e.width*=h/e.height,e.height=h))}function q(e){return new Promise((t,r)=>{const n=new Image;n.onload=()=>{n.decode().then(()=>{requestAnimationFrame(()=>t(n))})},n.onerror=r,n.crossOrigin="anonymous",n.decoding="async",n.src=e})}async function de(e){return Promise.resolve().then(()=>new XMLSerializer().serializeToString(e)).then(encodeURIComponent).then(t=>`data:image/svg+xml;charset=utf-8,${t}`)}async function fe(e,t,r){const n="http://www.w3.org/2000/svg",s=document.createElementNS(n,"svg"),o=document.createElementNS(n,"foreignObject");return s.setAttribute("width",`${t}`),s.setAttribute("height",`${r}`),s.setAttribute("viewBox",`0 0 ${t} ${r}`),o.setAttribute("width","100%"),o.setAttribute("height","100%"),o.setAttribute("x","0"),o.setAttribute("y","0"),o.setAttribute("externalResourcesRequired","true"),s.appendChild(o),o.appendChild(e),de(s)}const m=(e,t)=>{if(e instanceof t)return!0;const r=Object.getPrototypeOf(e);return r===null?!1:r.constructor.name===t.name||m(r,t)};function me(e){const t=e.getPropertyValue("content");return`${e.cssText} content: '${t.replace(/'|"/g,"")}';`}function he(e,t){return F(t).map(r=>{const n=e.getPropertyValue(r),s=e.getPropertyPriority(r);return`${r}: ${n}${s?" !important":""};`}).join(" ")}function pe(e,t,r,n){const s=`.${e}:${t}`,o=r.cssText?me(r):he(r,n);return document.createTextNode(`${s}{${o}}`)}function O(e,t,r,n){const s=window.getComputedStyle(e,r),o=s.getPropertyValue("content");if(o===""||o==="none")return;const i=ie();try{t.className=`${t.className} ${i}`}catch{return}const a=document.createElement("style");a.appendChild(pe(i,r,s,n)),t.appendChild(a)}function ge(e,t,r){O(e,t,":before",r),O(e,t,":after",r)}const D="application/font-woff",U="image/jpeg",ye={woff:D,woff2:D,ttf:"application/font-truetype",eot:"application/vnd.ms-fontobject",png:"image/png",jpg:U,jpeg:U,gif:"image/gif",tiff:"image/tiff",svg:"image/svg+xml",webp:"image/webp"};function be(e){const t=/\.([^./]*?)$/g.exec(e);return t?t[1]:""}function I(e){const t=be(e).toLowerCase();return ye[t]||""}function we(e){return e.split(/,/)[1]}function k(e){return e.search(/^(data:)/)!==-1}function xe(e,t){return`data:${t};base64,${e}`}async function H(e,t,r){const n=await fetch(e,t);if(n.status===404)throw new Error(`Resource "${n.url}" not found`);const s=await n.blob();return new Promise((o,i)=>{const a=new FileReader;a.onerror=i,a.onloadend=()=>{try{o(r({res:n,result:a.result}))}catch(c){i(c)}},a.readAsDataURL(s)})}const T={};function Ee(e,t,r){let n=e.replace(/\?.*/,"");return r&&(n=e),/ttf|otf|eot|woff2?/i.test(n)&&(n=n.replace(/.*\//,"")),t?`[${t}]${n}`:n}async function P(e,t,r){const n=Ee(e,t,r.includeQueryParams);if(T[n]!=null)return T[n];r.cacheBust&&(e+=(/\?/.test(e)?"&":"?")+new Date().getTime());let s;try{const o=await H(e,r.fetchRequestInit,({res:i,result:a})=>(t||(t=i.headers.get("Content-Type")||""),we(a)));s=xe(o,t)}catch(o){s=r.imagePlaceholder||"";let i=`Failed to fetch resource: ${e}`;o&&(i=typeof o=="string"?o:o.message),i&&console.warn(i)}return T[n]=s,s}async function _e(e){const t=e.toDataURL();return t==="data:,"?e.cloneNode(!1):q(t)}async function Se(e,t){if(e.currentSrc){const o=document.createElement("canvas"),i=o.getContext("2d");o.width=e.clientWidth,o.height=e.clientHeight,i?.drawImage(e,0,0,o.width,o.height);const a=o.toDataURL();return q(a)}const r=e.poster,n=I(r),s=await P(r,n,t);return q(s)}async function Re(e,t){var r;try{if(!((r=e?.contentDocument)===null||r===void 0)&&r.body)return await L(e.contentDocument.body,t,!0)}catch{}return e.cloneNode(!1)}async function ve(e,t){return m(e,HTMLCanvasElement)?_e(e):m(e,HTMLVideoElement)?Se(e,t):m(e,HTMLIFrameElement)?Re(e,t):e.cloneNode(M(e))}const Ce=e=>e.tagName!=null&&e.tagName.toUpperCase()==="SLOT",M=e=>e.tagName!=null&&e.tagName.toUpperCase()==="SVG";async function qe(e,t,r){var n,s;if(M(t))return t;let o=[];return Ce(e)&&e.assignedNodes?o=p(e.assignedNodes()):m(e,HTMLIFrameElement)&&(!((n=e.contentDocument)===null||n===void 0)&&n.body)?o=p(e.contentDocument.body.childNodes):o=p(((s=e.shadowRoot)!==null&&s!==void 0?s:e).childNodes),o.length===0||m(e,HTMLVideoElement)||await o.reduce((i,a)=>i.then(()=>L(a,r)).then(c=>{c&&t.appendChild(c)}),Promise.resolve()),t}function Le(e,t,r){const n=t.style;if(!n)return;const s=window.getComputedStyle(e);s.cssText?(n.cssText=s.cssText,n.transformOrigin=s.transformOrigin):F(r).forEach(o=>{let i=s.getPropertyValue(o);o==="font-size"&&i.endsWith("px")&&(i=`${Math.floor(parseFloat(i.substring(0,i.length-2)))-.1}px`),m(e,HTMLIFrameElement)&&o==="display"&&i==="inline"&&(i="block"),o==="d"&&t.getAttribute("d")&&(i=`path(${t.getAttribute("d")})`),n.setProperty(o,i,s.getPropertyPriority(o))})}function Ie(e,t){m(e,HTMLTextAreaElement)&&(t.innerHTML=e.value),m(e,HTMLInputElement)&&t.setAttribute("value",e.value)}function ke(e,t){if(m(e,HTMLSelectElement)){const r=t,n=Array.from(r.children).find(s=>e.value===s.getAttribute("value"));n&&n.setAttribute("selected","")}}function Te(e,t,r){return m(t,Element)&&(Le(e,t,r),ge(e,t,r),Ie(e,t),ke(e,t)),t}async function Pe(e,t){const r=e.querySelectorAll?e.querySelectorAll("use"):[];if(r.length===0)return e;const n={};for(let o=0;o<r.length;o++){const a=r[o].getAttribute("xlink:href");if(a){const c=e.querySelector(a),l=document.querySelector(a);!c&&l&&!n[a]&&(n[a]=await L(l,t,!0))}}const s=Object.values(n);if(s.length){const o="http://www.w3.org/1999/xhtml",i=document.createElementNS(o,"svg");i.setAttribute("xmlns",o),i.style.position="absolute",i.style.width="0",i.style.height="0",i.style.overflow="hidden",i.style.display="none";const a=document.createElementNS(o,"defs");i.appendChild(a);for(let c=0;c<s.length;c++)a.appendChild(s[c]);e.appendChild(i)}return e}async function L(e,t,r){return!r&&t.filter&&!t.filter(e)?null:Promise.resolve(e).then(n=>ve(n,t)).then(n=>qe(e,n,t)).then(n=>Te(e,n,t)).then(n=>Pe(n,t))}const z=/url\((['"]?)([^'"]+?)\1\)/g,$e=/url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g,Ae=/src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;function Fe(e){const t=e.replace(/([.*+?^${}()|\[\]\/\\])/g,"\\$1");return new RegExp(`(url\\(['"]?)(${t})(['"]?\\))`,"g")}function je(e){const t=[];return e.replace(z,(r,n,s)=>(t.push(s),r)),t.filter(r=>!k(r))}async function Oe(e,t,r,n,s){try{const o=r?se(t,r):t,i=I(t);let a;return s||(a=await P(o,i,n)),e.replace(Fe(t),`$1${a}$3`)}catch{}return e}function De(e,{preferredFontFormat:t}){return t?e.replace(Ae,r=>{for(;;){const[n,,s]=$e.exec(r)||[];if(!s)return"";if(s===t)return`src: ${n};`}}):e}function B(e){return e.search(z)!==-1}async function V(e,t,r){if(!B(e))return e;const n=De(e,r);return je(n).reduce((o,i)=>o.then(a=>Oe(a,i,t,r)),Promise.resolve(n))}async function w(e,t,r){var n;const s=(n=t.style)===null||n===void 0?void 0:n.getPropertyValue(e);if(s){const o=await V(s,null,r);return t.style.setProperty(e,o,t.style.getPropertyPriority(e)),!0}return!1}async function Ue(e,t){await w("background",e,t)||await w("background-image",e,t),await w("mask",e,t)||await w("-webkit-mask",e,t)||await w("mask-image",e,t)||await w("-webkit-mask-image",e,t)}async function He(e,t){const r=m(e,HTMLImageElement);if(!(r&&!k(e.src))&&!(m(e,SVGImageElement)&&!k(e.href.baseVal)))return;const n=r?e.src:e.href.baseVal,s=await P(n,I(n),t);await new Promise((o,i)=>{e.onload=o,e.onerror=t.onImageErrorHandler?(...c)=>{try{o(t.onImageErrorHandler(...c))}catch(l){i(l)}}:i;const a=e;a.decode&&(a.decode=o),a.loading==="lazy"&&(a.loading="eager"),r?(e.srcset="",e.src=s):e.href.baseVal=s})}async function Me(e,t){const n=p(e.childNodes).map(s=>J(s,t));await Promise.all(n).then(()=>e)}async function J(e,t){m(e,Element)&&(await Ue(e,t),await He(e,t),await Me(e,t))}function ze(e,t){const{style:r}=e;t.backgroundColor&&(r.backgroundColor=t.backgroundColor),t.width&&(r.width=`${t.width}px`),t.height&&(r.height=`${t.height}px`);const n=t.style;return n!=null&&Object.keys(n).forEach(s=>{r[s]=n[s]}),e}const W={};async function G(e){let t=W[e];if(t!=null)return t;const n=await(await fetch(e)).text();return t={url:e,cssText:n},W[e]=t,t}async function X(e,t){let r=e.cssText;const n=/url\(["']?([^"')]+)["']?\)/g,o=(r.match(/url\([^)]+\)/g)||[]).map(async i=>{let a=i.replace(n,"$1");return a.startsWith("https://")||(a=new URL(a,e.url).href),H(a,t.fetchRequestInit,({result:c})=>(r=r.replace(i,`url(${c})`),[i,c]))});return Promise.all(o).then(()=>r)}function N(e){if(e==null)return[];const t=[],r=/(\/\*[\s\S]*?\*\/)/gi;let n=e.replace(r,"");const s=new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})","gi");for(;;){const c=s.exec(n);if(c===null)break;t.push(c[0])}n=n.replace(s,"");const o=/@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi,i="((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})",a=new RegExp(i,"gi");for(;;){let c=o.exec(n);if(c===null){if(c=a.exec(n),c===null)break;o.lastIndex=a.lastIndex}else a.lastIndex=o.lastIndex;t.push(c[0])}return t}async function Be(e,t){const r=[],n=[];return e.forEach(s=>{if("cssRules"in s)try{p(s.cssRules||[]).forEach((o,i)=>{if(o.type===CSSRule.IMPORT_RULE){let a=i+1;const c=o.href,l=G(c).then(d=>X(d,t)).then(d=>N(d).forEach(u=>{try{s.insertRule(u,u.startsWith("@import")?a+=1:s.cssRules.length)}catch(f){console.error("Error inserting rule from remote css",{rule:u,error:f})}})).catch(d=>{console.error("Error loading remote css",d.toString())});n.push(l)}})}catch(o){const i=e.find(a=>a.href==null)||document.styleSheets[0];s.href!=null&&n.push(G(s.href).then(a=>X(a,t)).then(a=>N(a).forEach(c=>{i.insertRule(c,i.cssRules.length)})).catch(a=>{console.error("Error loading remote stylesheet",a)})),console.error("Error inlining remote css file",o)}}),Promise.all(n).then(()=>(e.forEach(s=>{if("cssRules"in s)try{p(s.cssRules||[]).forEach(o=>{r.push(o)})}catch(o){console.error(`Error while reading CSS rules from ${s.href}`,o)}}),r))}function Ve(e){return e.filter(t=>t.type===CSSRule.FONT_FACE_RULE).filter(t=>B(t.style.getPropertyValue("src")))}async function Je(e,t){if(e.ownerDocument==null)throw new Error("Provided element is not within a Document");const r=p(e.ownerDocument.styleSheets),n=await Be(r,t);return Ve(n)}function Q(e){return e.trim().replace(/["']/g,"")}function We(e){const t=new Set;function r(n){(n.style.fontFamily||getComputedStyle(n).fontFamily).split(",").forEach(o=>{t.add(Q(o))}),Array.from(n.children).forEach(o=>{o instanceof HTMLElement&&r(o)})}return r(e),t}async function Ge(e,t){const r=await Je(e,t),n=We(e);return(await Promise.all(r.filter(o=>n.has(Q(o.style.fontFamily))).map(o=>{const i=o.parentStyleSheet?o.parentStyleSheet.href:null;return V(o.cssText,i,t)}))).join(`
`)}async function Xe(e,t){const r=t.fontEmbedCSS!=null?t.fontEmbedCSS:t.skipFonts?null:await Ge(e,t);if(r){const n=document.createElement("style"),s=document.createTextNode(r);n.appendChild(s),e.firstChild?e.insertBefore(n,e.firstChild):e.appendChild(n)}}async function K(e,t={}){const{width:r,height:n}=j(e,t),s=await L(e,t,!0);return await Xe(s,t),await J(s,t),ze(s,t),await fe(s,r,n)}async function Y(e,t={}){const{width:r,height:n}=j(e,t),s=await K(e,t),o=await q(s),i=document.createElement("canvas"),a=i.getContext("2d"),c=t.pixelRatio||le(),l=t.canvasWidth||r,d=t.canvasHeight||n;return i.width=l*c,i.height=d*c,t.skipAutoScale||ue(i),i.style.width=`${l}`,i.style.height=`${d}`,t.backgroundColor&&(a.fillStyle=t.backgroundColor,a.fillRect(0,0,i.width,i.height)),a.drawImage(o,0,0,i.width,i.height),i}async function Ne(e,t={}){return(await Y(e,t)).toDataURL("image/jpeg",t.quality||1)}const Qe=Object.freeze(Object.defineProperty({__proto__:null,toCanvas:Y,toJpeg:Ne,toSvg:K},Symbol.toStringTag,{value:"Module"}));y.BugReporter=oe,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});