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.
483 lines (482 loc) • 16.6 kB
JavaScript
function W(t, e) {
if (t.match(/^[a-z]+:\/\//i))
return t;
if (t.match(/^\/\//))
return window.location.protocol + t;
if (t.match(/^[a-z]+:/i))
return t;
const r = document.implementation.createHTMLDocument(), n = r.createElement("base"), s = r.createElement("a");
return r.head.appendChild(n), r.body.appendChild(s), e && (n.href = e), s.href = t, s.href;
}
const j = /* @__PURE__ */ (() => {
let t = 0;
const e = () => (
// eslint-disable-next-line no-bitwise
`0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4)
);
return () => (t += 1, `u${e()}${t}`);
})();
function m(t) {
const e = [];
for (let r = 0, n = t.length; r < n; r++)
e.push(t[r]);
return e;
}
let g = null;
function A(t = {}) {
return g || (t.includeStyleProperties ? (g = t.includeStyleProperties, g) : (g = m(window.getComputedStyle(document.documentElement)), g));
}
function y(t, e) {
const n = (t.ownerDocument.defaultView || window).getComputedStyle(t).getPropertyValue(e);
return n ? parseFloat(n.replace("px", "")) : 0;
}
function q(t) {
const e = y(t, "border-left-width"), r = y(t, "border-right-width");
return t.clientWidth + e + r;
}
function z(t) {
const e = y(t, "border-top-width"), r = y(t, "border-bottom-width");
return t.clientHeight + e + r;
}
function k(t, e = {}) {
const r = e.width || q(t), n = e.height || z(t);
return { width: r, height: n };
}
function B() {
let t, e;
try {
e = process;
} catch {
}
const r = e && e.env ? e.env.devicePixelRatio : null;
return r && (t = parseInt(r, 10), Number.isNaN(t) && (t = 1)), t || window.devicePixelRatio || 1;
}
const u = 16384;
function G(t) {
(t.width > u || t.height > u) && (t.width > u && t.height > u ? t.width > t.height ? (t.height *= u / t.width, t.width = u) : (t.width *= u / t.height, t.height = u) : t.width > u ? (t.height *= u / t.width, t.width = u) : (t.width *= u / t.height, t.height = u));
}
function w(t) {
return new Promise((e, r) => {
const n = new Image();
n.onload = () => {
n.decode().then(() => {
requestAnimationFrame(() => e(n));
});
}, n.onerror = r, n.crossOrigin = "anonymous", n.decoding = "async", n.src = t;
});
}
async function X(t) {
return Promise.resolve().then(() => new XMLSerializer().serializeToString(t)).then(encodeURIComponent).then((e) => `data:image/svg+xml;charset=utf-8,${e}`);
}
async function J(t, e, r) {
const n = "http://www.w3.org/2000/svg", s = document.createElementNS(n, "svg"), i = document.createElementNS(n, "foreignObject");
return s.setAttribute("width", `${e}`), s.setAttribute("height", `${r}`), s.setAttribute("viewBox", `0 0 ${e} ${r}`), i.setAttribute("width", "100%"), i.setAttribute("height", "100%"), i.setAttribute("x", "0"), i.setAttribute("y", "0"), i.setAttribute("externalResourcesRequired", "true"), s.appendChild(i), i.appendChild(t), X(s);
}
const l = (t, e) => {
if (t instanceof e)
return !0;
const r = Object.getPrototypeOf(t);
return r === null ? !1 : r.constructor.name === e.name || l(r, e);
};
function K(t) {
const e = t.getPropertyValue("content");
return `${t.cssText} content: '${e.replace(/'|"/g, "")}';`;
}
function Q(t, e) {
return A(e).map((r) => {
const n = t.getPropertyValue(r), s = t.getPropertyPriority(r);
return `${r}: ${n}${s ? " !important" : ""};`;
}).join(" ");
}
function Y(t, e, r, n) {
const s = `.${t}:${e}`, i = r.cssText ? K(r) : Q(r, n);
return document.createTextNode(`${s}{${i}}`);
}
function C(t, e, r, n) {
const s = window.getComputedStyle(t, r), i = s.getPropertyValue("content");
if (i === "" || i === "none")
return;
const c = j();
try {
e.className = `${e.className} ${c}`;
} catch {
return;
}
const a = document.createElement("style");
a.appendChild(Y(c, r, s, n)), e.appendChild(a);
}
function Z(t, e, r) {
C(t, e, ":before", r), C(t, e, ":after", r);
}
const P = "application/font-woff", $ = "image/jpeg", N = {
woff: P,
woff2: P,
ttf: "application/font-truetype",
eot: "application/vnd.ms-fontobject",
png: "image/png",
jpg: $,
jpeg: $,
gif: "image/gif",
tiff: "image/tiff",
svg: "image/svg+xml",
webp: "image/webp"
};
function tt(t) {
const e = /\.([^./]*?)$/g.exec(t);
return e ? e[1] : "";
}
function x(t) {
const e = tt(t).toLowerCase();
return N[e] || "";
}
function et(t) {
return t.split(/,/)[1];
}
function E(t) {
return t.search(/^(data:)/) !== -1;
}
function rt(t, e) {
return `data:${e};base64,${t}`;
}
async function D(t, e, r) {
const n = await fetch(t, e);
if (n.status === 404)
throw new Error(`Resource "${n.url}" not found`);
const s = await n.blob();
return new Promise((i, c) => {
const a = new FileReader();
a.onerror = c, a.onloadend = () => {
try {
i(r({ res: n, result: a.result }));
} catch (o) {
c(o);
}
}, a.readAsDataURL(s);
});
}
const b = {};
function nt(t, e, r) {
let n = t.replace(/\?.*/, "");
return r && (n = t), /ttf|otf|eot|woff2?/i.test(n) && (n = n.replace(/.*\//, "")), e ? `[${e}]${n}` : n;
}
async function R(t, e, r) {
const n = nt(t, e, r.includeQueryParams);
if (b[n] != null)
return b[n];
r.cacheBust && (t += (/\?/.test(t) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime());
let s;
try {
const i = await D(t, r.fetchRequestInit, ({ res: c, result: a }) => (e || (e = c.headers.get("Content-Type") || ""), et(a)));
s = rt(i, e);
} catch (i) {
s = r.imagePlaceholder || "";
let c = `Failed to fetch resource: ${t}`;
i && (c = typeof i == "string" ? i : i.message), c && console.warn(c);
}
return b[n] = s, s;
}
async function it(t) {
const e = t.toDataURL();
return e === "data:," ? t.cloneNode(!1) : w(e);
}
async function st(t, e) {
if (t.currentSrc) {
const i = document.createElement("canvas"), c = i.getContext("2d");
i.width = t.clientWidth, i.height = t.clientHeight, c?.drawImage(t, 0, 0, i.width, i.height);
const a = i.toDataURL();
return w(a);
}
const r = t.poster, n = x(r), s = await R(r, n, e);
return w(s);
}
async function ct(t, e) {
var r;
try {
if (!((r = t?.contentDocument) === null || r === void 0) && r.body)
return await p(t.contentDocument.body, e, !0);
} catch {
}
return t.cloneNode(!1);
}
async function at(t, e) {
return l(t, HTMLCanvasElement) ? it(t) : l(t, HTMLVideoElement) ? st(t, e) : l(t, HTMLIFrameElement) ? ct(t, e) : t.cloneNode(v(t));
}
const ot = (t) => t.tagName != null && t.tagName.toUpperCase() === "SLOT", v = (t) => t.tagName != null && t.tagName.toUpperCase() === "SVG";
async function lt(t, e, r) {
var n, s;
if (v(e))
return e;
let i = [];
return ot(t) && t.assignedNodes ? i = m(t.assignedNodes()) : l(t, HTMLIFrameElement) && (!((n = t.contentDocument) === null || n === void 0) && n.body) ? i = m(t.contentDocument.body.childNodes) : i = m(((s = t.shadowRoot) !== null && s !== void 0 ? s : t).childNodes), i.length === 0 || l(t, HTMLVideoElement) || await i.reduce((c, a) => c.then(() => p(a, r)).then((o) => {
o && e.appendChild(o);
}), Promise.resolve()), e;
}
function ut(t, e, r) {
const n = e.style;
if (!n)
return;
const s = window.getComputedStyle(t);
s.cssText ? (n.cssText = s.cssText, n.transformOrigin = s.transformOrigin) : A(r).forEach((i) => {
let c = s.getPropertyValue(i);
i === "font-size" && c.endsWith("px") && (c = `${Math.floor(parseFloat(c.substring(0, c.length - 2))) - 0.1}px`), l(t, HTMLIFrameElement) && i === "display" && c === "inline" && (c = "block"), i === "d" && e.getAttribute("d") && (c = `path(${e.getAttribute("d")})`), n.setProperty(i, c, s.getPropertyPriority(i));
});
}
function ft(t, e) {
l(t, HTMLTextAreaElement) && (e.innerHTML = t.value), l(t, HTMLInputElement) && e.setAttribute("value", t.value);
}
function ht(t, e) {
if (l(t, HTMLSelectElement)) {
const r = e, n = Array.from(r.children).find((s) => t.value === s.getAttribute("value"));
n && n.setAttribute("selected", "");
}
}
function mt(t, e, r) {
return l(e, Element) && (ut(t, e, r), Z(t, e, r), ft(t, e), ht(t, e)), e;
}
async function gt(t, e) {
const r = t.querySelectorAll ? t.querySelectorAll("use") : [];
if (r.length === 0)
return t;
const n = {};
for (let i = 0; i < r.length; i++) {
const a = r[i].getAttribute("xlink:href");
if (a) {
const o = t.querySelector(a), f = document.querySelector(a);
!o && f && !n[a] && (n[a] = await p(f, e, !0));
}
}
const s = Object.values(n);
if (s.length) {
const i = "http://www.w3.org/1999/xhtml", c = document.createElementNS(i, "svg");
c.setAttribute("xmlns", i), c.style.position = "absolute", c.style.width = "0", c.style.height = "0", c.style.overflow = "hidden", c.style.display = "none";
const a = document.createElementNS(i, "defs");
c.appendChild(a);
for (let o = 0; o < s.length; o++)
a.appendChild(s[o]);
t.appendChild(c);
}
return t;
}
async function p(t, e, r) {
return !r && e.filter && !e.filter(t) ? null : Promise.resolve(t).then((n) => at(n, e)).then((n) => lt(t, n, e)).then((n) => mt(t, n, e)).then((n) => gt(n, e));
}
const U = /url\((['"]?)([^'"]+?)\1\)/g, dt = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, yt = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
function wt(t) {
const e = t.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
return new RegExp(`(url\\(['"]?)(${e})(['"]?\\))`, "g");
}
function pt(t) {
const e = [];
return t.replace(U, (r, n, s) => (e.push(s), r)), e.filter((r) => !E(r));
}
async function St(t, e, r, n, s) {
try {
const i = r ? W(e, r) : e, c = x(e);
let a;
return s || (a = await R(i, c, n)), t.replace(wt(e), `$1${a}$3`);
} catch {
}
return t;
}
function bt(t, { preferredFontFormat: e }) {
return e ? t.replace(yt, (r) => {
for (; ; ) {
const [n, , s] = dt.exec(r) || [];
if (!s)
return "";
if (s === e)
return `src: ${n};`;
}
}) : t;
}
function H(t) {
return t.search(U) !== -1;
}
async function V(t, e, r) {
if (!H(t))
return t;
const n = bt(t, r);
return pt(n).reduce((i, c) => i.then((a) => St(a, c, e, r)), Promise.resolve(n));
}
async function d(t, e, r) {
var n;
const s = (n = e.style) === null || n === void 0 ? void 0 : n.getPropertyValue(t);
if (s) {
const i = await V(s, null, r);
return e.style.setProperty(t, i, e.style.getPropertyPriority(t)), !0;
}
return !1;
}
async function Et(t, e) {
await d("background", t, e) || await d("background-image", t, e), await d("mask", t, e) || await d("-webkit-mask", t, e) || await d("mask-image", t, e) || await d("-webkit-mask-image", t, e);
}
async function xt(t, e) {
const r = l(t, HTMLImageElement);
if (!(r && !E(t.src)) && !(l(t, SVGImageElement) && !E(t.href.baseVal)))
return;
const n = r ? t.src : t.href.baseVal, s = await R(n, x(n), e);
await new Promise((i, c) => {
t.onload = i, t.onerror = e.onImageErrorHandler ? (...o) => {
try {
i(e.onImageErrorHandler(...o));
} catch (f) {
c(f);
}
} : c;
const a = t;
a.decode && (a.decode = i), a.loading === "lazy" && (a.loading = "eager"), r ? (t.srcset = "", t.src = s) : t.href.baseVal = s;
});
}
async function Rt(t, e) {
const n = m(t.childNodes).map((s) => M(s, e));
await Promise.all(n).then(() => t);
}
async function M(t, e) {
l(t, Element) && (await Et(t, e), await xt(t, e), await Rt(t, e));
}
function Ct(t, e) {
const { style: r } = t;
e.backgroundColor && (r.backgroundColor = e.backgroundColor), e.width && (r.width = `${e.width}px`), e.height && (r.height = `${e.height}px`);
const n = e.style;
return n != null && Object.keys(n).forEach((s) => {
r[s] = n[s];
}), t;
}
const T = {};
async function F(t) {
let e = T[t];
if (e != null)
return e;
const n = await (await fetch(t)).text();
return e = { url: t, cssText: n }, T[t] = e, e;
}
async function L(t, e) {
let r = t.cssText;
const n = /url\(["']?([^"')]+)["']?\)/g, i = (r.match(/url\([^)]+\)/g) || []).map(async (c) => {
let a = c.replace(n, "$1");
return a.startsWith("https://") || (a = new URL(a, t.url).href), D(a, e.fetchRequestInit, ({ result: o }) => (r = r.replace(c, `url(${o})`), [c, o]));
});
return Promise.all(i).then(() => r);
}
function I(t) {
if (t == null)
return [];
const e = [], r = /(\/\*[\s\S]*?\*\/)/gi;
let n = t.replace(r, "");
const s = new RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi");
for (; ; ) {
const o = s.exec(n);
if (o === null)
break;
e.push(o[0]);
}
n = n.replace(s, "");
const i = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi, c = "((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})", a = new RegExp(c, "gi");
for (; ; ) {
let o = i.exec(n);
if (o === null) {
if (o = a.exec(n), o === null)
break;
i.lastIndex = a.lastIndex;
} else
a.lastIndex = i.lastIndex;
e.push(o[0]);
}
return e;
}
async function Pt(t, e) {
const r = [], n = [];
return t.forEach((s) => {
if ("cssRules" in s)
try {
m(s.cssRules || []).forEach((i, c) => {
if (i.type === CSSRule.IMPORT_RULE) {
let a = c + 1;
const o = i.href, f = F(o).then((h) => L(h, e)).then((h) => I(h).forEach((S) => {
try {
s.insertRule(S, S.startsWith("@import") ? a += 1 : s.cssRules.length);
} catch (_) {
console.error("Error inserting rule from remote css", {
rule: S,
error: _
});
}
})).catch((h) => {
console.error("Error loading remote css", h.toString());
});
n.push(f);
}
});
} catch (i) {
const c = t.find((a) => a.href == null) || document.styleSheets[0];
s.href != null && n.push(F(s.href).then((a) => L(a, e)).then((a) => I(a).forEach((o) => {
c.insertRule(o, c.cssRules.length);
})).catch((a) => {
console.error("Error loading remote stylesheet", a);
})), console.error("Error inlining remote css file", i);
}
}), Promise.all(n).then(() => (t.forEach((s) => {
if ("cssRules" in s)
try {
m(s.cssRules || []).forEach((i) => {
r.push(i);
});
} catch (i) {
console.error(`Error while reading CSS rules from ${s.href}`, i);
}
}), r));
}
function $t(t) {
return t.filter((e) => e.type === CSSRule.FONT_FACE_RULE).filter((e) => H(e.style.getPropertyValue("src")));
}
async function Tt(t, e) {
if (t.ownerDocument == null)
throw new Error("Provided element is not within a Document");
const r = m(t.ownerDocument.styleSheets), n = await Pt(r, e);
return $t(n);
}
function O(t) {
return t.trim().replace(/["']/g, "");
}
function Ft(t) {
const e = /* @__PURE__ */ new Set();
function r(n) {
(n.style.fontFamily || getComputedStyle(n).fontFamily).split(",").forEach((i) => {
e.add(O(i));
}), Array.from(n.children).forEach((i) => {
i instanceof HTMLElement && r(i);
});
}
return r(t), e;
}
async function Lt(t, e) {
const r = await Tt(t, e), n = Ft(t);
return (await Promise.all(r.filter((i) => n.has(O(i.style.fontFamily))).map((i) => {
const c = i.parentStyleSheet ? i.parentStyleSheet.href : null;
return V(i.cssText, c, e);
}))).join(`
`);
}
async function It(t, e) {
const r = e.fontEmbedCSS != null ? e.fontEmbedCSS : e.skipFonts ? null : await Lt(t, e);
if (r) {
const n = document.createElement("style"), s = document.createTextNode(r);
n.appendChild(s), t.firstChild ? t.insertBefore(n, t.firstChild) : t.appendChild(n);
}
}
async function At(t, e = {}) {
const { width: r, height: n } = k(t, e), s = await p(t, e, !0);
return await It(s, e), await M(s, e), Ct(s, e), await J(s, r, n);
}
async function kt(t, e = {}) {
const { width: r, height: n } = k(t, e), s = await At(t, e), i = await w(s), c = document.createElement("canvas"), a = c.getContext("2d"), o = e.pixelRatio || B(), f = e.canvasWidth || r, h = e.canvasHeight || n;
return c.width = f * o, c.height = h * o, e.skipAutoScale || G(c), c.style.width = `${f}`, c.style.height = `${h}`, e.backgroundColor && (a.fillStyle = e.backgroundColor, a.fillRect(0, 0, c.width, c.height)), a.drawImage(i, 0, 0, c.width, c.height), c;
}
async function Dt(t, e = {}) {
return (await kt(t, e)).toDataURL("image/jpeg", e.quality || 1);
}
export {
kt as toCanvas,
Dt as toJpeg,
At as toSvg
};