@burdenoff/microfe-bigconsole 2026.1103.6 → 2026.1103.7
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/dist/bigconsole/hooks/useDashboardImageExport.js +44 -64
- package/dist/bigconsole/hooks/useWidgetExport.js +37 -51
- package/dist/bigconsole/utils/elementToCanvas.d.ts +9 -0
- package/dist/bigconsole/utils/elementToCanvas.js +16 -0
- package/dist/node_modules/html-to-image/es/apply-style.js +11 -0
- package/dist/node_modules/html-to-image/es/clone-node.js +82 -0
- package/dist/node_modules/html-to-image/es/clone-pseudos.js +30 -0
- package/dist/node_modules/html-to-image/es/dataurl.js +49 -0
- package/dist/node_modules/html-to-image/es/embed-images.js +41 -0
- package/dist/node_modules/html-to-image/es/embed-resources.js +39 -0
- package/dist/node_modules/html-to-image/es/embed-webfonts.js +115 -0
- package/dist/node_modules/html-to-image/es/index.js +16 -0
- package/dist/node_modules/html-to-image/es/mimes.js +23 -0
- package/dist/node_modules/html-to-image/es/util.js +75 -0
- package/package.json +3 -2
|
@@ -1,90 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { elementToCanvas as e } from "../utils/elementToCanvas.js";
|
|
2
|
+
import { useCallback as t, useState as n } from "react";
|
|
3
|
+
import { useI18n as r } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
4
|
+
import { toast as i } from "sonner";
|
|
2
5
|
//#region src/bigconsole/hooks/useDashboardImageExport.ts
|
|
3
|
-
function
|
|
6
|
+
function a(e, t) {
|
|
4
7
|
let n = URL.createObjectURL(e), r = document.createElement("a");
|
|
5
8
|
r.href = n, r.download = t, r.click(), URL.revokeObjectURL(n);
|
|
6
9
|
}
|
|
7
|
-
function
|
|
8
|
-
let t =
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
async function i(e) {
|
|
12
|
-
if (typeof window < "u" && "html2canvas" in window) return await window.html2canvas(e, {
|
|
13
|
-
backgroundColor: r(e),
|
|
14
|
-
scale: 2,
|
|
15
|
-
useCORS: !0
|
|
16
|
-
});
|
|
17
|
-
let t = document.createElement("canvas"), n = t.getContext("2d");
|
|
18
|
-
if (!n) throw Error("Could not get canvas context");
|
|
19
|
-
let i = e.getBoundingClientRect();
|
|
20
|
-
t.width = i.width * 2, t.height = i.height * 2, n.scale(2, 2), n.fillStyle = r(e), n.fillRect(0, 0, i.width, i.height);
|
|
21
|
-
let a = e.querySelectorAll("svg");
|
|
22
|
-
for (let e of a) {
|
|
23
|
-
let t = new XMLSerializer().serializeToString(e), r = new Blob([t], { type: "image/svg+xml;charset=utf-8" }), a = URL.createObjectURL(r);
|
|
24
|
-
try {
|
|
25
|
-
await new Promise((t) => {
|
|
26
|
-
let r = new Image();
|
|
27
|
-
r.onload = () => {
|
|
28
|
-
let a = e.getBoundingClientRect();
|
|
29
|
-
n.drawImage(r, a.left - i.left, a.top - i.top), t();
|
|
30
|
-
}, r.onerror = () => t(), r.src = a;
|
|
31
|
-
});
|
|
32
|
-
} finally {
|
|
33
|
-
URL.revokeObjectURL(a);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return t;
|
|
37
|
-
}
|
|
38
|
-
function a(r) {
|
|
39
|
-
let { containerRef: a, name: o = "dashboard" } = r, [s, c] = t(!1);
|
|
10
|
+
function o(o) {
|
|
11
|
+
let { containerRef: s, name: c = "dashboard" } = o, [l, u] = n(!1), { t: d } = r(), f = t(() => {
|
|
12
|
+
i.error(d("bigconsole.dashboards.export.failed", "Could not export the dashboard. Please try again."));
|
|
13
|
+
}, [d]);
|
|
40
14
|
return {
|
|
41
|
-
exportPNG:
|
|
42
|
-
let
|
|
43
|
-
if (!(!
|
|
44
|
-
|
|
15
|
+
exportPNG: t(async (t) => {
|
|
16
|
+
let n = s.current;
|
|
17
|
+
if (!(!n || l)) {
|
|
18
|
+
u(!0);
|
|
45
19
|
try {
|
|
46
|
-
let r = await
|
|
20
|
+
let r = await e(n), i = await new Promise((e, t) => {
|
|
47
21
|
r.toBlob((n) => n ? e(n) : t(/* @__PURE__ */ Error("Failed to create image blob")), "image/png");
|
|
48
|
-
}),
|
|
49
|
-
|
|
22
|
+
}), o = c.replace(/\s+/g, "_").toLowerCase();
|
|
23
|
+
a(i, t || `${o}_board.png`);
|
|
24
|
+
} catch {
|
|
25
|
+
f();
|
|
50
26
|
} finally {
|
|
51
|
-
|
|
27
|
+
u(!1);
|
|
52
28
|
}
|
|
53
29
|
}
|
|
54
30
|
}, [
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
31
|
+
s,
|
|
32
|
+
c,
|
|
33
|
+
l,
|
|
34
|
+
f
|
|
58
35
|
]),
|
|
59
|
-
exportPDF:
|
|
60
|
-
let
|
|
61
|
-
if (!(!
|
|
62
|
-
|
|
36
|
+
exportPDF: t(async () => {
|
|
37
|
+
let t = s.current;
|
|
38
|
+
if (!(!t || l)) {
|
|
39
|
+
u(!0);
|
|
63
40
|
try {
|
|
64
|
-
let
|
|
41
|
+
let n = await e(t), r = n.toDataURL("image/png"), i = `${c} — board`, a = window.open("", "_blank");
|
|
65
42
|
if (!a) {
|
|
66
43
|
window.print();
|
|
67
44
|
return;
|
|
68
45
|
}
|
|
69
|
-
let
|
|
70
|
-
|
|
71
|
-
let l =
|
|
72
|
-
l.textContent = `@page{size:${
|
|
73
|
-
let u =
|
|
74
|
-
u.alt =
|
|
46
|
+
let o = n.width >= n.height ? "landscape" : "portrait", s = a.document;
|
|
47
|
+
s.title = i;
|
|
48
|
+
let l = s.createElement("style");
|
|
49
|
+
l.textContent = `@page{size:${o};margin:12mm}html,body{margin:0;padding:0}img{width:100%;height:auto;display:block}`, s.head.appendChild(l);
|
|
50
|
+
let u = s.createElement("img");
|
|
51
|
+
u.alt = i, u.addEventListener("load", () => {
|
|
75
52
|
a.focus(), a.print();
|
|
76
|
-
}), u.src =
|
|
53
|
+
}), u.src = r, s.body.appendChild(u);
|
|
54
|
+
} catch {
|
|
55
|
+
f();
|
|
77
56
|
} finally {
|
|
78
|
-
|
|
57
|
+
u(!1);
|
|
79
58
|
}
|
|
80
59
|
}
|
|
81
60
|
}, [
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
61
|
+
s,
|
|
62
|
+
c,
|
|
63
|
+
l,
|
|
64
|
+
f
|
|
85
65
|
]),
|
|
86
|
-
isExporting:
|
|
66
|
+
isExporting: l
|
|
87
67
|
};
|
|
88
68
|
}
|
|
89
69
|
//#endregion
|
|
90
|
-
export {
|
|
70
|
+
export { o as default, o as useDashboardImageExport };
|
|
@@ -1,75 +1,61 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { elementToCanvas as e } from "../utils/elementToCanvas.js";
|
|
2
|
+
import { useCallback as t, useRef as n } from "react";
|
|
3
|
+
import { useI18n as r } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
4
|
+
import { toast as i } from "sonner";
|
|
2
5
|
//#region src/bigconsole/hooks/useWidgetExport.ts
|
|
3
|
-
function
|
|
6
|
+
function a(e) {
|
|
4
7
|
if (!e.length) return "";
|
|
5
8
|
let t = Object.keys(e[0]), n = [];
|
|
6
|
-
n.push(t.map(
|
|
7
|
-
for (let
|
|
9
|
+
n.push(t.map(o).join(","));
|
|
10
|
+
for (let r of e) {
|
|
8
11
|
let e = t.map((e) => {
|
|
9
|
-
let t =
|
|
10
|
-
return
|
|
12
|
+
let t = r[e];
|
|
13
|
+
return o(t);
|
|
11
14
|
});
|
|
12
15
|
n.push(e.join(","));
|
|
13
16
|
}
|
|
14
17
|
return n.join("\n");
|
|
15
18
|
}
|
|
16
|
-
function
|
|
19
|
+
function o(e) {
|
|
17
20
|
if (e == null) return "";
|
|
18
21
|
let t = String(e);
|
|
19
22
|
return t.includes(",") || t.includes("\"") || t.includes("\n") || t.includes("\r") ? `"${t.replace(/"/g, "\"\"")}"` : t;
|
|
20
23
|
}
|
|
21
|
-
function
|
|
24
|
+
function s(e, t, n) {
|
|
22
25
|
let r = e instanceof Blob ? e : new Blob([e], { type: n }), i = URL.createObjectURL(r), a = document.createElement("a");
|
|
23
26
|
a.href = i, a.download = t, document.body.appendChild(a), a.click(), document.body.removeChild(a), setTimeout(() => URL.revokeObjectURL(i), 100);
|
|
24
27
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
backgroundColor: null,
|
|
28
|
-
scale: 2,
|
|
29
|
-
logging: !1,
|
|
30
|
-
useCORS: !0
|
|
31
|
-
});
|
|
32
|
-
let t = document.createElement("canvas"), n = t.getContext("2d");
|
|
33
|
-
if (!n) throw Error("Could not get canvas context");
|
|
34
|
-
let r = e.getBoundingClientRect();
|
|
35
|
-
t.width = r.width * 2, t.height = r.height * 2, n.scale(2, 2);
|
|
36
|
-
let i = e.querySelectorAll("svg");
|
|
37
|
-
if (i.length > 0) for (let e of i) {
|
|
38
|
-
let t = new XMLSerializer().serializeToString(e), i = new Blob([t], { type: "image/svg+xml;charset=utf-8" }), a = URL.createObjectURL(i), o = new Image();
|
|
39
|
-
await new Promise((t, i) => {
|
|
40
|
-
o.onload = () => {
|
|
41
|
-
let i = e.getBoundingClientRect(), s = i.left - r.left, c = i.top - r.top;
|
|
42
|
-
n.drawImage(o, s, c), URL.revokeObjectURL(a), t();
|
|
43
|
-
}, o.onerror = i, o.src = a;
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
return n.globalCompositeOperation = "destination-over", n.fillStyle = getComputedStyle(e).backgroundColor || "#ffffff", n.fillRect(0, 0, t.width / 2, t.height / 2), t;
|
|
47
|
-
}
|
|
48
|
-
function o(r, o = {}) {
|
|
49
|
-
let { data: s, containerRef: c } = o, l = t(!1);
|
|
28
|
+
function c(o, c = {}) {
|
|
29
|
+
let { data: l, containerRef: u } = c, d = n(!1), { t: f } = r();
|
|
50
30
|
return {
|
|
51
|
-
exportCSV:
|
|
52
|
-
if (!
|
|
53
|
-
let t =
|
|
54
|
-
|
|
55
|
-
}, [
|
|
56
|
-
exportPNG:
|
|
57
|
-
if (
|
|
58
|
-
|
|
31
|
+
exportCSV: t((e) => {
|
|
32
|
+
if (!l?.length) return;
|
|
33
|
+
let t = a(l), n = `${o.title.replace(/\s+/g, "_").toLowerCase()}_${Date.now()}.csv`;
|
|
34
|
+
s(t, e || n, "text/csv;charset=utf-8");
|
|
35
|
+
}, [l, o.title]),
|
|
36
|
+
exportPNG: t(async (t) => {
|
|
37
|
+
if (u?.current && !d.current) {
|
|
38
|
+
d.current = !0;
|
|
59
39
|
try {
|
|
60
|
-
let
|
|
61
|
-
|
|
62
|
-
|
|
40
|
+
let n = await e(u.current), r = await new Promise((e, t) => {
|
|
41
|
+
n.toBlob((n) => {
|
|
42
|
+
n ? e(n) : t(/* @__PURE__ */ Error("Failed to create image blob"));
|
|
63
43
|
}, "image/png");
|
|
64
|
-
}),
|
|
65
|
-
|
|
66
|
-
} catch {
|
|
67
|
-
|
|
44
|
+
}), i = `${o.title.replace(/\s+/g, "_").toLowerCase()}_${Date.now()}.png`;
|
|
45
|
+
s(r, t || i, "image/png");
|
|
46
|
+
} catch {
|
|
47
|
+
i.error(f("bigconsole.widget.export.failed", "Could not export the widget image. Please try again."));
|
|
48
|
+
} finally {
|
|
49
|
+
d.current = !1;
|
|
68
50
|
}
|
|
69
51
|
}
|
|
70
|
-
}, [
|
|
71
|
-
|
|
52
|
+
}, [
|
|
53
|
+
u,
|
|
54
|
+
o.title,
|
|
55
|
+
f
|
|
56
|
+
]),
|
|
57
|
+
isExporting: d.current
|
|
72
58
|
};
|
|
73
59
|
}
|
|
74
60
|
//#endregion
|
|
75
|
-
export {
|
|
61
|
+
export { c as default, c as useWidgetExport };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Export resolution multiplier, so text stays sharp when the image is zoomed or printed. */
|
|
2
|
+
export declare const EXPORT_PIXEL_RATIO = 2;
|
|
3
|
+
/**
|
|
4
|
+
* A concrete background fill for the export. Prefers the element's own computed
|
|
5
|
+
* background, then the resolved `--color-bg-surface` theme token, then none (a
|
|
6
|
+
* transparent image), so no colour literal is needed.
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveExportBackground(element: HTMLElement): string | undefined;
|
|
9
|
+
export declare function elementToCanvas(element: HTMLElement): Promise<HTMLCanvasElement>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { toCanvas as e } from "../../node_modules/html-to-image/es/index.js";
|
|
2
|
+
//#region src/bigconsole/utils/elementToCanvas.ts
|
|
3
|
+
var t = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
|
|
4
|
+
function n(e) {
|
|
5
|
+
let t = getComputedStyle(e).backgroundColor;
|
|
6
|
+
return !t || t === "transparent" || /,\s*0\)\s*$/.test(t) ? getComputedStyle(document.documentElement).getPropertyValue("--color-bg-surface").trim() || void 0 : t;
|
|
7
|
+
}
|
|
8
|
+
async function r(r) {
|
|
9
|
+
return e(r, {
|
|
10
|
+
pixelRatio: 2,
|
|
11
|
+
backgroundColor: n(r),
|
|
12
|
+
imagePlaceholder: t
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { r as elementToCanvas, n as resolveExportBackground };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region node_modules/html-to-image/es/apply-style.js
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
let { style: n } = e;
|
|
4
|
+
t.backgroundColor && (n.backgroundColor = t.backgroundColor), t.width && (n.width = `${t.width}px`), t.height && (n.height = `${t.height}px`);
|
|
5
|
+
let r = t.style;
|
|
6
|
+
return r != null && Object.keys(r).forEach((e) => {
|
|
7
|
+
n[e] = r[e];
|
|
8
|
+
}), e;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { e as applyStyle };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createImage as e, getStyleProperties as t, isInstanceOfElement as n, toArray as r } from "./util.js";
|
|
2
|
+
import { clonePseudoElements as i } from "./clone-pseudos.js";
|
|
3
|
+
import { getMimeType as a } from "./mimes.js";
|
|
4
|
+
import { resourceToDataURL as o } from "./dataurl.js";
|
|
5
|
+
//#region node_modules/html-to-image/es/clone-node.js
|
|
6
|
+
async function s(t) {
|
|
7
|
+
let n = t.toDataURL();
|
|
8
|
+
return n === "data:," ? t.cloneNode(!1) : e(n);
|
|
9
|
+
}
|
|
10
|
+
async function c(t, n) {
|
|
11
|
+
if (t.currentSrc) {
|
|
12
|
+
let n = document.createElement("canvas"), r = n.getContext("2d");
|
|
13
|
+
return n.width = t.clientWidth, n.height = t.clientHeight, r?.drawImage(t, 0, 0, n.width, n.height), e(n.toDataURL());
|
|
14
|
+
}
|
|
15
|
+
let r = t.poster;
|
|
16
|
+
return e(await o(r, a(r), n));
|
|
17
|
+
}
|
|
18
|
+
async function l(e, t) {
|
|
19
|
+
try {
|
|
20
|
+
if (e?.contentDocument?.body) return await y(e.contentDocument.body, t, !0);
|
|
21
|
+
} catch {}
|
|
22
|
+
return e.cloneNode(!1);
|
|
23
|
+
}
|
|
24
|
+
async function u(e, t) {
|
|
25
|
+
return n(e, HTMLCanvasElement) ? s(e) : n(e, HTMLVideoElement) ? c(e, t) : n(e, HTMLIFrameElement) ? l(e, t) : e.cloneNode(f(e));
|
|
26
|
+
}
|
|
27
|
+
var d = (e) => e.tagName != null && e.tagName.toUpperCase() === "SLOT", f = (e) => e.tagName != null && e.tagName.toUpperCase() === "SVG";
|
|
28
|
+
async function p(e, t, i) {
|
|
29
|
+
if (f(t)) return t;
|
|
30
|
+
let a = [];
|
|
31
|
+
return a = d(e) && e.assignedNodes ? r(e.assignedNodes()) : n(e, HTMLIFrameElement) && e.contentDocument?.body ? r(e.contentDocument.body.childNodes) : r((e.shadowRoot ?? e).childNodes), a.length === 0 || n(e, HTMLVideoElement) || await a.reduce((e, n) => e.then(() => y(n, i)).then((e) => {
|
|
32
|
+
e && t.appendChild(e);
|
|
33
|
+
}), Promise.resolve()), t;
|
|
34
|
+
}
|
|
35
|
+
function m(e, r, i) {
|
|
36
|
+
let a = r.style;
|
|
37
|
+
if (!a) return;
|
|
38
|
+
let o = window.getComputedStyle(e);
|
|
39
|
+
o.cssText ? (a.cssText = o.cssText, a.transformOrigin = o.transformOrigin) : t(i).forEach((t) => {
|
|
40
|
+
let i = o.getPropertyValue(t);
|
|
41
|
+
t === "font-size" && i.endsWith("px") && (i = `${Math.floor(parseFloat(i.substring(0, i.length - 2))) - .1}px`), n(e, HTMLIFrameElement) && t === "display" && i === "inline" && (i = "block"), t === "d" && r.getAttribute("d") && (i = `path(${r.getAttribute("d")})`), a.setProperty(t, i, o.getPropertyPriority(t));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function h(e, t) {
|
|
45
|
+
n(e, HTMLTextAreaElement) && (t.innerHTML = e.value), n(e, HTMLInputElement) && t.setAttribute("value", e.value);
|
|
46
|
+
}
|
|
47
|
+
function g(e, t) {
|
|
48
|
+
if (n(e, HTMLSelectElement)) {
|
|
49
|
+
let n = t, r = Array.from(n.children).find((t) => e.value === t.getAttribute("value"));
|
|
50
|
+
r && r.setAttribute("selected", "");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function _(e, t, r) {
|
|
54
|
+
return n(t, Element) && (m(e, t, r), i(e, t, r), h(e, t), g(e, t)), t;
|
|
55
|
+
}
|
|
56
|
+
async function v(e, t) {
|
|
57
|
+
let n = e.querySelectorAll ? e.querySelectorAll("use") : [];
|
|
58
|
+
if (n.length === 0) return e;
|
|
59
|
+
let r = {};
|
|
60
|
+
for (let i = 0; i < n.length; i++) {
|
|
61
|
+
let a = n[i].getAttribute("xlink:href");
|
|
62
|
+
if (a) {
|
|
63
|
+
let n = e.querySelector(a), i = document.querySelector(a);
|
|
64
|
+
!n && i && !r[a] && (r[a] = await y(i, t, !0));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
let i = Object.values(r);
|
|
68
|
+
if (i.length) {
|
|
69
|
+
let t = "http://www.w3.org/1999/xhtml", n = document.createElementNS(t, "svg");
|
|
70
|
+
n.setAttribute("xmlns", t), n.style.position = "absolute", n.style.width = "0", n.style.height = "0", n.style.overflow = "hidden", n.style.display = "none";
|
|
71
|
+
let r = document.createElementNS(t, "defs");
|
|
72
|
+
n.appendChild(r);
|
|
73
|
+
for (let e = 0; e < i.length; e++) r.appendChild(i[e]);
|
|
74
|
+
e.appendChild(n);
|
|
75
|
+
}
|
|
76
|
+
return e;
|
|
77
|
+
}
|
|
78
|
+
async function y(e, t, n) {
|
|
79
|
+
return !n && t.filter && !t.filter(e) ? null : Promise.resolve(e).then((e) => u(e, t)).then((n) => p(e, n, t)).then((n) => _(e, n, t)).then((e) => v(e, t));
|
|
80
|
+
}
|
|
81
|
+
//#endregion
|
|
82
|
+
export { y as cloneNode };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getStyleProperties as e, uuid as t } from "./util.js";
|
|
2
|
+
//#region node_modules/html-to-image/es/clone-pseudos.js
|
|
3
|
+
function n(e) {
|
|
4
|
+
let t = e.getPropertyValue("content");
|
|
5
|
+
return `${e.cssText} content: '${t.replace(/'|"/g, "")}';`;
|
|
6
|
+
}
|
|
7
|
+
function r(t, n) {
|
|
8
|
+
return e(n).map((e) => `${e}: ${t.getPropertyValue(e)}${t.getPropertyPriority(e) ? " !important" : ""};`).join(" ");
|
|
9
|
+
}
|
|
10
|
+
function i(e, t, i, a) {
|
|
11
|
+
let o = `.${e}:${t}`, s = i.cssText ? n(i) : r(i, a);
|
|
12
|
+
return document.createTextNode(`${o}{${s}}`);
|
|
13
|
+
}
|
|
14
|
+
function a(e, n, r, a) {
|
|
15
|
+
let o = window.getComputedStyle(e, r), s = o.getPropertyValue("content");
|
|
16
|
+
if (s === "" || s === "none") return;
|
|
17
|
+
let c = t();
|
|
18
|
+
try {
|
|
19
|
+
n.className = `${n.className} ${c}`;
|
|
20
|
+
} catch {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
let l = document.createElement("style");
|
|
24
|
+
l.appendChild(i(c, r, o, a)), n.appendChild(l);
|
|
25
|
+
}
|
|
26
|
+
function o(e, t, n) {
|
|
27
|
+
a(e, t, ":before", n), a(e, t, ":after", n);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { o as clonePseudoElements };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//#region node_modules/html-to-image/es/dataurl.js
|
|
2
|
+
function e(e) {
|
|
3
|
+
return e.split(/,/)[1];
|
|
4
|
+
}
|
|
5
|
+
function t(e) {
|
|
6
|
+
return e.search(/^(data:)/) !== -1;
|
|
7
|
+
}
|
|
8
|
+
function n(e, t) {
|
|
9
|
+
return `data:${t};base64,${e}`;
|
|
10
|
+
}
|
|
11
|
+
async function r(e, t, n) {
|
|
12
|
+
let r = await fetch(e, t);
|
|
13
|
+
if (r.status === 404) throw Error(`Resource "${r.url}" not found`);
|
|
14
|
+
let i = await r.blob();
|
|
15
|
+
return new Promise((e, t) => {
|
|
16
|
+
let a = new FileReader();
|
|
17
|
+
a.onerror = t, a.onloadend = () => {
|
|
18
|
+
try {
|
|
19
|
+
e(n({
|
|
20
|
+
res: r,
|
|
21
|
+
result: a.result
|
|
22
|
+
}));
|
|
23
|
+
} catch (e) {
|
|
24
|
+
t(e);
|
|
25
|
+
}
|
|
26
|
+
}, a.readAsDataURL(i);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
var i = {};
|
|
30
|
+
function a(e, t, n) {
|
|
31
|
+
let r = e.replace(/\?.*/, "");
|
|
32
|
+
return n && (r = e), /ttf|otf|eot|woff2?/i.test(r) && (r = r.replace(/.*\//, "")), t ? `[${t}]${r}` : r;
|
|
33
|
+
}
|
|
34
|
+
async function o(t, o, s) {
|
|
35
|
+
let c = a(t, o, s.includeQueryParams);
|
|
36
|
+
if (i[c] != null) return i[c];
|
|
37
|
+
s.cacheBust && (t += (/\?/.test(t) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime());
|
|
38
|
+
let l;
|
|
39
|
+
try {
|
|
40
|
+
l = n(await r(t, s.fetchRequestInit, ({ res: t, result: n }) => (o ||= t.headers.get("Content-Type") || "", e(n))), o);
|
|
41
|
+
} catch (e) {
|
|
42
|
+
l = s.imagePlaceholder || "";
|
|
43
|
+
let n = `Failed to fetch resource: ${t}`;
|
|
44
|
+
e && (n = typeof e == "string" ? e : e.message), n && console.warn(n);
|
|
45
|
+
}
|
|
46
|
+
return i[c] = l, l;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { r as fetchAsDataURL, t as isDataUrl, n as makeDataUrl, o as resourceToDataURL };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isInstanceOfElement as e, toArray as t } from "./util.js";
|
|
2
|
+
import { getMimeType as n } from "./mimes.js";
|
|
3
|
+
import { isDataUrl as r, resourceToDataURL as i } from "./dataurl.js";
|
|
4
|
+
import { embedResources as a } from "./embed-resources.js";
|
|
5
|
+
//#region node_modules/html-to-image/es/embed-images.js
|
|
6
|
+
async function o(e, t, n) {
|
|
7
|
+
let r = t.style?.getPropertyValue(e);
|
|
8
|
+
if (r) {
|
|
9
|
+
let i = await a(r, null, n);
|
|
10
|
+
return t.style.setProperty(e, i, t.style.getPropertyPriority(e)), !0;
|
|
11
|
+
}
|
|
12
|
+
return !1;
|
|
13
|
+
}
|
|
14
|
+
async function s(e, t) {
|
|
15
|
+
await o("background", e, t) || await o("background-image", e, t), await o("mask", e, t) || await o("-webkit-mask", e, t) || await o("mask-image", e, t) || await o("-webkit-mask-image", e, t);
|
|
16
|
+
}
|
|
17
|
+
async function c(t, a) {
|
|
18
|
+
let o = e(t, HTMLImageElement);
|
|
19
|
+
if (!(o && !r(t.src)) && !(e(t, SVGImageElement) && !r(t.href.baseVal))) return;
|
|
20
|
+
let s = o ? t.src : t.href.baseVal, c = await i(s, n(s), a);
|
|
21
|
+
await new Promise((e, n) => {
|
|
22
|
+
t.onload = e, t.onerror = a.onImageErrorHandler ? (...t) => {
|
|
23
|
+
try {
|
|
24
|
+
e(a.onImageErrorHandler(...t));
|
|
25
|
+
} catch (e) {
|
|
26
|
+
n(e);
|
|
27
|
+
}
|
|
28
|
+
} : n;
|
|
29
|
+
let r = t;
|
|
30
|
+
r.decode &&= e, r.loading === "lazy" && (r.loading = "eager"), o ? (t.srcset = "", t.src = c) : t.href.baseVal = c;
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async function l(e, n) {
|
|
34
|
+
let r = t(e.childNodes).map((e) => u(e, n));
|
|
35
|
+
await Promise.all(r).then(() => e);
|
|
36
|
+
}
|
|
37
|
+
async function u(t, n) {
|
|
38
|
+
e(t, Element) && (await s(t, n), await c(t, n), await l(t, n));
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { u as embedImages };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { resolveUrl as e } from "./util.js";
|
|
2
|
+
import { getMimeType as t } from "./mimes.js";
|
|
3
|
+
import { isDataUrl as n, makeDataUrl as r, resourceToDataURL as i } from "./dataurl.js";
|
|
4
|
+
//#region node_modules/html-to-image/es/embed-resources.js
|
|
5
|
+
var a = /url\((['"]?)([^'"]+?)\1\)/g, o = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g, s = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
|
|
6
|
+
function c(e) {
|
|
7
|
+
let t = e.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
|
|
8
|
+
return RegExp(`(url\\(['"]?)(${t})(['"]?\\))`, "g");
|
|
9
|
+
}
|
|
10
|
+
function l(e) {
|
|
11
|
+
let t = [];
|
|
12
|
+
return e.replace(a, (e, n, r) => (t.push(r), e)), t.filter((e) => !n(e));
|
|
13
|
+
}
|
|
14
|
+
async function u(n, a, o, s, l) {
|
|
15
|
+
try {
|
|
16
|
+
let u = o ? e(a, o) : a, d = t(a), f;
|
|
17
|
+
return f = l ? r(await l(u), d) : await i(u, d, s), n.replace(c(a), `$1${f}$3`);
|
|
18
|
+
} catch {}
|
|
19
|
+
return n;
|
|
20
|
+
}
|
|
21
|
+
function d(e, { preferredFontFormat: t }) {
|
|
22
|
+
return t ? e.replace(s, (e) => {
|
|
23
|
+
for (;;) {
|
|
24
|
+
let [n, , r] = o.exec(e) || [];
|
|
25
|
+
if (!r) return "";
|
|
26
|
+
if (r === t) return `src: ${n};`;
|
|
27
|
+
}
|
|
28
|
+
}) : e;
|
|
29
|
+
}
|
|
30
|
+
function f(e) {
|
|
31
|
+
return e.search(a) !== -1;
|
|
32
|
+
}
|
|
33
|
+
async function p(e, t, n) {
|
|
34
|
+
if (!f(e)) return e;
|
|
35
|
+
let r = d(e, n);
|
|
36
|
+
return l(r).reduce((e, r) => e.then((e) => u(e, r, t, n)), Promise.resolve(r));
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { u as embed, p as embedResources, l as parseURLs, f as shouldEmbed };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { toArray as e } from "./util.js";
|
|
2
|
+
import { fetchAsDataURL as t } from "./dataurl.js";
|
|
3
|
+
import { embedResources as n, shouldEmbed as r } from "./embed-resources.js";
|
|
4
|
+
//#region node_modules/html-to-image/es/embed-webfonts.js
|
|
5
|
+
var i = {};
|
|
6
|
+
async function a(e) {
|
|
7
|
+
let t = i[e];
|
|
8
|
+
return t ?? (t = {
|
|
9
|
+
url: e,
|
|
10
|
+
cssText: await (await fetch(e)).text()
|
|
11
|
+
}, i[e] = t, t);
|
|
12
|
+
}
|
|
13
|
+
async function o(e, n) {
|
|
14
|
+
let r = e.cssText, i = /url\(["']?([^"')]+)["']?\)/g, a = (r.match(/url\([^)]+\)/g) || []).map(async (a) => {
|
|
15
|
+
let o = a.replace(i, "$1");
|
|
16
|
+
return o.startsWith("https://") || (o = new URL(o, e.url).href), t(o, n.fetchRequestInit, ({ result: e }) => (r = r.replace(a, `url(${e})`), [a, e]));
|
|
17
|
+
});
|
|
18
|
+
return Promise.all(a).then(() => r);
|
|
19
|
+
}
|
|
20
|
+
function s(e) {
|
|
21
|
+
if (e == null) return [];
|
|
22
|
+
let t = [], n = e.replace(/(\/\*[\s\S]*?\*\/)/gi, ""), r = /* @__PURE__ */ RegExp("((@.*?keyframes [\\s\\S]*?){([\\s\\S]*?}\\s*?)})", "gi");
|
|
23
|
+
for (;;) {
|
|
24
|
+
let e = r.exec(n);
|
|
25
|
+
if (e === null) break;
|
|
26
|
+
t.push(e[0]);
|
|
27
|
+
}
|
|
28
|
+
n = n.replace(r, "");
|
|
29
|
+
let i = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi, a = /* @__PURE__ */ RegExp("((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})", "gi");
|
|
30
|
+
for (;;) {
|
|
31
|
+
let e = i.exec(n);
|
|
32
|
+
if (e === null) {
|
|
33
|
+
if (e = a.exec(n), e === null) break;
|
|
34
|
+
i.lastIndex = a.lastIndex;
|
|
35
|
+
} else a.lastIndex = i.lastIndex;
|
|
36
|
+
t.push(e[0]);
|
|
37
|
+
}
|
|
38
|
+
return t;
|
|
39
|
+
}
|
|
40
|
+
async function c(t, n) {
|
|
41
|
+
let r = [], i = [];
|
|
42
|
+
return t.forEach((r) => {
|
|
43
|
+
if ("cssRules" in r) try {
|
|
44
|
+
e(r.cssRules || []).forEach((e, t) => {
|
|
45
|
+
if (e.type === CSSRule.IMPORT_RULE) {
|
|
46
|
+
let c = t + 1, l = e.href, u = a(l).then((e) => o(e, n)).then((e) => s(e).forEach((e) => {
|
|
47
|
+
try {
|
|
48
|
+
r.insertRule(e, e.startsWith("@import") ? c += 1 : r.cssRules.length);
|
|
49
|
+
} catch (t) {
|
|
50
|
+
console.error("Error inserting rule from remote css", {
|
|
51
|
+
rule: e,
|
|
52
|
+
error: t
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
})).catch((e) => {
|
|
56
|
+
console.error("Error loading remote css", e.toString());
|
|
57
|
+
});
|
|
58
|
+
i.push(u);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
} catch (e) {
|
|
62
|
+
let c = t.find((e) => e.href == null) || document.styleSheets[0];
|
|
63
|
+
r.href != null && i.push(a(r.href).then((e) => o(e, n)).then((e) => s(e).forEach((e) => {
|
|
64
|
+
c.insertRule(e, c.cssRules.length);
|
|
65
|
+
})).catch((e) => {
|
|
66
|
+
console.error("Error loading remote stylesheet", e);
|
|
67
|
+
})), console.error("Error inlining remote css file", e);
|
|
68
|
+
}
|
|
69
|
+
}), Promise.all(i).then(() => (t.forEach((t) => {
|
|
70
|
+
if ("cssRules" in t) try {
|
|
71
|
+
e(t.cssRules || []).forEach((e) => {
|
|
72
|
+
r.push(e);
|
|
73
|
+
});
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.error(`Error while reading CSS rules from ${t.href}`, e);
|
|
76
|
+
}
|
|
77
|
+
}), r));
|
|
78
|
+
}
|
|
79
|
+
function l(e) {
|
|
80
|
+
return e.filter((e) => e.type === CSSRule.FONT_FACE_RULE).filter((e) => r(e.style.getPropertyValue("src")));
|
|
81
|
+
}
|
|
82
|
+
async function u(t, n) {
|
|
83
|
+
if (t.ownerDocument == null) throw Error("Provided element is not within a Document");
|
|
84
|
+
return l(await c(e(t.ownerDocument.styleSheets), n));
|
|
85
|
+
}
|
|
86
|
+
function d(e) {
|
|
87
|
+
return e.trim().replace(/["']/g, "");
|
|
88
|
+
}
|
|
89
|
+
function f(e) {
|
|
90
|
+
let t = /* @__PURE__ */ new Set();
|
|
91
|
+
function n(e) {
|
|
92
|
+
(e.style.fontFamily || getComputedStyle(e).fontFamily).split(",").forEach((e) => {
|
|
93
|
+
t.add(d(e));
|
|
94
|
+
}), Array.from(e.children).forEach((e) => {
|
|
95
|
+
e instanceof HTMLElement && n(e);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return n(e), t;
|
|
99
|
+
}
|
|
100
|
+
async function p(e, t) {
|
|
101
|
+
let r = await u(e, t), i = f(e);
|
|
102
|
+
return (await Promise.all(r.filter((e) => i.has(d(e.style.fontFamily))).map((e) => {
|
|
103
|
+
let r = e.parentStyleSheet ? e.parentStyleSheet.href : null;
|
|
104
|
+
return n(e.cssText, r, t);
|
|
105
|
+
}))).join("\n");
|
|
106
|
+
}
|
|
107
|
+
async function m(e, t) {
|
|
108
|
+
let n = t.fontEmbedCSS == null ? t.skipFonts ? null : await p(e, t) : t.fontEmbedCSS;
|
|
109
|
+
if (n) {
|
|
110
|
+
let t = document.createElement("style"), r = document.createTextNode(n);
|
|
111
|
+
t.appendChild(r), e.firstChild ? e.insertBefore(t, e.firstChild) : e.appendChild(t);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { m as embedWebFonts, p as getWebFontCSS };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { checkCanvasDimensions as e, createImage as t, getImageSize as n, getPixelRatio as r, nodeToDataURL as i } from "./util.js";
|
|
2
|
+
import { cloneNode as a } from "./clone-node.js";
|
|
3
|
+
import { embedImages as o } from "./embed-images.js";
|
|
4
|
+
import { applyStyle as s } from "./apply-style.js";
|
|
5
|
+
import { embedWebFonts as c } from "./embed-webfonts.js";
|
|
6
|
+
//#region node_modules/html-to-image/es/index.js
|
|
7
|
+
async function l(e, t = {}) {
|
|
8
|
+
let { width: r, height: l } = n(e, t), u = await a(e, t, !0);
|
|
9
|
+
return await c(u, t), await o(u, t), s(u, t), await i(u, r, l);
|
|
10
|
+
}
|
|
11
|
+
async function u(i, a = {}) {
|
|
12
|
+
let { width: o, height: s } = n(i, a), c = await t(await l(i, a)), u = document.createElement("canvas"), d = u.getContext("2d"), f = a.pixelRatio || r(), p = a.canvasWidth || o, m = a.canvasHeight || s;
|
|
13
|
+
return u.width = p * f, u.height = m * f, a.skipAutoScale || e(u), u.style.width = `${p}`, u.style.height = `${m}`, a.backgroundColor && (d.fillStyle = a.backgroundColor, d.fillRect(0, 0, u.width, u.height)), d.drawImage(c, 0, 0, u.width, u.height), u;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { u as toCanvas, l as toSvg };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region node_modules/html-to-image/es/mimes.js
|
|
2
|
+
var e = "application/font-woff", t = "image/jpeg", n = {
|
|
3
|
+
woff: e,
|
|
4
|
+
woff2: e,
|
|
5
|
+
ttf: "application/font-truetype",
|
|
6
|
+
eot: "application/vnd.ms-fontobject",
|
|
7
|
+
png: "image/png",
|
|
8
|
+
jpg: t,
|
|
9
|
+
jpeg: t,
|
|
10
|
+
gif: "image/gif",
|
|
11
|
+
tiff: "image/tiff",
|
|
12
|
+
svg: "image/svg+xml",
|
|
13
|
+
webp: "image/webp"
|
|
14
|
+
};
|
|
15
|
+
function r(e) {
|
|
16
|
+
let t = /\.([^./]*?)$/g.exec(e);
|
|
17
|
+
return t ? t[1] : "";
|
|
18
|
+
}
|
|
19
|
+
function i(e) {
|
|
20
|
+
return n[r(e).toLowerCase()] || "";
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { i as getMimeType };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//#region node_modules/html-to-image/es/util.js
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
if (e.match(/^[a-z]+:\/\//i)) return e;
|
|
4
|
+
if (e.match(/^\/\//)) return window.location.protocol + e;
|
|
5
|
+
if (e.match(/^[a-z]+:/i)) return e;
|
|
6
|
+
let n = document.implementation.createHTMLDocument(), r = n.createElement("base"), i = n.createElement("a");
|
|
7
|
+
return n.head.appendChild(r), n.body.appendChild(i), t && (r.href = t), i.href = e, i.href;
|
|
8
|
+
}
|
|
9
|
+
var t = (() => {
|
|
10
|
+
let e = 0, t = () => `0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4);
|
|
11
|
+
return () => (e += 1, `u${t()}${e}`);
|
|
12
|
+
})();
|
|
13
|
+
function n(e) {
|
|
14
|
+
let t = [];
|
|
15
|
+
for (let n = 0, r = e.length; n < r; n++) t.push(e[n]);
|
|
16
|
+
return t;
|
|
17
|
+
}
|
|
18
|
+
var r = null;
|
|
19
|
+
function i(e = {}) {
|
|
20
|
+
return r || (e.includeStyleProperties ? (r = e.includeStyleProperties, r) : (r = n(window.getComputedStyle(document.documentElement)), r));
|
|
21
|
+
}
|
|
22
|
+
function a(e, t) {
|
|
23
|
+
let n = (e.ownerDocument.defaultView || window).getComputedStyle(e).getPropertyValue(t);
|
|
24
|
+
return n ? parseFloat(n.replace("px", "")) : 0;
|
|
25
|
+
}
|
|
26
|
+
function o(e) {
|
|
27
|
+
let t = a(e, "border-left-width"), n = a(e, "border-right-width");
|
|
28
|
+
return e.clientWidth + t + n;
|
|
29
|
+
}
|
|
30
|
+
function s(e) {
|
|
31
|
+
let t = a(e, "border-top-width"), n = a(e, "border-bottom-width");
|
|
32
|
+
return e.clientHeight + t + n;
|
|
33
|
+
}
|
|
34
|
+
function c(e, t = {}) {
|
|
35
|
+
return {
|
|
36
|
+
width: t.width || o(e),
|
|
37
|
+
height: t.height || s(e)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function l() {
|
|
41
|
+
let e, t;
|
|
42
|
+
try {
|
|
43
|
+
t = process;
|
|
44
|
+
} catch {}
|
|
45
|
+
let n = t && t.env ? t.env.devicePixelRatio : null;
|
|
46
|
+
return n && (e = parseInt(n, 10), Number.isNaN(e) && (e = 1)), e || window.devicePixelRatio || 1;
|
|
47
|
+
}
|
|
48
|
+
var u = 16384;
|
|
49
|
+
function d(e) {
|
|
50
|
+
(e.width > u || e.height > u) && (e.width > u && e.height > u ? e.width > e.height ? (e.height *= u / e.width, e.width = u) : (e.width *= u / e.height, e.height = u) : e.width > u ? (e.height *= u / e.width, e.width = u) : (e.width *= u / e.height, e.height = u));
|
|
51
|
+
}
|
|
52
|
+
function f(e) {
|
|
53
|
+
return new Promise((t, n) => {
|
|
54
|
+
let r = new Image();
|
|
55
|
+
r.onload = () => {
|
|
56
|
+
r.decode().then(() => {
|
|
57
|
+
requestAnimationFrame(() => t(r));
|
|
58
|
+
});
|
|
59
|
+
}, r.onerror = n, r.crossOrigin = "anonymous", r.decoding = "async", r.src = e;
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function p(e) {
|
|
63
|
+
return Promise.resolve().then(() => new XMLSerializer().serializeToString(e)).then(encodeURIComponent).then((e) => `data:image/svg+xml;charset=utf-8,${e}`);
|
|
64
|
+
}
|
|
65
|
+
async function m(e, t, n) {
|
|
66
|
+
let r = "http://www.w3.org/2000/svg", i = document.createElementNS(r, "svg"), a = document.createElementNS(r, "foreignObject");
|
|
67
|
+
return i.setAttribute("width", `${t}`), i.setAttribute("height", `${n}`), i.setAttribute("viewBox", `0 0 ${t} ${n}`), a.setAttribute("width", "100%"), a.setAttribute("height", "100%"), a.setAttribute("x", "0"), a.setAttribute("y", "0"), a.setAttribute("externalResourcesRequired", "true"), i.appendChild(a), a.appendChild(e), p(i);
|
|
68
|
+
}
|
|
69
|
+
var h = (e, t) => {
|
|
70
|
+
if (e instanceof t) return !0;
|
|
71
|
+
let n = Object.getPrototypeOf(e);
|
|
72
|
+
return n === null ? !1 : n.constructor.name === t.name || h(n, t);
|
|
73
|
+
};
|
|
74
|
+
//#endregion
|
|
75
|
+
export { d as checkCanvasDimensions, f as createImage, c as getImageSize, l as getPixelRatio, i as getStyleProperties, h as isInstanceOfElement, m as nodeToDataURL, e as resolveUrl, p as svgToDataURL, n as toArray, t as uuid };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@burdenoff/microfe-bigconsole",
|
|
3
|
-
"version": "2026.1103.
|
|
3
|
+
"version": "2026.1103.7",
|
|
4
4
|
"description": "BigConsole - AI-powered analytics and dashboard platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"verify:dependency-mitigations": "bun test tests/dependency-mitigations.test.ts"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"dompurify": "^3.4.17"
|
|
54
|
+
"dompurify": "^3.4.17",
|
|
55
|
+
"html-to-image": "1.11.13"
|
|
55
56
|
},
|
|
56
57
|
"peerDependencies": {
|
|
57
58
|
"@apollo/client": "^4.2.0",
|