issue-sticker 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/README.md +82 -415
- package/dist/NetworkCollector-BlY2qUKF.js +12278 -0
- package/dist/createLucideIcon-B457EluY.js +27415 -0
- package/dist/{index-DN49yZjv.js → index-D6SaRFm4.js} +98 -1
- package/dist/issue-sticker-headless-react.js +764 -0
- package/dist/issue-sticker-headless.js +1914 -0
- package/dist/issue-sticker-react.js +17399 -46756
- package/dist/tooltip-BkQcdrki.js +512 -0
- package/headless-react.d.ts +12 -0
- package/headless.d.ts +172 -0
- package/package.json +26 -26
- package/react.d.ts +29 -2
- package/dist/index.d.ts +0 -37
- package/dist/issue-sticker-runtime.js +0 -37
- package/dist/issue-sticker.js +0 -2105
- package/dist/issue-sticker.umd.js +0 -1
- package/dist/sdkEventListeners-B7idjnFi.js +0 -498
- package/runtime.d.ts +0 -11
package/dist/issue-sticker.js
DELETED
|
@@ -1,2105 +0,0 @@
|
|
|
1
|
-
var _a;
|
|
2
|
-
const SCREENSHOT_DATA_URL_QUALITY = 0.95;
|
|
3
|
-
const CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE = "data-issue-sticker-capture-exclude-node-id";
|
|
4
|
-
const MODERN_STICKY_NODE_ID_ATTRIBUTE = "data-issue-sticker-modern-sticky-node-id";
|
|
5
|
-
const MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE = "data-issue-sticker-modern-scroll-ancestor-id";
|
|
6
|
-
function getCaptureScale() {
|
|
7
|
-
return Math.min(Math.max(window.devicePixelRatio || 1, 2), 3);
|
|
8
|
-
}
|
|
9
|
-
async function waitForDocumentFonts() {
|
|
10
|
-
const fontFaceSet = document.fonts;
|
|
11
|
-
if (!fontFaceSet) {
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
await fontFaceSet.ready;
|
|
15
|
-
}
|
|
16
|
-
function forEachElementDeep(root, callback) {
|
|
17
|
-
if (root instanceof Element) {
|
|
18
|
-
callback(root);
|
|
19
|
-
if (root.shadowRoot) {
|
|
20
|
-
forEachElementDeep(root.shadowRoot, callback);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
Array.from(root.children).forEach((child) => {
|
|
24
|
-
forEachElementDeep(child, callback);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function isScrollableOnAxis(element, axis) {
|
|
28
|
-
const style = getComputedStyle(element);
|
|
29
|
-
const overflowValue = axis === "y" ? style.overflowY || style.overflow : style.overflowX || style.overflow;
|
|
30
|
-
const scrollSize = axis === "y" ? element.scrollHeight - element.clientHeight : element.scrollWidth - element.clientWidth;
|
|
31
|
-
return /(auto|scroll|overlay)/.test(overflowValue) && scrollSize > 1;
|
|
32
|
-
}
|
|
33
|
-
function findNearestScrollableAncestor(element, root) {
|
|
34
|
-
let current = element.parentElement;
|
|
35
|
-
while (current && current !== root) {
|
|
36
|
-
if (isScrollableOnAxis(current, "y") || isScrollableOnAxis(current, "x")) {
|
|
37
|
-
return current;
|
|
38
|
-
}
|
|
39
|
-
current = current.parentElement;
|
|
40
|
-
}
|
|
41
|
-
return isScrollableOnAxis(root, "y") || isScrollableOnAxis(root, "x") ? root : null;
|
|
42
|
-
}
|
|
43
|
-
function parseStickyInset(value) {
|
|
44
|
-
if (!value || value === "auto") {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
const parsed = Number.parseFloat(value);
|
|
48
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
49
|
-
}
|
|
50
|
-
function createExcludeElementSnapshot(root, excludeSelectors) {
|
|
51
|
-
if (excludeSelectors.length === 0) {
|
|
52
|
-
return {
|
|
53
|
-
applyToClone: () => void 0,
|
|
54
|
-
cleanup: () => void 0
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const markedElements = [];
|
|
58
|
-
let nextCaptureId = 0;
|
|
59
|
-
forEachElementDeep(root, (element) => {
|
|
60
|
-
if (!excludeSelectors.some((selector) => element.matches(selector))) {
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
const captureId = String(++nextCaptureId);
|
|
64
|
-
const previousValue = element.getAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE);
|
|
65
|
-
element.setAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE, captureId);
|
|
66
|
-
markedElements.push({ element, previousValue });
|
|
67
|
-
});
|
|
68
|
-
return {
|
|
69
|
-
applyToClone(clonedRoot) {
|
|
70
|
-
forEachElementDeep(clonedRoot, (element) => {
|
|
71
|
-
if (!element.hasAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE)) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const styledElement = element;
|
|
75
|
-
if (styledElement.style) {
|
|
76
|
-
styledElement.style.setProperty("opacity", "0", "important");
|
|
77
|
-
styledElement.style.setProperty("visibility", "hidden", "important");
|
|
78
|
-
styledElement.style.setProperty("pointer-events", "none", "important");
|
|
79
|
-
}
|
|
80
|
-
element.removeAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE);
|
|
81
|
-
});
|
|
82
|
-
},
|
|
83
|
-
cleanup() {
|
|
84
|
-
markedElements.forEach(({ element, previousValue }) => {
|
|
85
|
-
if (previousValue === null) {
|
|
86
|
-
element.removeAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE);
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
element.setAttribute(CAPTURE_EXCLUDE_NODE_ID_ATTRIBUTE, previousValue);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function createModernStickySnapshot(root) {
|
|
95
|
-
const stickyOverlays = /* @__PURE__ */ new Map();
|
|
96
|
-
const markedStickyElements = [];
|
|
97
|
-
const markedScrollAncestors = [];
|
|
98
|
-
let nextStickyId = 0;
|
|
99
|
-
let nextScrollAncestorId = 0;
|
|
100
|
-
function ensureScrollAncestorId(element) {
|
|
101
|
-
const existingId = element.getAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
102
|
-
if (existingId) {
|
|
103
|
-
return existingId;
|
|
104
|
-
}
|
|
105
|
-
const ancestorId = `scroll-${++nextScrollAncestorId}`;
|
|
106
|
-
const previousValue = element.getAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
107
|
-
element.setAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE, ancestorId);
|
|
108
|
-
markedScrollAncestors.push({ element, previousValue });
|
|
109
|
-
return ancestorId;
|
|
110
|
-
}
|
|
111
|
-
forEachElementDeep(root, (node) => {
|
|
112
|
-
if (!(node instanceof HTMLElement)) {
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
const style = getComputedStyle(node);
|
|
116
|
-
if (style.position !== "sticky") {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
const scrollAncestor = findNearestScrollableAncestor(node, root);
|
|
120
|
-
if (!scrollAncestor) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const nodeRect = node.getBoundingClientRect();
|
|
124
|
-
const ancestorRect = scrollAncestor.getBoundingClientRect();
|
|
125
|
-
const currentTop = nodeRect.top - ancestorRect.top - scrollAncestor.clientTop;
|
|
126
|
-
const currentLeft = nodeRect.left - ancestorRect.left - scrollAncestor.clientLeft;
|
|
127
|
-
const topInset = parseStickyInset(style.top);
|
|
128
|
-
const leftInset = parseStickyInset(style.left);
|
|
129
|
-
const isStuckY = topInset !== null && scrollAncestor.scrollTop > 0 && currentTop <= topInset + 0.5;
|
|
130
|
-
const isStuckX = leftInset !== null && scrollAncestor.scrollLeft > 0 && currentLeft <= leftInset + 0.5;
|
|
131
|
-
if (!isStuckX && !isStuckY) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const captureId = String(++nextStickyId);
|
|
135
|
-
const previousValue = node.getAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE);
|
|
136
|
-
const ancestorId = ensureScrollAncestorId(scrollAncestor);
|
|
137
|
-
stickyOverlays.set(captureId, {
|
|
138
|
-
ancestorId,
|
|
139
|
-
top: currentTop,
|
|
140
|
-
left: currentLeft,
|
|
141
|
-
width: nodeRect.width,
|
|
142
|
-
height: nodeRect.height
|
|
143
|
-
});
|
|
144
|
-
node.setAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE, captureId);
|
|
145
|
-
markedStickyElements.push({ element: node, previousValue });
|
|
146
|
-
});
|
|
147
|
-
return {
|
|
148
|
-
applyToClone(clonedRoot) {
|
|
149
|
-
const stickyById = /* @__PURE__ */ new Map();
|
|
150
|
-
const scrollAncestorById = /* @__PURE__ */ new Map();
|
|
151
|
-
forEachElementDeep(clonedRoot, (node) => {
|
|
152
|
-
if (!(node instanceof HTMLElement)) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const captureId = node.getAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE);
|
|
156
|
-
if (captureId) {
|
|
157
|
-
stickyById.set(captureId, node);
|
|
158
|
-
}
|
|
159
|
-
const scrollAncestorId = node.getAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
160
|
-
if (scrollAncestorId) {
|
|
161
|
-
scrollAncestorById.set(scrollAncestorId, node);
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
stickyOverlays.forEach(({ ancestorId, top, left, width, height }, captureId) => {
|
|
165
|
-
const stickyNode = stickyById.get(captureId);
|
|
166
|
-
const scrollAncestor = scrollAncestorById.get(ancestorId);
|
|
167
|
-
if (!stickyNode || !scrollAncestor) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
const overlay = stickyNode.cloneNode(true);
|
|
171
|
-
if (!(overlay instanceof HTMLElement)) {
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
overlay.removeAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE);
|
|
175
|
-
overlay.removeAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
176
|
-
overlay.style.position = "absolute";
|
|
177
|
-
overlay.style.top = `${top}px`;
|
|
178
|
-
overlay.style.left = `${left}px`;
|
|
179
|
-
overlay.style.width = `${width}px`;
|
|
180
|
-
overlay.style.height = `${height}px`;
|
|
181
|
-
overlay.style.margin = "0";
|
|
182
|
-
overlay.style.transform = "none";
|
|
183
|
-
overlay.style.pointerEvents = "none";
|
|
184
|
-
overlay.style.right = "auto";
|
|
185
|
-
overlay.style.bottom = "auto";
|
|
186
|
-
if (!overlay.style.zIndex || overlay.style.zIndex === "auto") {
|
|
187
|
-
overlay.style.zIndex = "1";
|
|
188
|
-
}
|
|
189
|
-
if (!scrollAncestor.style.position || scrollAncestor.style.position === "static") {
|
|
190
|
-
scrollAncestor.style.position = "relative";
|
|
191
|
-
}
|
|
192
|
-
stickyNode.style.visibility = "hidden";
|
|
193
|
-
stickyNode.style.pointerEvents = "none";
|
|
194
|
-
stickyNode.style.transform = "none";
|
|
195
|
-
scrollAncestor.appendChild(overlay);
|
|
196
|
-
});
|
|
197
|
-
forEachElementDeep(clonedRoot, (node) => {
|
|
198
|
-
if (!(node instanceof HTMLElement)) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
node.removeAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE);
|
|
202
|
-
node.removeAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
203
|
-
});
|
|
204
|
-
},
|
|
205
|
-
cleanup() {
|
|
206
|
-
markedStickyElements.forEach(({ element, previousValue }) => {
|
|
207
|
-
if (previousValue === null) {
|
|
208
|
-
element.removeAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE);
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
element.setAttribute(MODERN_STICKY_NODE_ID_ATTRIBUTE, previousValue);
|
|
212
|
-
});
|
|
213
|
-
markedScrollAncestors.forEach(({ element, previousValue }) => {
|
|
214
|
-
if (previousValue === null) {
|
|
215
|
-
element.removeAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE);
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
element.setAttribute(MODERN_SCROLL_ANCESTOR_ID_ATTRIBUTE, previousValue);
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
async function captureWithModernScreenshot(options) {
|
|
224
|
-
const { domToWebp: domToWebp2 } = await Promise.resolve().then(() => index);
|
|
225
|
-
const {
|
|
226
|
-
element,
|
|
227
|
-
excludeSelectors = [],
|
|
228
|
-
width,
|
|
229
|
-
height,
|
|
230
|
-
scale = getCaptureScale()
|
|
231
|
-
} = options;
|
|
232
|
-
await waitForDocumentFonts();
|
|
233
|
-
const stickySnapshot = createModernStickySnapshot(element);
|
|
234
|
-
const excludeSnapshot = createExcludeElementSnapshot(element, excludeSelectors);
|
|
235
|
-
try {
|
|
236
|
-
const captureOptions = {
|
|
237
|
-
scale,
|
|
238
|
-
quality: SCREENSHOT_DATA_URL_QUALITY,
|
|
239
|
-
features: {
|
|
240
|
-
restoreScrollPosition: true
|
|
241
|
-
},
|
|
242
|
-
onCloneNode: (cloned) => {
|
|
243
|
-
if (!(cloned instanceof Element)) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
stickySnapshot.applyToClone(cloned);
|
|
247
|
-
excludeSnapshot.applyToClone(cloned);
|
|
248
|
-
}
|
|
249
|
-
};
|
|
250
|
-
if (width) {
|
|
251
|
-
captureOptions.width = width;
|
|
252
|
-
}
|
|
253
|
-
if (height) {
|
|
254
|
-
captureOptions.height = height;
|
|
255
|
-
}
|
|
256
|
-
return await domToWebp2(element, captureOptions);
|
|
257
|
-
} finally {
|
|
258
|
-
excludeSnapshot.cleanup();
|
|
259
|
-
stickySnapshot.cleanup();
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
function createViewportBounds() {
|
|
263
|
-
return {
|
|
264
|
-
width: window.innerWidth,
|
|
265
|
-
height: window.innerHeight
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
const STORAGE_PREFIX = "is_sdk_";
|
|
269
|
-
class WebPlatform {
|
|
270
|
-
constructor(eventBus) {
|
|
271
|
-
this.memoryStorage = /* @__PURE__ */ new Map();
|
|
272
|
-
this.storageListeners = /* @__PURE__ */ new Map();
|
|
273
|
-
this.storage = {
|
|
274
|
-
get: async (key) => {
|
|
275
|
-
try {
|
|
276
|
-
const raw = localStorage.getItem(`${STORAGE_PREFIX}${key}`);
|
|
277
|
-
return raw ? JSON.parse(raw) : null;
|
|
278
|
-
} catch {
|
|
279
|
-
return this.memoryStorage.get(key) ?? null;
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
set: async (key, value) => {
|
|
283
|
-
var _a2;
|
|
284
|
-
try {
|
|
285
|
-
localStorage.setItem(`${STORAGE_PREFIX}${key}`, JSON.stringify(value));
|
|
286
|
-
} catch {
|
|
287
|
-
this.memoryStorage.set(key, value);
|
|
288
|
-
}
|
|
289
|
-
(_a2 = this.storageListeners.get(key)) == null ? void 0 : _a2.forEach((cb) => cb(value));
|
|
290
|
-
},
|
|
291
|
-
remove: async (key) => {
|
|
292
|
-
var _a2;
|
|
293
|
-
try {
|
|
294
|
-
localStorage.removeItem(`${STORAGE_PREFIX}${key}`);
|
|
295
|
-
} catch {
|
|
296
|
-
this.memoryStorage.delete(key);
|
|
297
|
-
}
|
|
298
|
-
(_a2 = this.storageListeners.get(key)) == null ? void 0 : _a2.forEach((cb) => cb(null));
|
|
299
|
-
},
|
|
300
|
-
onChange: (key, callback) => {
|
|
301
|
-
if (!this.storageListeners.has(key)) {
|
|
302
|
-
this.storageListeners.set(key, /* @__PURE__ */ new Set());
|
|
303
|
-
}
|
|
304
|
-
this.storageListeners.get(key).add(callback);
|
|
305
|
-
return () => {
|
|
306
|
-
var _a2;
|
|
307
|
-
(_a2 = this.storageListeners.get(key)) == null ? void 0 : _a2.delete(callback);
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
};
|
|
311
|
-
this.messaging = {
|
|
312
|
-
send: async (action, payload) => {
|
|
313
|
-
this.eventBus.emit(action, payload);
|
|
314
|
-
return void 0;
|
|
315
|
-
},
|
|
316
|
-
onMessage: (callback) => {
|
|
317
|
-
return this.eventBus.on("*", callback);
|
|
318
|
-
},
|
|
319
|
-
broadcast: (action, payload) => {
|
|
320
|
-
this.eventBus.emit(action, payload);
|
|
321
|
-
}
|
|
322
|
-
};
|
|
323
|
-
this.screenshot = {
|
|
324
|
-
capture: async (options) => {
|
|
325
|
-
const excludeSelectors = (options == null ? void 0 : options.excludeSelectors) ?? [];
|
|
326
|
-
if (options == null ? void 0 : options.element) {
|
|
327
|
-
return captureWithModernScreenshot({
|
|
328
|
-
element: options.element,
|
|
329
|
-
excludeSelectors
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
const viewportBounds = createViewportBounds();
|
|
333
|
-
return captureWithModernScreenshot({
|
|
334
|
-
element: document.documentElement,
|
|
335
|
-
excludeSelectors,
|
|
336
|
-
width: viewportBounds.width,
|
|
337
|
-
height: viewportBounds.height
|
|
338
|
-
});
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
this.capabilities = {
|
|
342
|
-
screenRecording: typeof MediaRecorder !== "undefined",
|
|
343
|
-
detailedNetworkLogs: true,
|
|
344
|
-
consoleLogCapture: true,
|
|
345
|
-
screenshotCapture: true
|
|
346
|
-
};
|
|
347
|
-
this.eventBus = eventBus;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
class EventBus {
|
|
351
|
-
constructor() {
|
|
352
|
-
this.listeners = /* @__PURE__ */ new Map();
|
|
353
|
-
}
|
|
354
|
-
on(event, callback) {
|
|
355
|
-
if (!this.listeners.has(event)) {
|
|
356
|
-
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
357
|
-
}
|
|
358
|
-
this.listeners.get(event).add(callback);
|
|
359
|
-
return () => this.off(event, callback);
|
|
360
|
-
}
|
|
361
|
-
off(event, callback) {
|
|
362
|
-
var _a2;
|
|
363
|
-
(_a2 = this.listeners.get(event)) == null ? void 0 : _a2.delete(callback);
|
|
364
|
-
}
|
|
365
|
-
emit(event, ...args) {
|
|
366
|
-
var _a2, _b;
|
|
367
|
-
(_a2 = this.listeners.get(event)) == null ? void 0 : _a2.forEach((cb) => cb(...args));
|
|
368
|
-
(_b = this.listeners.get("*")) == null ? void 0 : _b.forEach((cb) => cb(event, ...args));
|
|
369
|
-
}
|
|
370
|
-
once(event, callback) {
|
|
371
|
-
const wrapper = (...args) => {
|
|
372
|
-
this.off(event, wrapper);
|
|
373
|
-
callback(...args);
|
|
374
|
-
};
|
|
375
|
-
return this.on(event, wrapper);
|
|
376
|
-
}
|
|
377
|
-
removeAllListeners() {
|
|
378
|
-
this.listeners.clear();
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
const DEFAULT_FLAGS = {
|
|
382
|
-
networkLogs: true,
|
|
383
|
-
consoleLogs: true,
|
|
384
|
-
screenshot: true,
|
|
385
|
-
screenRecording: true,
|
|
386
|
-
stickers: true,
|
|
387
|
-
keyboardShortcuts: true,
|
|
388
|
-
jiraIntegration: false,
|
|
389
|
-
fab: true
|
|
390
|
-
};
|
|
391
|
-
class FeatureFlags {
|
|
392
|
-
constructor(overrides) {
|
|
393
|
-
this.flags = { ...DEFAULT_FLAGS, ...overrides };
|
|
394
|
-
}
|
|
395
|
-
get(name) {
|
|
396
|
-
return this.flags[name];
|
|
397
|
-
}
|
|
398
|
-
set(name, enabled) {
|
|
399
|
-
this.flags[name] = enabled;
|
|
400
|
-
}
|
|
401
|
-
getAll() {
|
|
402
|
-
return { ...this.flags };
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
const _SDKManager = class _SDKManager {
|
|
406
|
-
constructor() {
|
|
407
|
-
this._config = null;
|
|
408
|
-
this._platform = null;
|
|
409
|
-
this._eventBus = null;
|
|
410
|
-
this._featureFlags = null;
|
|
411
|
-
this._initialized = false;
|
|
412
|
-
}
|
|
413
|
-
static getInstance() {
|
|
414
|
-
if (!_SDKManager.instance) {
|
|
415
|
-
_SDKManager.instance = new _SDKManager();
|
|
416
|
-
}
|
|
417
|
-
return _SDKManager.instance;
|
|
418
|
-
}
|
|
419
|
-
init(config) {
|
|
420
|
-
if (this._initialized) {
|
|
421
|
-
this.updateConfig(config);
|
|
422
|
-
return;
|
|
423
|
-
}
|
|
424
|
-
this._config = config;
|
|
425
|
-
this._eventBus = new EventBus();
|
|
426
|
-
this._platform = new WebPlatform(this._eventBus);
|
|
427
|
-
this._featureFlags = new FeatureFlags({});
|
|
428
|
-
this._initialized = true;
|
|
429
|
-
}
|
|
430
|
-
updateConfig(config) {
|
|
431
|
-
if (!this._initialized) {
|
|
432
|
-
this.init(config);
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
this._config = config;
|
|
436
|
-
}
|
|
437
|
-
destroy() {
|
|
438
|
-
var _a2;
|
|
439
|
-
(_a2 = this._eventBus) == null ? void 0 : _a2.removeAllListeners();
|
|
440
|
-
this._config = null;
|
|
441
|
-
this._platform = null;
|
|
442
|
-
this._eventBus = null;
|
|
443
|
-
this._featureFlags = null;
|
|
444
|
-
this._initialized = false;
|
|
445
|
-
}
|
|
446
|
-
isInitialized() {
|
|
447
|
-
return this._initialized;
|
|
448
|
-
}
|
|
449
|
-
get config() {
|
|
450
|
-
if (!this._config) throw new Error("SDK not initialized");
|
|
451
|
-
return this._config;
|
|
452
|
-
}
|
|
453
|
-
get platform() {
|
|
454
|
-
if (!this._platform) throw new Error("SDK not initialized");
|
|
455
|
-
return this._platform;
|
|
456
|
-
}
|
|
457
|
-
get eventBus() {
|
|
458
|
-
if (!this._eventBus) throw new Error("SDK not initialized");
|
|
459
|
-
return this._eventBus;
|
|
460
|
-
}
|
|
461
|
-
get featureFlags() {
|
|
462
|
-
if (!this._featureFlags) throw new Error("SDK not initialized");
|
|
463
|
-
return this._featureFlags;
|
|
464
|
-
}
|
|
465
|
-
static resetInstance() {
|
|
466
|
-
if (_SDKManager.instance) {
|
|
467
|
-
_SDKManager.instance.destroy();
|
|
468
|
-
_SDKManager.instance = null;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
_SDKManager.instance = null;
|
|
473
|
-
let SDKManager = _SDKManager;
|
|
474
|
-
const pendingListeners = /* @__PURE__ */ new Map();
|
|
475
|
-
function addPendingSdkEventListener(event, callback) {
|
|
476
|
-
if (!pendingListeners.has(event)) {
|
|
477
|
-
pendingListeners.set(event, /* @__PURE__ */ new Set());
|
|
478
|
-
}
|
|
479
|
-
pendingListeners.get(event).add(callback);
|
|
480
|
-
}
|
|
481
|
-
function removePendingSdkEventListener(event, callback) {
|
|
482
|
-
var _a2, _b;
|
|
483
|
-
(_a2 = pendingListeners.get(event)) == null ? void 0 : _a2.delete(callback);
|
|
484
|
-
if (((_b = pendingListeners.get(event)) == null ? void 0 : _b.size) === 0) {
|
|
485
|
-
pendingListeners.delete(event);
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
function flushPendingSdkEventListeners(eventBus) {
|
|
489
|
-
pendingListeners.forEach((listeners, event) => {
|
|
490
|
-
listeners.forEach((callback) => eventBus.on(event, callback));
|
|
491
|
-
});
|
|
492
|
-
pendingListeners.clear();
|
|
493
|
-
}
|
|
494
|
-
const IssueSticker = {
|
|
495
|
-
init(config) {
|
|
496
|
-
const sdk = SDKManager.getInstance();
|
|
497
|
-
if (sdk.isInitialized()) {
|
|
498
|
-
sdk.updateConfig(config);
|
|
499
|
-
flushPendingSdkEventListeners(sdk.eventBus);
|
|
500
|
-
sdk.eventBus.emit("ready");
|
|
501
|
-
return;
|
|
502
|
-
}
|
|
503
|
-
sdk.init(config);
|
|
504
|
-
flushPendingSdkEventListeners(sdk.eventBus);
|
|
505
|
-
sdk.eventBus.emit("ready");
|
|
506
|
-
},
|
|
507
|
-
destroy() {
|
|
508
|
-
SDKManager.resetInstance();
|
|
509
|
-
},
|
|
510
|
-
on(event, callback) {
|
|
511
|
-
const sdk = SDKManager.getInstance();
|
|
512
|
-
if (sdk.isInitialized()) {
|
|
513
|
-
sdk.eventBus.on(event, callback);
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
addPendingSdkEventListener(event, callback);
|
|
517
|
-
},
|
|
518
|
-
off(event, callback) {
|
|
519
|
-
removePendingSdkEventListener(event, callback);
|
|
520
|
-
const sdk = SDKManager.getInstance();
|
|
521
|
-
if (sdk.isInitialized()) {
|
|
522
|
-
sdk.eventBus.off(event, callback);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
|
-
function changeJpegDpi(uint8Array, dpi) {
|
|
527
|
-
uint8Array[13] = 1;
|
|
528
|
-
uint8Array[14] = dpi >> 8;
|
|
529
|
-
uint8Array[15] = dpi & 255;
|
|
530
|
-
uint8Array[16] = dpi >> 8;
|
|
531
|
-
uint8Array[17] = dpi & 255;
|
|
532
|
-
return uint8Array;
|
|
533
|
-
}
|
|
534
|
-
const _P = "p".charCodeAt(0);
|
|
535
|
-
const _H = "H".charCodeAt(0);
|
|
536
|
-
const _Y = "Y".charCodeAt(0);
|
|
537
|
-
const _S = "s".charCodeAt(0);
|
|
538
|
-
let pngDataTable;
|
|
539
|
-
function createPngDataTable() {
|
|
540
|
-
const crcTable = new Int32Array(256);
|
|
541
|
-
for (let n = 0; n < 256; n++) {
|
|
542
|
-
let c = n;
|
|
543
|
-
for (let k = 0; k < 8; k++) {
|
|
544
|
-
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
545
|
-
}
|
|
546
|
-
crcTable[n] = c;
|
|
547
|
-
}
|
|
548
|
-
return crcTable;
|
|
549
|
-
}
|
|
550
|
-
function calcCrc(uint8Array) {
|
|
551
|
-
let c = -1;
|
|
552
|
-
if (!pngDataTable)
|
|
553
|
-
pngDataTable = createPngDataTable();
|
|
554
|
-
for (let n = 0; n < uint8Array.length; n++) {
|
|
555
|
-
c = pngDataTable[(c ^ uint8Array[n]) & 255] ^ c >>> 8;
|
|
556
|
-
}
|
|
557
|
-
return c ^ -1;
|
|
558
|
-
}
|
|
559
|
-
function searchStartOfPhys(uint8Array) {
|
|
560
|
-
const length = uint8Array.length - 1;
|
|
561
|
-
for (let i = length; i >= 4; i--) {
|
|
562
|
-
if (uint8Array[i - 4] === 9 && uint8Array[i - 3] === _P && uint8Array[i - 2] === _H && uint8Array[i - 1] === _Y && uint8Array[i] === _S) {
|
|
563
|
-
return i - 3;
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
return 0;
|
|
567
|
-
}
|
|
568
|
-
function changePngDpi(uint8Array, dpi, overwritepHYs = false) {
|
|
569
|
-
const physChunk = new Uint8Array(13);
|
|
570
|
-
dpi *= 39.3701;
|
|
571
|
-
physChunk[0] = _P;
|
|
572
|
-
physChunk[1] = _H;
|
|
573
|
-
physChunk[2] = _Y;
|
|
574
|
-
physChunk[3] = _S;
|
|
575
|
-
physChunk[4] = dpi >>> 24;
|
|
576
|
-
physChunk[5] = dpi >>> 16;
|
|
577
|
-
physChunk[6] = dpi >>> 8;
|
|
578
|
-
physChunk[7] = dpi & 255;
|
|
579
|
-
physChunk[8] = physChunk[4];
|
|
580
|
-
physChunk[9] = physChunk[5];
|
|
581
|
-
physChunk[10] = physChunk[6];
|
|
582
|
-
physChunk[11] = physChunk[7];
|
|
583
|
-
physChunk[12] = 1;
|
|
584
|
-
const crc = calcCrc(physChunk);
|
|
585
|
-
const crcChunk = new Uint8Array(4);
|
|
586
|
-
crcChunk[0] = crc >>> 24;
|
|
587
|
-
crcChunk[1] = crc >>> 16;
|
|
588
|
-
crcChunk[2] = crc >>> 8;
|
|
589
|
-
crcChunk[3] = crc & 255;
|
|
590
|
-
if (overwritepHYs) {
|
|
591
|
-
const startingIndex = searchStartOfPhys(uint8Array);
|
|
592
|
-
uint8Array.set(physChunk, startingIndex);
|
|
593
|
-
uint8Array.set(crcChunk, startingIndex + 13);
|
|
594
|
-
return uint8Array;
|
|
595
|
-
} else {
|
|
596
|
-
const chunkLength = new Uint8Array(4);
|
|
597
|
-
chunkLength[0] = 0;
|
|
598
|
-
chunkLength[1] = 0;
|
|
599
|
-
chunkLength[2] = 0;
|
|
600
|
-
chunkLength[3] = 9;
|
|
601
|
-
const finalHeader = new Uint8Array(54);
|
|
602
|
-
finalHeader.set(uint8Array, 0);
|
|
603
|
-
finalHeader.set(chunkLength, 33);
|
|
604
|
-
finalHeader.set(physChunk, 37);
|
|
605
|
-
finalHeader.set(crcChunk, 50);
|
|
606
|
-
return finalHeader;
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
const b64PhysSignature1 = "AAlwSFlz";
|
|
610
|
-
const b64PhysSignature2 = "AAAJcEhZ";
|
|
611
|
-
const b64PhysSignature3 = "AAAACXBI";
|
|
612
|
-
function detectPhysChunkFromDataUrl(dataUrl) {
|
|
613
|
-
let b64index = dataUrl.indexOf(b64PhysSignature1);
|
|
614
|
-
if (b64index === -1) {
|
|
615
|
-
b64index = dataUrl.indexOf(b64PhysSignature2);
|
|
616
|
-
}
|
|
617
|
-
if (b64index === -1) {
|
|
618
|
-
b64index = dataUrl.indexOf(b64PhysSignature3);
|
|
619
|
-
}
|
|
620
|
-
return b64index;
|
|
621
|
-
}
|
|
622
|
-
const PREFIX = "[modern-screenshot]";
|
|
623
|
-
const IN_BROWSER = typeof window !== "undefined";
|
|
624
|
-
const SUPPORT_WEB_WORKER = IN_BROWSER && "Worker" in window;
|
|
625
|
-
const SUPPORT_ATOB = IN_BROWSER && "atob" in window;
|
|
626
|
-
const SUPPORT_BTOA = IN_BROWSER && "btoa" in window;
|
|
627
|
-
const USER_AGENT = IN_BROWSER ? (_a = window.navigator) == null ? void 0 : _a.userAgent : "";
|
|
628
|
-
const IN_CHROME = USER_AGENT.includes("Chrome");
|
|
629
|
-
const IN_SAFARI = USER_AGENT.includes("AppleWebKit") && !IN_CHROME;
|
|
630
|
-
const IN_FIREFOX = USER_AGENT.includes("Firefox");
|
|
631
|
-
const isContext = (value) => value && "__CONTEXT__" in value;
|
|
632
|
-
const isCssFontFaceRule = (rule) => rule.constructor.name === "CSSFontFaceRule";
|
|
633
|
-
const isCSSImportRule = (rule) => rule.constructor.name === "CSSImportRule";
|
|
634
|
-
const isLayerBlockRule = (rule) => rule.constructor.name === "CSSLayerBlockRule";
|
|
635
|
-
const isElementNode = (node) => node.nodeType === 1;
|
|
636
|
-
const isSVGElementNode = (node) => typeof node.className === "object";
|
|
637
|
-
const isSVGImageElementNode = (node) => node.tagName === "image";
|
|
638
|
-
const isSVGUseElementNode = (node) => node.tagName === "use";
|
|
639
|
-
const isHTMLElementNode = (node) => isElementNode(node) && typeof node.style !== "undefined" && !isSVGElementNode(node);
|
|
640
|
-
const isCommentNode = (node) => node.nodeType === 8;
|
|
641
|
-
const isTextNode = (node) => node.nodeType === 3;
|
|
642
|
-
const isImageElement = (node) => node.tagName === "IMG";
|
|
643
|
-
const isVideoElement = (node) => node.tagName === "VIDEO";
|
|
644
|
-
const isCanvasElement = (node) => node.tagName === "CANVAS";
|
|
645
|
-
const isTextareaElement = (node) => node.tagName === "TEXTAREA";
|
|
646
|
-
const isInputElement = (node) => node.tagName === "INPUT";
|
|
647
|
-
const isStyleElement = (node) => node.tagName === "STYLE";
|
|
648
|
-
const isScriptElement = (node) => node.tagName === "SCRIPT";
|
|
649
|
-
const isSelectElement = (node) => node.tagName === "SELECT";
|
|
650
|
-
const isSlotElement = (node) => node.tagName === "SLOT";
|
|
651
|
-
const isIFrameElement = (node) => node.tagName === "IFRAME";
|
|
652
|
-
const consoleWarn = (...args) => console.warn(PREFIX, ...args);
|
|
653
|
-
function supportWebp(ownerDocument) {
|
|
654
|
-
var _a2;
|
|
655
|
-
const canvas = (_a2 = ownerDocument == null ? void 0 : ownerDocument.createElement) == null ? void 0 : _a2.call(ownerDocument, "canvas");
|
|
656
|
-
if (canvas) {
|
|
657
|
-
canvas.height = canvas.width = 1;
|
|
658
|
-
}
|
|
659
|
-
return Boolean(canvas) && "toDataURL" in canvas && Boolean(canvas.toDataURL("image/webp").includes("image/webp"));
|
|
660
|
-
}
|
|
661
|
-
const isDataUrl = (url) => url.startsWith("data:");
|
|
662
|
-
function resolveUrl(url, baseUrl) {
|
|
663
|
-
if (url.match(/^[a-z]+:\/\//i))
|
|
664
|
-
return url;
|
|
665
|
-
if (IN_BROWSER && url.match(/^\/\//))
|
|
666
|
-
return window.location.protocol + url;
|
|
667
|
-
if (url.match(/^[a-z]+:/i))
|
|
668
|
-
return url;
|
|
669
|
-
if (!IN_BROWSER)
|
|
670
|
-
return url;
|
|
671
|
-
const doc = getDocument().implementation.createHTMLDocument();
|
|
672
|
-
const base = doc.createElement("base");
|
|
673
|
-
const a = doc.createElement("a");
|
|
674
|
-
doc.head.appendChild(base);
|
|
675
|
-
doc.body.appendChild(a);
|
|
676
|
-
if (baseUrl)
|
|
677
|
-
base.href = baseUrl;
|
|
678
|
-
a.href = url;
|
|
679
|
-
return a.href;
|
|
680
|
-
}
|
|
681
|
-
function getDocument(target) {
|
|
682
|
-
return (target && isElementNode(target) ? target == null ? void 0 : target.ownerDocument : target) ?? window.document;
|
|
683
|
-
}
|
|
684
|
-
const XMLNS = "http://www.w3.org/2000/svg";
|
|
685
|
-
function createSvg(width, height, ownerDocument) {
|
|
686
|
-
const svg = getDocument(ownerDocument).createElementNS(XMLNS, "svg");
|
|
687
|
-
svg.setAttributeNS(null, "width", width.toString());
|
|
688
|
-
svg.setAttributeNS(null, "height", height.toString());
|
|
689
|
-
svg.setAttributeNS(null, "viewBox", `0 0 ${width} ${height}`);
|
|
690
|
-
return svg;
|
|
691
|
-
}
|
|
692
|
-
function svgToDataUrl(svg, removeControlCharacter) {
|
|
693
|
-
let xhtml = new XMLSerializer().serializeToString(svg);
|
|
694
|
-
if (removeControlCharacter) {
|
|
695
|
-
xhtml = xhtml.replace(/[\u0000-\u0008\v\f\u000E-\u001F\uD800-\uDFFF\uFFFE\uFFFF]/gu, "");
|
|
696
|
-
}
|
|
697
|
-
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(xhtml)}`;
|
|
698
|
-
}
|
|
699
|
-
function readBlob(blob, type) {
|
|
700
|
-
return new Promise((resolve, reject) => {
|
|
701
|
-
const reader = new FileReader();
|
|
702
|
-
reader.onload = () => resolve(reader.result);
|
|
703
|
-
reader.onerror = () => reject(reader.error);
|
|
704
|
-
reader.onabort = () => reject(new Error(`Failed read blob to ${type}`));
|
|
705
|
-
{
|
|
706
|
-
reader.readAsDataURL(blob);
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
}
|
|
710
|
-
const blobToDataUrl = (blob) => readBlob(blob, "dataUrl");
|
|
711
|
-
function createImage(url, ownerDocument) {
|
|
712
|
-
const img = getDocument(ownerDocument).createElement("img");
|
|
713
|
-
img.decoding = "sync";
|
|
714
|
-
img.loading = "eager";
|
|
715
|
-
img.src = url;
|
|
716
|
-
return img;
|
|
717
|
-
}
|
|
718
|
-
function loadMedia(media, options) {
|
|
719
|
-
return new Promise((resolve) => {
|
|
720
|
-
const { timeout, ownerDocument, onError: userOnError, onWarn } = options ?? {};
|
|
721
|
-
const node = typeof media === "string" ? createImage(media, getDocument(ownerDocument)) : media;
|
|
722
|
-
let timer = null;
|
|
723
|
-
let removeEventListeners = null;
|
|
724
|
-
function onResolve() {
|
|
725
|
-
resolve(node);
|
|
726
|
-
timer && clearTimeout(timer);
|
|
727
|
-
removeEventListeners == null ? void 0 : removeEventListeners();
|
|
728
|
-
}
|
|
729
|
-
if (timeout) {
|
|
730
|
-
timer = setTimeout(onResolve, timeout);
|
|
731
|
-
}
|
|
732
|
-
if (isVideoElement(node)) {
|
|
733
|
-
const currentSrc = node.currentSrc || node.src;
|
|
734
|
-
if (!currentSrc) {
|
|
735
|
-
if (node.poster) {
|
|
736
|
-
return loadMedia(node.poster, options).then(resolve);
|
|
737
|
-
}
|
|
738
|
-
return onResolve();
|
|
739
|
-
}
|
|
740
|
-
if (node.readyState >= 2) {
|
|
741
|
-
return onResolve();
|
|
742
|
-
}
|
|
743
|
-
const onLoadeddata = onResolve;
|
|
744
|
-
const onError = (error) => {
|
|
745
|
-
onWarn == null ? void 0 : onWarn(
|
|
746
|
-
"Failed video load",
|
|
747
|
-
currentSrc,
|
|
748
|
-
error
|
|
749
|
-
);
|
|
750
|
-
userOnError == null ? void 0 : userOnError(error);
|
|
751
|
-
onResolve();
|
|
752
|
-
};
|
|
753
|
-
removeEventListeners = () => {
|
|
754
|
-
node.removeEventListener("loadeddata", onLoadeddata);
|
|
755
|
-
node.removeEventListener("error", onError);
|
|
756
|
-
};
|
|
757
|
-
node.addEventListener("loadeddata", onLoadeddata, { once: true });
|
|
758
|
-
node.addEventListener("error", onError, { once: true });
|
|
759
|
-
} else {
|
|
760
|
-
const currentSrc = isSVGImageElementNode(node) ? node.href.baseVal : node.currentSrc || node.src;
|
|
761
|
-
if (!currentSrc) {
|
|
762
|
-
return onResolve();
|
|
763
|
-
}
|
|
764
|
-
const onLoad = async () => {
|
|
765
|
-
if (isImageElement(node) && "decode" in node) {
|
|
766
|
-
try {
|
|
767
|
-
await node.decode();
|
|
768
|
-
} catch (error) {
|
|
769
|
-
onWarn == null ? void 0 : onWarn(
|
|
770
|
-
"Failed to decode image, trying to render anyway",
|
|
771
|
-
node.dataset.originalSrc || currentSrc,
|
|
772
|
-
error
|
|
773
|
-
);
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
onResolve();
|
|
777
|
-
};
|
|
778
|
-
const onError = (error) => {
|
|
779
|
-
onWarn == null ? void 0 : onWarn(
|
|
780
|
-
"Failed image load",
|
|
781
|
-
node.dataset.originalSrc || currentSrc,
|
|
782
|
-
error
|
|
783
|
-
);
|
|
784
|
-
onResolve();
|
|
785
|
-
};
|
|
786
|
-
if (isImageElement(node) && node.complete) {
|
|
787
|
-
return onLoad();
|
|
788
|
-
}
|
|
789
|
-
removeEventListeners = () => {
|
|
790
|
-
node.removeEventListener("load", onLoad);
|
|
791
|
-
node.removeEventListener("error", onError);
|
|
792
|
-
};
|
|
793
|
-
node.addEventListener("load", onLoad, { once: true });
|
|
794
|
-
node.addEventListener("error", onError, { once: true });
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
}
|
|
798
|
-
async function waitUntilLoad(node, options) {
|
|
799
|
-
if (isHTMLElementNode(node)) {
|
|
800
|
-
if (isImageElement(node) || isVideoElement(node)) {
|
|
801
|
-
await loadMedia(node, options);
|
|
802
|
-
} else {
|
|
803
|
-
await Promise.all(
|
|
804
|
-
["img", "video"].flatMap((selectors) => {
|
|
805
|
-
return Array.from(node.querySelectorAll(selectors)).map((el) => loadMedia(el, options));
|
|
806
|
-
})
|
|
807
|
-
);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
const uuid = /* @__PURE__ */ (function uuid2() {
|
|
812
|
-
let counter = 0;
|
|
813
|
-
const random = () => `0000${(Math.random() * 36 ** 4 << 0).toString(36)}`.slice(-4);
|
|
814
|
-
return () => {
|
|
815
|
-
counter += 1;
|
|
816
|
-
return `u${random()}${counter}`;
|
|
817
|
-
};
|
|
818
|
-
})();
|
|
819
|
-
function splitFontFamily(fontFamily) {
|
|
820
|
-
return fontFamily == null ? void 0 : fontFamily.split(",").map((val) => val.trim().replace(/"|'/g, "").toLowerCase()).filter(Boolean);
|
|
821
|
-
}
|
|
822
|
-
let uid = 0;
|
|
823
|
-
function createLogger(debug) {
|
|
824
|
-
const prefix = `${PREFIX}[#${uid}]`;
|
|
825
|
-
uid++;
|
|
826
|
-
return {
|
|
827
|
-
// eslint-disable-next-line no-console
|
|
828
|
-
time: (label) => debug && console.time(`${prefix} ${label}`),
|
|
829
|
-
// eslint-disable-next-line no-console
|
|
830
|
-
timeEnd: (label) => debug && console.timeEnd(`${prefix} ${label}`),
|
|
831
|
-
warn: (...args) => debug && consoleWarn(...args)
|
|
832
|
-
};
|
|
833
|
-
}
|
|
834
|
-
function getDefaultRequestInit(bypassingCache) {
|
|
835
|
-
return {
|
|
836
|
-
cache: bypassingCache ? "no-cache" : "force-cache"
|
|
837
|
-
};
|
|
838
|
-
}
|
|
839
|
-
async function orCreateContext(node, options) {
|
|
840
|
-
return isContext(node) ? node : createContext(node, { ...options, autoDestruct: true });
|
|
841
|
-
}
|
|
842
|
-
async function createContext(node, options) {
|
|
843
|
-
var _a2, _b;
|
|
844
|
-
const { scale = 1, workerUrl, workerNumber = 1 } = options || {};
|
|
845
|
-
const debug = Boolean(options == null ? void 0 : options.debug);
|
|
846
|
-
const features = (options == null ? void 0 : options.features) ?? true;
|
|
847
|
-
const ownerDocument = node.ownerDocument ?? (IN_BROWSER ? window.document : void 0);
|
|
848
|
-
const ownerWindow = ((_a2 = node.ownerDocument) == null ? void 0 : _a2.defaultView) ?? (IN_BROWSER ? window : void 0);
|
|
849
|
-
const requests = /* @__PURE__ */ new Map();
|
|
850
|
-
const context = {
|
|
851
|
-
// Options
|
|
852
|
-
width: 0,
|
|
853
|
-
height: 0,
|
|
854
|
-
quality: 1,
|
|
855
|
-
type: "image/png",
|
|
856
|
-
scale,
|
|
857
|
-
backgroundColor: null,
|
|
858
|
-
style: null,
|
|
859
|
-
filter: null,
|
|
860
|
-
maximumCanvasSize: 0,
|
|
861
|
-
timeout: 3e4,
|
|
862
|
-
progress: null,
|
|
863
|
-
debug,
|
|
864
|
-
fetch: {
|
|
865
|
-
requestInit: getDefaultRequestInit((_b = options == null ? void 0 : options.fetch) == null ? void 0 : _b.bypassingCache),
|
|
866
|
-
placeholderImage: "data:image/png;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
|
|
867
|
-
bypassingCache: false,
|
|
868
|
-
...options == null ? void 0 : options.fetch
|
|
869
|
-
},
|
|
870
|
-
fetchFn: null,
|
|
871
|
-
font: {},
|
|
872
|
-
drawImageInterval: 100,
|
|
873
|
-
workerUrl: null,
|
|
874
|
-
workerNumber,
|
|
875
|
-
onCloneEachNode: null,
|
|
876
|
-
onCloneNode: null,
|
|
877
|
-
onEmbedNode: null,
|
|
878
|
-
onCreateForeignObjectSvg: null,
|
|
879
|
-
includeStyleProperties: null,
|
|
880
|
-
autoDestruct: false,
|
|
881
|
-
...options,
|
|
882
|
-
// InternalContext
|
|
883
|
-
__CONTEXT__: true,
|
|
884
|
-
log: createLogger(debug),
|
|
885
|
-
node,
|
|
886
|
-
ownerDocument,
|
|
887
|
-
ownerWindow,
|
|
888
|
-
dpi: scale === 1 ? null : 96 * scale,
|
|
889
|
-
svgStyleElement: createStyleElement(ownerDocument),
|
|
890
|
-
svgDefsElement: ownerDocument == null ? void 0 : ownerDocument.createElementNS(XMLNS, "defs"),
|
|
891
|
-
svgStyles: /* @__PURE__ */ new Map(),
|
|
892
|
-
defaultComputedStyles: /* @__PURE__ */ new Map(),
|
|
893
|
-
workers: [
|
|
894
|
-
...Array.from({
|
|
895
|
-
length: SUPPORT_WEB_WORKER && workerUrl && workerNumber ? workerNumber : 0
|
|
896
|
-
})
|
|
897
|
-
].map(() => {
|
|
898
|
-
try {
|
|
899
|
-
const worker = new Worker(workerUrl);
|
|
900
|
-
worker.onmessage = async (event) => {
|
|
901
|
-
var _a3, _b2, _c, _d;
|
|
902
|
-
const { url, result } = event.data;
|
|
903
|
-
if (result) {
|
|
904
|
-
(_b2 = (_a3 = requests.get(url)) == null ? void 0 : _a3.resolve) == null ? void 0 : _b2.call(_a3, result);
|
|
905
|
-
} else {
|
|
906
|
-
(_d = (_c = requests.get(url)) == null ? void 0 : _c.reject) == null ? void 0 : _d.call(_c, new Error(`Error receiving message from worker: ${url}`));
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
worker.onmessageerror = (event) => {
|
|
910
|
-
var _a3, _b2;
|
|
911
|
-
const { url } = event.data;
|
|
912
|
-
(_b2 = (_a3 = requests.get(url)) == null ? void 0 : _a3.reject) == null ? void 0 : _b2.call(_a3, new Error(`Error receiving message from worker: ${url}`));
|
|
913
|
-
};
|
|
914
|
-
return worker;
|
|
915
|
-
} catch (error) {
|
|
916
|
-
context.log.warn("Failed to new Worker", error);
|
|
917
|
-
return null;
|
|
918
|
-
}
|
|
919
|
-
}).filter(Boolean),
|
|
920
|
-
fontFamilies: /* @__PURE__ */ new Map(),
|
|
921
|
-
fontCssTexts: /* @__PURE__ */ new Map(),
|
|
922
|
-
acceptOfImage: `${[
|
|
923
|
-
supportWebp(ownerDocument) && "image/webp",
|
|
924
|
-
"image/svg+xml",
|
|
925
|
-
"image/*",
|
|
926
|
-
"*/*"
|
|
927
|
-
].filter(Boolean).join(",")};q=0.8`,
|
|
928
|
-
requests,
|
|
929
|
-
drawImageCount: 0,
|
|
930
|
-
tasks: [],
|
|
931
|
-
features,
|
|
932
|
-
isEnable: (key) => {
|
|
933
|
-
if (key === "restoreScrollPosition") {
|
|
934
|
-
return typeof features === "boolean" ? false : features[key] ?? false;
|
|
935
|
-
}
|
|
936
|
-
if (typeof features === "boolean") {
|
|
937
|
-
return features;
|
|
938
|
-
}
|
|
939
|
-
return features[key] ?? true;
|
|
940
|
-
},
|
|
941
|
-
shadowRoots: []
|
|
942
|
-
};
|
|
943
|
-
context.log.time("wait until load");
|
|
944
|
-
await waitUntilLoad(node, { timeout: context.timeout, onWarn: context.log.warn });
|
|
945
|
-
context.log.timeEnd("wait until load");
|
|
946
|
-
const { width, height } = resolveBoundingBox(node, context);
|
|
947
|
-
context.width = width;
|
|
948
|
-
context.height = height;
|
|
949
|
-
return context;
|
|
950
|
-
}
|
|
951
|
-
function createStyleElement(ownerDocument) {
|
|
952
|
-
if (!ownerDocument)
|
|
953
|
-
return void 0;
|
|
954
|
-
const style = ownerDocument.createElement("style");
|
|
955
|
-
const cssText = style.ownerDocument.createTextNode(`
|
|
956
|
-
.______background-clip--text {
|
|
957
|
-
background-clip: text;
|
|
958
|
-
-webkit-background-clip: text;
|
|
959
|
-
}
|
|
960
|
-
`);
|
|
961
|
-
style.appendChild(cssText);
|
|
962
|
-
return style;
|
|
963
|
-
}
|
|
964
|
-
function resolveBoundingBox(node, context) {
|
|
965
|
-
let { width, height } = context;
|
|
966
|
-
if (isElementNode(node) && (!width || !height)) {
|
|
967
|
-
const box = node.getBoundingClientRect();
|
|
968
|
-
width = width || box.width || Number(node.getAttribute("width")) || 0;
|
|
969
|
-
height = height || box.height || Number(node.getAttribute("height")) || 0;
|
|
970
|
-
}
|
|
971
|
-
return { width, height };
|
|
972
|
-
}
|
|
973
|
-
async function imageToCanvas(image, context) {
|
|
974
|
-
const {
|
|
975
|
-
log,
|
|
976
|
-
timeout,
|
|
977
|
-
drawImageCount,
|
|
978
|
-
drawImageInterval
|
|
979
|
-
} = context;
|
|
980
|
-
log.time("image to canvas");
|
|
981
|
-
const loaded = await loadMedia(image, { timeout, onWarn: context.log.warn });
|
|
982
|
-
const { canvas, context2d } = createCanvas(image.ownerDocument, context);
|
|
983
|
-
const drawImage = () => {
|
|
984
|
-
try {
|
|
985
|
-
context2d == null ? void 0 : context2d.drawImage(loaded, 0, 0, canvas.width, canvas.height);
|
|
986
|
-
} catch (error) {
|
|
987
|
-
context.log.warn("Failed to drawImage", error);
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
drawImage();
|
|
991
|
-
if (context.isEnable("fixSvgXmlDecode")) {
|
|
992
|
-
for (let i = 0; i < drawImageCount; i++) {
|
|
993
|
-
await new Promise((resolve) => {
|
|
994
|
-
setTimeout(() => {
|
|
995
|
-
context2d == null ? void 0 : context2d.clearRect(0, 0, canvas.width, canvas.height);
|
|
996
|
-
drawImage();
|
|
997
|
-
resolve();
|
|
998
|
-
}, i + drawImageInterval);
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
context.drawImageCount = 0;
|
|
1003
|
-
log.timeEnd("image to canvas");
|
|
1004
|
-
return canvas;
|
|
1005
|
-
}
|
|
1006
|
-
function createCanvas(ownerDocument, context) {
|
|
1007
|
-
const { width, height, scale, backgroundColor, maximumCanvasSize: max } = context;
|
|
1008
|
-
const canvas = ownerDocument.createElement("canvas");
|
|
1009
|
-
canvas.width = Math.floor(width * scale);
|
|
1010
|
-
canvas.height = Math.floor(height * scale);
|
|
1011
|
-
canvas.style.width = `${width}px`;
|
|
1012
|
-
canvas.style.height = `${height}px`;
|
|
1013
|
-
if (max) {
|
|
1014
|
-
if (canvas.width > max || canvas.height > max) {
|
|
1015
|
-
if (canvas.width > max && canvas.height > max) {
|
|
1016
|
-
if (canvas.width > canvas.height) {
|
|
1017
|
-
canvas.height *= max / canvas.width;
|
|
1018
|
-
canvas.width = max;
|
|
1019
|
-
} else {
|
|
1020
|
-
canvas.width *= max / canvas.height;
|
|
1021
|
-
canvas.height = max;
|
|
1022
|
-
}
|
|
1023
|
-
} else if (canvas.width > max) {
|
|
1024
|
-
canvas.height *= max / canvas.width;
|
|
1025
|
-
canvas.width = max;
|
|
1026
|
-
} else {
|
|
1027
|
-
canvas.width *= max / canvas.height;
|
|
1028
|
-
canvas.height = max;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
const context2d = canvas.getContext("2d");
|
|
1033
|
-
if (context2d && backgroundColor) {
|
|
1034
|
-
context2d.fillStyle = backgroundColor;
|
|
1035
|
-
context2d.fillRect(0, 0, canvas.width, canvas.height);
|
|
1036
|
-
}
|
|
1037
|
-
return { canvas, context2d };
|
|
1038
|
-
}
|
|
1039
|
-
function cloneCanvas(canvas, context) {
|
|
1040
|
-
if (canvas.ownerDocument) {
|
|
1041
|
-
try {
|
|
1042
|
-
const dataURL = canvas.toDataURL();
|
|
1043
|
-
if (dataURL !== "data:,") {
|
|
1044
|
-
return createImage(dataURL, canvas.ownerDocument);
|
|
1045
|
-
}
|
|
1046
|
-
} catch (error) {
|
|
1047
|
-
context.log.warn("Failed to clone canvas", error);
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
const cloned = canvas.cloneNode(false);
|
|
1051
|
-
const ctx = canvas.getContext("2d");
|
|
1052
|
-
const clonedCtx = cloned.getContext("2d");
|
|
1053
|
-
try {
|
|
1054
|
-
if (ctx && clonedCtx) {
|
|
1055
|
-
clonedCtx.putImageData(
|
|
1056
|
-
ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
1057
|
-
0,
|
|
1058
|
-
0
|
|
1059
|
-
);
|
|
1060
|
-
}
|
|
1061
|
-
return cloned;
|
|
1062
|
-
} catch (error) {
|
|
1063
|
-
context.log.warn("Failed to clone canvas", error);
|
|
1064
|
-
}
|
|
1065
|
-
return cloned;
|
|
1066
|
-
}
|
|
1067
|
-
function cloneIframe(iframe, context) {
|
|
1068
|
-
var _a2;
|
|
1069
|
-
try {
|
|
1070
|
-
if ((_a2 = iframe == null ? void 0 : iframe.contentDocument) == null ? void 0 : _a2.documentElement) {
|
|
1071
|
-
return cloneNode(iframe.contentDocument.documentElement, context);
|
|
1072
|
-
}
|
|
1073
|
-
} catch (error) {
|
|
1074
|
-
context.log.warn("Failed to clone iframe", error);
|
|
1075
|
-
}
|
|
1076
|
-
return iframe.cloneNode(false);
|
|
1077
|
-
}
|
|
1078
|
-
function cloneImage(image) {
|
|
1079
|
-
const cloned = image.cloneNode(false);
|
|
1080
|
-
if (image.currentSrc && image.currentSrc !== image.src) {
|
|
1081
|
-
cloned.src = image.currentSrc;
|
|
1082
|
-
cloned.srcset = "";
|
|
1083
|
-
}
|
|
1084
|
-
if (cloned.loading === "lazy") {
|
|
1085
|
-
cloned.loading = "eager";
|
|
1086
|
-
}
|
|
1087
|
-
return cloned;
|
|
1088
|
-
}
|
|
1089
|
-
async function cloneVideo(video, context) {
|
|
1090
|
-
if (video.ownerDocument && !video.currentSrc && video.poster) {
|
|
1091
|
-
return createImage(video.poster, video.ownerDocument);
|
|
1092
|
-
}
|
|
1093
|
-
const cloned = video.cloneNode(false);
|
|
1094
|
-
cloned.crossOrigin = "anonymous";
|
|
1095
|
-
if (video.currentSrc && video.currentSrc !== video.src) {
|
|
1096
|
-
cloned.src = video.currentSrc;
|
|
1097
|
-
}
|
|
1098
|
-
const ownerDocument = cloned.ownerDocument;
|
|
1099
|
-
if (ownerDocument) {
|
|
1100
|
-
let canPlay = true;
|
|
1101
|
-
await loadMedia(cloned, { onError: () => canPlay = false, onWarn: context.log.warn });
|
|
1102
|
-
if (!canPlay) {
|
|
1103
|
-
if (video.poster) {
|
|
1104
|
-
return createImage(video.poster, video.ownerDocument);
|
|
1105
|
-
}
|
|
1106
|
-
return cloned;
|
|
1107
|
-
}
|
|
1108
|
-
cloned.currentTime = video.currentTime;
|
|
1109
|
-
await new Promise((resolve) => {
|
|
1110
|
-
cloned.addEventListener("seeked", resolve, { once: true });
|
|
1111
|
-
});
|
|
1112
|
-
const canvas = ownerDocument.createElement("canvas");
|
|
1113
|
-
canvas.width = video.offsetWidth;
|
|
1114
|
-
canvas.height = video.offsetHeight;
|
|
1115
|
-
try {
|
|
1116
|
-
const ctx = canvas.getContext("2d");
|
|
1117
|
-
if (ctx)
|
|
1118
|
-
ctx.drawImage(cloned, 0, 0, canvas.width, canvas.height);
|
|
1119
|
-
} catch (error) {
|
|
1120
|
-
context.log.warn("Failed to clone video", error);
|
|
1121
|
-
if (video.poster) {
|
|
1122
|
-
return createImage(video.poster, video.ownerDocument);
|
|
1123
|
-
}
|
|
1124
|
-
return cloned;
|
|
1125
|
-
}
|
|
1126
|
-
return cloneCanvas(canvas, context);
|
|
1127
|
-
}
|
|
1128
|
-
return cloned;
|
|
1129
|
-
}
|
|
1130
|
-
function cloneElement(node, context) {
|
|
1131
|
-
if (isCanvasElement(node)) {
|
|
1132
|
-
return cloneCanvas(node, context);
|
|
1133
|
-
}
|
|
1134
|
-
if (isIFrameElement(node)) {
|
|
1135
|
-
return cloneIframe(node, context);
|
|
1136
|
-
}
|
|
1137
|
-
if (isImageElement(node)) {
|
|
1138
|
-
return cloneImage(node);
|
|
1139
|
-
}
|
|
1140
|
-
if (isVideoElement(node)) {
|
|
1141
|
-
return cloneVideo(node, context);
|
|
1142
|
-
}
|
|
1143
|
-
return node.cloneNode(false);
|
|
1144
|
-
}
|
|
1145
|
-
function getSandBox(context) {
|
|
1146
|
-
let sandbox = context.sandbox;
|
|
1147
|
-
if (!sandbox) {
|
|
1148
|
-
const { ownerDocument } = context;
|
|
1149
|
-
try {
|
|
1150
|
-
if (ownerDocument) {
|
|
1151
|
-
sandbox = ownerDocument.createElement("iframe");
|
|
1152
|
-
sandbox.id = `__SANDBOX__${uuid()}`;
|
|
1153
|
-
sandbox.width = "0";
|
|
1154
|
-
sandbox.height = "0";
|
|
1155
|
-
sandbox.style.visibility = "hidden";
|
|
1156
|
-
sandbox.style.position = "fixed";
|
|
1157
|
-
ownerDocument.body.appendChild(sandbox);
|
|
1158
|
-
sandbox.srcdoc = '<!DOCTYPE html><meta charset="UTF-8"><title></title><body>';
|
|
1159
|
-
context.sandbox = sandbox;
|
|
1160
|
-
}
|
|
1161
|
-
} catch (error) {
|
|
1162
|
-
context.log.warn("Failed to getSandBox", error);
|
|
1163
|
-
}
|
|
1164
|
-
}
|
|
1165
|
-
return sandbox;
|
|
1166
|
-
}
|
|
1167
|
-
const ignoredStyles = [
|
|
1168
|
-
"width",
|
|
1169
|
-
"height",
|
|
1170
|
-
"-webkit-text-fill-color"
|
|
1171
|
-
];
|
|
1172
|
-
const includedAttributes = [
|
|
1173
|
-
"stroke",
|
|
1174
|
-
"fill"
|
|
1175
|
-
];
|
|
1176
|
-
function getDefaultStyle(node, pseudoElement, context) {
|
|
1177
|
-
const { defaultComputedStyles } = context;
|
|
1178
|
-
const nodeName = node.nodeName.toLowerCase();
|
|
1179
|
-
const isSvgNode = isSVGElementNode(node) && nodeName !== "svg";
|
|
1180
|
-
const attributes = isSvgNode ? includedAttributes.map((name) => [name, node.getAttribute(name)]).filter(([, value]) => value !== null) : [];
|
|
1181
|
-
const key = [
|
|
1182
|
-
isSvgNode && "svg",
|
|
1183
|
-
nodeName,
|
|
1184
|
-
attributes.map((name, value) => `${name}=${value}`).join(","),
|
|
1185
|
-
pseudoElement
|
|
1186
|
-
].filter(Boolean).join(":");
|
|
1187
|
-
if (defaultComputedStyles.has(key))
|
|
1188
|
-
return defaultComputedStyles.get(key);
|
|
1189
|
-
const sandbox = getSandBox(context);
|
|
1190
|
-
const sandboxWindow = sandbox == null ? void 0 : sandbox.contentWindow;
|
|
1191
|
-
if (!sandboxWindow)
|
|
1192
|
-
return /* @__PURE__ */ new Map();
|
|
1193
|
-
const sandboxDocument = sandboxWindow == null ? void 0 : sandboxWindow.document;
|
|
1194
|
-
let root;
|
|
1195
|
-
let el;
|
|
1196
|
-
if (isSvgNode) {
|
|
1197
|
-
root = sandboxDocument.createElementNS(XMLNS, "svg");
|
|
1198
|
-
el = root.ownerDocument.createElementNS(root.namespaceURI, nodeName);
|
|
1199
|
-
attributes.forEach(([name, value]) => {
|
|
1200
|
-
el.setAttributeNS(null, name, value);
|
|
1201
|
-
});
|
|
1202
|
-
root.appendChild(el);
|
|
1203
|
-
} else {
|
|
1204
|
-
root = el = sandboxDocument.createElement(nodeName);
|
|
1205
|
-
}
|
|
1206
|
-
el.textContent = " ";
|
|
1207
|
-
sandboxDocument.body.appendChild(root);
|
|
1208
|
-
const computedStyle = sandboxWindow.getComputedStyle(el, pseudoElement);
|
|
1209
|
-
const styles = /* @__PURE__ */ new Map();
|
|
1210
|
-
for (let len = computedStyle.length, i = 0; i < len; i++) {
|
|
1211
|
-
const name = computedStyle.item(i);
|
|
1212
|
-
if (ignoredStyles.includes(name))
|
|
1213
|
-
continue;
|
|
1214
|
-
styles.set(name, computedStyle.getPropertyValue(name));
|
|
1215
|
-
}
|
|
1216
|
-
sandboxDocument.body.removeChild(root);
|
|
1217
|
-
defaultComputedStyles.set(key, styles);
|
|
1218
|
-
return styles;
|
|
1219
|
-
}
|
|
1220
|
-
function getDiffStyle(style, defaultStyle, includeStyleProperties) {
|
|
1221
|
-
var _a2;
|
|
1222
|
-
const diffStyle = /* @__PURE__ */ new Map();
|
|
1223
|
-
const prefixs = [];
|
|
1224
|
-
const prefixTree = /* @__PURE__ */ new Map();
|
|
1225
|
-
if (includeStyleProperties) {
|
|
1226
|
-
for (const name of includeStyleProperties) {
|
|
1227
|
-
applyTo(name);
|
|
1228
|
-
}
|
|
1229
|
-
} else {
|
|
1230
|
-
for (let len = style.length, i = 0; i < len; i++) {
|
|
1231
|
-
const name = style.item(i);
|
|
1232
|
-
applyTo(name);
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
for (let len = prefixs.length, i = 0; i < len; i++) {
|
|
1236
|
-
(_a2 = prefixTree.get(prefixs[i])) == null ? void 0 : _a2.forEach((value, name) => diffStyle.set(name, value));
|
|
1237
|
-
}
|
|
1238
|
-
function applyTo(name) {
|
|
1239
|
-
const value = style.getPropertyValue(name);
|
|
1240
|
-
const priority = style.getPropertyPriority(name);
|
|
1241
|
-
const subIndex = name.lastIndexOf("-");
|
|
1242
|
-
const prefix = subIndex > -1 ? name.substring(0, subIndex) : void 0;
|
|
1243
|
-
if (prefix) {
|
|
1244
|
-
let map = prefixTree.get(prefix);
|
|
1245
|
-
if (!map) {
|
|
1246
|
-
map = /* @__PURE__ */ new Map();
|
|
1247
|
-
prefixTree.set(prefix, map);
|
|
1248
|
-
}
|
|
1249
|
-
map.set(name, [value, priority]);
|
|
1250
|
-
}
|
|
1251
|
-
if (defaultStyle.get(name) === value && !priority)
|
|
1252
|
-
return;
|
|
1253
|
-
if (prefix) {
|
|
1254
|
-
prefixs.push(prefix);
|
|
1255
|
-
} else {
|
|
1256
|
-
diffStyle.set(name, [value, priority]);
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
return diffStyle;
|
|
1260
|
-
}
|
|
1261
|
-
function copyCssStyles(node, cloned, isRoot, context) {
|
|
1262
|
-
var _a2, _b, _c, _d;
|
|
1263
|
-
const { ownerWindow, includeStyleProperties, currentParentNodeStyle } = context;
|
|
1264
|
-
const clonedStyle = cloned.style;
|
|
1265
|
-
const computedStyle = ownerWindow.getComputedStyle(node);
|
|
1266
|
-
const defaultStyle = getDefaultStyle(node, null, context);
|
|
1267
|
-
currentParentNodeStyle == null ? void 0 : currentParentNodeStyle.forEach((_, key) => {
|
|
1268
|
-
defaultStyle.delete(key);
|
|
1269
|
-
});
|
|
1270
|
-
const style = getDiffStyle(computedStyle, defaultStyle, includeStyleProperties);
|
|
1271
|
-
style.delete("transition-property");
|
|
1272
|
-
style.delete("all");
|
|
1273
|
-
style.delete("d");
|
|
1274
|
-
style.delete("content");
|
|
1275
|
-
if (isRoot) {
|
|
1276
|
-
style.delete("position");
|
|
1277
|
-
style.delete("margin-top");
|
|
1278
|
-
style.delete("margin-right");
|
|
1279
|
-
style.delete("margin-bottom");
|
|
1280
|
-
style.delete("margin-left");
|
|
1281
|
-
style.delete("margin-block-start");
|
|
1282
|
-
style.delete("margin-block-end");
|
|
1283
|
-
style.delete("margin-inline-start");
|
|
1284
|
-
style.delete("margin-inline-end");
|
|
1285
|
-
style.set("box-sizing", ["border-box", ""]);
|
|
1286
|
-
}
|
|
1287
|
-
if (((_a2 = style.get("background-clip")) == null ? void 0 : _a2[0]) === "text") {
|
|
1288
|
-
cloned.classList.add("______background-clip--text");
|
|
1289
|
-
}
|
|
1290
|
-
if (IN_CHROME) {
|
|
1291
|
-
if (!style.has("font-kerning"))
|
|
1292
|
-
style.set("font-kerning", ["normal", ""]);
|
|
1293
|
-
if ((((_b = style.get("overflow-x")) == null ? void 0 : _b[0]) === "hidden" || ((_c = style.get("overflow-y")) == null ? void 0 : _c[0]) === "hidden") && ((_d = style.get("text-overflow")) == null ? void 0 : _d[0]) === "ellipsis" && node.scrollWidth === node.clientWidth) {
|
|
1294
|
-
style.set("text-overflow", ["clip", ""]);
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
for (let len = clonedStyle.length, i = 0; i < len; i++) {
|
|
1298
|
-
clonedStyle.removeProperty(clonedStyle.item(i));
|
|
1299
|
-
}
|
|
1300
|
-
style.forEach(([value, priority], name) => {
|
|
1301
|
-
clonedStyle.setProperty(name, value, priority);
|
|
1302
|
-
});
|
|
1303
|
-
return style;
|
|
1304
|
-
}
|
|
1305
|
-
function copyInputValue(node, cloned) {
|
|
1306
|
-
if (isTextareaElement(node) || isInputElement(node) || isSelectElement(node)) {
|
|
1307
|
-
cloned.setAttribute("value", node.value);
|
|
1308
|
-
}
|
|
1309
|
-
}
|
|
1310
|
-
const pseudoClasses = [
|
|
1311
|
-
"::before",
|
|
1312
|
-
"::after"
|
|
1313
|
-
// '::placeholder', TODO
|
|
1314
|
-
];
|
|
1315
|
-
const scrollbarPseudoClasses = [
|
|
1316
|
-
"::-webkit-scrollbar",
|
|
1317
|
-
"::-webkit-scrollbar-button",
|
|
1318
|
-
// '::-webkit-scrollbar:horizontal', TODO
|
|
1319
|
-
"::-webkit-scrollbar-thumb",
|
|
1320
|
-
"::-webkit-scrollbar-track",
|
|
1321
|
-
"::-webkit-scrollbar-track-piece",
|
|
1322
|
-
// '::-webkit-scrollbar:vertical', TODO
|
|
1323
|
-
"::-webkit-scrollbar-corner",
|
|
1324
|
-
"::-webkit-resizer"
|
|
1325
|
-
];
|
|
1326
|
-
function copyPseudoClass(node, cloned, copyScrollbar, context, addWordToFontFamilies) {
|
|
1327
|
-
const { ownerWindow, svgStyleElement, svgStyles, currentNodeStyle } = context;
|
|
1328
|
-
if (!svgStyleElement || !ownerWindow)
|
|
1329
|
-
return;
|
|
1330
|
-
function copyBy(pseudoClass) {
|
|
1331
|
-
var _a2;
|
|
1332
|
-
const computedStyle = ownerWindow.getComputedStyle(node, pseudoClass);
|
|
1333
|
-
let content = computedStyle.getPropertyValue("content");
|
|
1334
|
-
if (!content || content === "none")
|
|
1335
|
-
return;
|
|
1336
|
-
addWordToFontFamilies == null ? void 0 : addWordToFontFamilies(content);
|
|
1337
|
-
content = content.replace(/(')|(")|(counter\(.+\))/g, "");
|
|
1338
|
-
const klasses = [uuid()];
|
|
1339
|
-
const defaultStyle = getDefaultStyle(node, pseudoClass, context);
|
|
1340
|
-
currentNodeStyle == null ? void 0 : currentNodeStyle.forEach((_, key) => {
|
|
1341
|
-
defaultStyle.delete(key);
|
|
1342
|
-
});
|
|
1343
|
-
const style = getDiffStyle(computedStyle, defaultStyle, context.includeStyleProperties);
|
|
1344
|
-
style.delete("content");
|
|
1345
|
-
style.delete("-webkit-locale");
|
|
1346
|
-
if (((_a2 = style.get("background-clip")) == null ? void 0 : _a2[0]) === "text") {
|
|
1347
|
-
cloned.classList.add("______background-clip--text");
|
|
1348
|
-
}
|
|
1349
|
-
const cloneStyle = [
|
|
1350
|
-
`content: '${content}';`
|
|
1351
|
-
];
|
|
1352
|
-
style.forEach(([value, priority], name) => {
|
|
1353
|
-
cloneStyle.push(`${name}: ${value}${priority ? " !important" : ""};`);
|
|
1354
|
-
});
|
|
1355
|
-
if (cloneStyle.length === 1)
|
|
1356
|
-
return;
|
|
1357
|
-
try {
|
|
1358
|
-
cloned.className = [cloned.className, ...klasses].join(" ");
|
|
1359
|
-
} catch (err) {
|
|
1360
|
-
context.log.warn("Failed to copyPseudoClass", err);
|
|
1361
|
-
return;
|
|
1362
|
-
}
|
|
1363
|
-
const cssText = cloneStyle.join("\n ");
|
|
1364
|
-
let allClasses = svgStyles.get(cssText);
|
|
1365
|
-
if (!allClasses) {
|
|
1366
|
-
allClasses = [];
|
|
1367
|
-
svgStyles.set(cssText, allClasses);
|
|
1368
|
-
}
|
|
1369
|
-
allClasses.push(`.${klasses[0]}${pseudoClass}`);
|
|
1370
|
-
}
|
|
1371
|
-
pseudoClasses.forEach(copyBy);
|
|
1372
|
-
if (copyScrollbar)
|
|
1373
|
-
scrollbarPseudoClasses.forEach(copyBy);
|
|
1374
|
-
}
|
|
1375
|
-
const excludeParentNodes = /* @__PURE__ */ new Set([
|
|
1376
|
-
"symbol"
|
|
1377
|
-
// test/fixtures/svg.symbol.html
|
|
1378
|
-
]);
|
|
1379
|
-
async function appendChildNode(node, cloned, child, context, addWordToFontFamilies) {
|
|
1380
|
-
if (isElementNode(child) && (isStyleElement(child) || isScriptElement(child)))
|
|
1381
|
-
return;
|
|
1382
|
-
if (context.filter && !context.filter(child))
|
|
1383
|
-
return;
|
|
1384
|
-
if (excludeParentNodes.has(cloned.nodeName) || excludeParentNodes.has(child.nodeName)) {
|
|
1385
|
-
context.currentParentNodeStyle = void 0;
|
|
1386
|
-
} else {
|
|
1387
|
-
context.currentParentNodeStyle = context.currentNodeStyle;
|
|
1388
|
-
}
|
|
1389
|
-
const childCloned = await cloneNode(child, context, false, addWordToFontFamilies);
|
|
1390
|
-
if (context.isEnable("restoreScrollPosition")) {
|
|
1391
|
-
restoreScrollPosition(node, childCloned);
|
|
1392
|
-
}
|
|
1393
|
-
cloned.appendChild(childCloned);
|
|
1394
|
-
}
|
|
1395
|
-
async function cloneChildNodes(node, cloned, context, addWordToFontFamilies) {
|
|
1396
|
-
var _a2;
|
|
1397
|
-
let firstChild = node.firstChild;
|
|
1398
|
-
if (isElementNode(node)) {
|
|
1399
|
-
if (node.shadowRoot) {
|
|
1400
|
-
firstChild = (_a2 = node.shadowRoot) == null ? void 0 : _a2.firstChild;
|
|
1401
|
-
context.shadowRoots.push(node.shadowRoot);
|
|
1402
|
-
}
|
|
1403
|
-
}
|
|
1404
|
-
for (let child = firstChild; child; child = child.nextSibling) {
|
|
1405
|
-
if (isCommentNode(child))
|
|
1406
|
-
continue;
|
|
1407
|
-
if (isElementNode(child) && isSlotElement(child) && typeof child.assignedNodes === "function") {
|
|
1408
|
-
const nodes = child.assignedNodes();
|
|
1409
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
1410
|
-
await appendChildNode(node, cloned, nodes[i], context, addWordToFontFamilies);
|
|
1411
|
-
}
|
|
1412
|
-
} else {
|
|
1413
|
-
await appendChildNode(node, cloned, child, context, addWordToFontFamilies);
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
function restoreScrollPosition(node, chlidCloned) {
|
|
1418
|
-
if (!isHTMLElementNode(node) || !isHTMLElementNode(chlidCloned))
|
|
1419
|
-
return;
|
|
1420
|
-
const { scrollTop, scrollLeft } = node;
|
|
1421
|
-
if (!scrollTop && !scrollLeft) {
|
|
1422
|
-
return;
|
|
1423
|
-
}
|
|
1424
|
-
const { transform } = chlidCloned.style;
|
|
1425
|
-
const matrix = new DOMMatrix(transform);
|
|
1426
|
-
const { a, b, c, d } = matrix;
|
|
1427
|
-
matrix.a = 1;
|
|
1428
|
-
matrix.b = 0;
|
|
1429
|
-
matrix.c = 0;
|
|
1430
|
-
matrix.d = 1;
|
|
1431
|
-
matrix.translateSelf(-scrollLeft, -scrollTop);
|
|
1432
|
-
matrix.a = a;
|
|
1433
|
-
matrix.b = b;
|
|
1434
|
-
matrix.c = c;
|
|
1435
|
-
matrix.d = d;
|
|
1436
|
-
chlidCloned.style.transform = matrix.toString();
|
|
1437
|
-
}
|
|
1438
|
-
function applyCssStyleWithOptions(cloned, context) {
|
|
1439
|
-
const { backgroundColor, width, height, style: styles } = context;
|
|
1440
|
-
const clonedStyle = cloned.style;
|
|
1441
|
-
if (backgroundColor)
|
|
1442
|
-
clonedStyle.setProperty("background-color", backgroundColor, "important");
|
|
1443
|
-
if (width)
|
|
1444
|
-
clonedStyle.setProperty("width", `${width}px`, "important");
|
|
1445
|
-
if (height)
|
|
1446
|
-
clonedStyle.setProperty("height", `${height}px`, "important");
|
|
1447
|
-
if (styles) {
|
|
1448
|
-
for (const name in styles) clonedStyle[name] = styles[name];
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
const NORMAL_ATTRIBUTE_RE = /^[\w-:]+$/;
|
|
1452
|
-
async function cloneNode(node, context, isRoot = false, addWordToFontFamilies) {
|
|
1453
|
-
var _a2, _b, _c, _d;
|
|
1454
|
-
const { ownerDocument, ownerWindow, fontFamilies, onCloneEachNode } = context;
|
|
1455
|
-
if (ownerDocument && isTextNode(node)) {
|
|
1456
|
-
if (addWordToFontFamilies && /\S/.test(node.data)) {
|
|
1457
|
-
addWordToFontFamilies(node.data);
|
|
1458
|
-
}
|
|
1459
|
-
return ownerDocument.createTextNode(node.data);
|
|
1460
|
-
}
|
|
1461
|
-
if (ownerDocument && ownerWindow && isElementNode(node) && (isHTMLElementNode(node) || isSVGElementNode(node))) {
|
|
1462
|
-
const cloned2 = await cloneElement(node, context);
|
|
1463
|
-
if (context.isEnable("removeAbnormalAttributes")) {
|
|
1464
|
-
const names = cloned2.getAttributeNames();
|
|
1465
|
-
for (let len = names.length, i = 0; i < len; i++) {
|
|
1466
|
-
const name = names[i];
|
|
1467
|
-
if (!NORMAL_ATTRIBUTE_RE.test(name)) {
|
|
1468
|
-
cloned2.removeAttribute(name);
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
}
|
|
1472
|
-
const style = context.currentNodeStyle = copyCssStyles(node, cloned2, isRoot, context);
|
|
1473
|
-
if (isRoot)
|
|
1474
|
-
applyCssStyleWithOptions(cloned2, context);
|
|
1475
|
-
let copyScrollbar = false;
|
|
1476
|
-
if (context.isEnable("copyScrollbar")) {
|
|
1477
|
-
const overflow = [
|
|
1478
|
-
(_a2 = style.get("overflow-x")) == null ? void 0 : _a2[0],
|
|
1479
|
-
(_b = style.get("overflow-y")) == null ? void 0 : _b[0]
|
|
1480
|
-
];
|
|
1481
|
-
copyScrollbar = overflow.includes("scroll") || (overflow.includes("auto") || overflow.includes("overlay")) && (node.scrollHeight > node.clientHeight || node.scrollWidth > node.clientWidth);
|
|
1482
|
-
}
|
|
1483
|
-
const textTransform = (_c = style.get("text-transform")) == null ? void 0 : _c[0];
|
|
1484
|
-
const families = splitFontFamily((_d = style.get("font-family")) == null ? void 0 : _d[0]);
|
|
1485
|
-
const addWordToFontFamilies2 = families ? (word) => {
|
|
1486
|
-
if (textTransform === "uppercase") {
|
|
1487
|
-
word = word.toUpperCase();
|
|
1488
|
-
} else if (textTransform === "lowercase") {
|
|
1489
|
-
word = word.toLowerCase();
|
|
1490
|
-
} else if (textTransform === "capitalize") {
|
|
1491
|
-
word = word[0].toUpperCase() + word.substring(1);
|
|
1492
|
-
}
|
|
1493
|
-
families.forEach((family) => {
|
|
1494
|
-
let fontFamily = fontFamilies.get(family);
|
|
1495
|
-
if (!fontFamily) {
|
|
1496
|
-
fontFamilies.set(family, fontFamily = /* @__PURE__ */ new Set());
|
|
1497
|
-
}
|
|
1498
|
-
word.split("").forEach((text) => fontFamily.add(text));
|
|
1499
|
-
});
|
|
1500
|
-
} : void 0;
|
|
1501
|
-
copyPseudoClass(
|
|
1502
|
-
node,
|
|
1503
|
-
cloned2,
|
|
1504
|
-
copyScrollbar,
|
|
1505
|
-
context,
|
|
1506
|
-
addWordToFontFamilies2
|
|
1507
|
-
);
|
|
1508
|
-
copyInputValue(node, cloned2);
|
|
1509
|
-
if (!isVideoElement(node)) {
|
|
1510
|
-
await cloneChildNodes(
|
|
1511
|
-
node,
|
|
1512
|
-
cloned2,
|
|
1513
|
-
context,
|
|
1514
|
-
addWordToFontFamilies2
|
|
1515
|
-
);
|
|
1516
|
-
}
|
|
1517
|
-
await (onCloneEachNode == null ? void 0 : onCloneEachNode(cloned2));
|
|
1518
|
-
return cloned2;
|
|
1519
|
-
}
|
|
1520
|
-
const cloned = node.cloneNode(false);
|
|
1521
|
-
await cloneChildNodes(node, cloned, context);
|
|
1522
|
-
await (onCloneEachNode == null ? void 0 : onCloneEachNode(cloned));
|
|
1523
|
-
return cloned;
|
|
1524
|
-
}
|
|
1525
|
-
function destroyContext(context) {
|
|
1526
|
-
context.ownerDocument = void 0;
|
|
1527
|
-
context.ownerWindow = void 0;
|
|
1528
|
-
context.svgStyleElement = void 0;
|
|
1529
|
-
context.svgDefsElement = void 0;
|
|
1530
|
-
context.svgStyles.clear();
|
|
1531
|
-
context.defaultComputedStyles.clear();
|
|
1532
|
-
if (context.sandbox) {
|
|
1533
|
-
try {
|
|
1534
|
-
context.sandbox.remove();
|
|
1535
|
-
} catch (err) {
|
|
1536
|
-
context.log.warn("Failed to destroyContext", err);
|
|
1537
|
-
}
|
|
1538
|
-
context.sandbox = void 0;
|
|
1539
|
-
}
|
|
1540
|
-
context.workers = [];
|
|
1541
|
-
context.fontFamilies.clear();
|
|
1542
|
-
context.fontCssTexts.clear();
|
|
1543
|
-
context.requests.clear();
|
|
1544
|
-
context.tasks = [];
|
|
1545
|
-
context.shadowRoots = [];
|
|
1546
|
-
}
|
|
1547
|
-
function baseFetch(options) {
|
|
1548
|
-
const { url, timeout, responseType, ...requestInit } = options;
|
|
1549
|
-
const controller = new AbortController();
|
|
1550
|
-
const timer = timeout ? setTimeout(() => controller.abort(), timeout) : void 0;
|
|
1551
|
-
return fetch(url, { signal: controller.signal, ...requestInit }).then((response) => {
|
|
1552
|
-
if (!response.ok) {
|
|
1553
|
-
throw new Error("Failed fetch, not 2xx response", { cause: response });
|
|
1554
|
-
}
|
|
1555
|
-
switch (responseType) {
|
|
1556
|
-
case "arrayBuffer":
|
|
1557
|
-
return response.arrayBuffer();
|
|
1558
|
-
case "dataUrl":
|
|
1559
|
-
return response.blob().then(blobToDataUrl);
|
|
1560
|
-
case "text":
|
|
1561
|
-
default:
|
|
1562
|
-
return response.text();
|
|
1563
|
-
}
|
|
1564
|
-
}).finally(() => clearTimeout(timer));
|
|
1565
|
-
}
|
|
1566
|
-
function contextFetch(context, options) {
|
|
1567
|
-
const { url: rawUrl, requestType = "text", responseType = "text", imageDom } = options;
|
|
1568
|
-
let url = rawUrl;
|
|
1569
|
-
const {
|
|
1570
|
-
timeout,
|
|
1571
|
-
acceptOfImage,
|
|
1572
|
-
requests,
|
|
1573
|
-
fetchFn,
|
|
1574
|
-
fetch: {
|
|
1575
|
-
requestInit,
|
|
1576
|
-
bypassingCache,
|
|
1577
|
-
placeholderImage
|
|
1578
|
-
},
|
|
1579
|
-
font,
|
|
1580
|
-
workers,
|
|
1581
|
-
fontFamilies
|
|
1582
|
-
} = context;
|
|
1583
|
-
if (requestType === "image" && (IN_SAFARI || IN_FIREFOX)) {
|
|
1584
|
-
context.drawImageCount++;
|
|
1585
|
-
}
|
|
1586
|
-
let request = requests.get(rawUrl);
|
|
1587
|
-
if (!request) {
|
|
1588
|
-
if (bypassingCache) {
|
|
1589
|
-
if (bypassingCache instanceof RegExp && bypassingCache.test(url)) {
|
|
1590
|
-
url += (/\?/.test(url) ? "&" : "?") + (/* @__PURE__ */ new Date()).getTime();
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
const canFontMinify = requestType.startsWith("font") && font && font.minify;
|
|
1594
|
-
const fontTexts = /* @__PURE__ */ new Set();
|
|
1595
|
-
if (canFontMinify) {
|
|
1596
|
-
const families = requestType.split(";")[1].split(",");
|
|
1597
|
-
families.forEach((family) => {
|
|
1598
|
-
if (!fontFamilies.has(family))
|
|
1599
|
-
return;
|
|
1600
|
-
fontFamilies.get(family).forEach((text) => fontTexts.add(text));
|
|
1601
|
-
});
|
|
1602
|
-
}
|
|
1603
|
-
const needFontMinify = canFontMinify && fontTexts.size;
|
|
1604
|
-
const baseFetchOptions = {
|
|
1605
|
-
url,
|
|
1606
|
-
timeout,
|
|
1607
|
-
responseType: needFontMinify ? "arrayBuffer" : responseType,
|
|
1608
|
-
headers: requestType === "image" ? { accept: acceptOfImage } : void 0,
|
|
1609
|
-
...requestInit
|
|
1610
|
-
};
|
|
1611
|
-
request = {
|
|
1612
|
-
type: requestType,
|
|
1613
|
-
resolve: void 0,
|
|
1614
|
-
reject: void 0,
|
|
1615
|
-
response: null
|
|
1616
|
-
};
|
|
1617
|
-
request.response = (async () => {
|
|
1618
|
-
if (fetchFn && requestType === "image") {
|
|
1619
|
-
const result = await fetchFn(rawUrl);
|
|
1620
|
-
if (result)
|
|
1621
|
-
return result;
|
|
1622
|
-
}
|
|
1623
|
-
if (!IN_SAFARI && rawUrl.startsWith("http") && workers.length) {
|
|
1624
|
-
return new Promise((resolve, reject) => {
|
|
1625
|
-
const worker = workers[requests.size & workers.length - 1];
|
|
1626
|
-
worker.postMessage({ rawUrl, ...baseFetchOptions });
|
|
1627
|
-
request.resolve = resolve;
|
|
1628
|
-
request.reject = reject;
|
|
1629
|
-
});
|
|
1630
|
-
}
|
|
1631
|
-
return baseFetch(baseFetchOptions);
|
|
1632
|
-
})().catch((error) => {
|
|
1633
|
-
requests.delete(rawUrl);
|
|
1634
|
-
if (requestType === "image" && placeholderImage) {
|
|
1635
|
-
context.log.warn("Failed to fetch image base64, trying to use placeholder image", url);
|
|
1636
|
-
return typeof placeholderImage === "string" ? placeholderImage : placeholderImage(imageDom);
|
|
1637
|
-
}
|
|
1638
|
-
throw error;
|
|
1639
|
-
});
|
|
1640
|
-
requests.set(rawUrl, request);
|
|
1641
|
-
}
|
|
1642
|
-
return request.response;
|
|
1643
|
-
}
|
|
1644
|
-
async function replaceCssUrlToDataUrl(cssText, baseUrl, context, isImage) {
|
|
1645
|
-
if (!hasCssUrl(cssText))
|
|
1646
|
-
return cssText;
|
|
1647
|
-
for (const [rawUrl, url] of parseCssUrls(cssText, baseUrl)) {
|
|
1648
|
-
try {
|
|
1649
|
-
const dataUrl = await contextFetch(
|
|
1650
|
-
context,
|
|
1651
|
-
{
|
|
1652
|
-
url,
|
|
1653
|
-
requestType: isImage ? "image" : "text",
|
|
1654
|
-
responseType: "dataUrl"
|
|
1655
|
-
}
|
|
1656
|
-
);
|
|
1657
|
-
cssText = cssText.replace(toRE(rawUrl), `$1${dataUrl}$3`);
|
|
1658
|
-
} catch (error) {
|
|
1659
|
-
context.log.warn("Failed to fetch css data url", rawUrl, error);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
return cssText;
|
|
1663
|
-
}
|
|
1664
|
-
function hasCssUrl(cssText) {
|
|
1665
|
-
return /url\((['"]?)([^'"]+?)\1\)/.test(cssText);
|
|
1666
|
-
}
|
|
1667
|
-
const URL_RE = /url\((['"]?)([^'"]+?)\1\)/g;
|
|
1668
|
-
function parseCssUrls(cssText, baseUrl) {
|
|
1669
|
-
const result = [];
|
|
1670
|
-
cssText.replace(URL_RE, (raw, quotation, url) => {
|
|
1671
|
-
result.push([url, resolveUrl(url, baseUrl)]);
|
|
1672
|
-
return raw;
|
|
1673
|
-
});
|
|
1674
|
-
return result.filter(([url]) => !isDataUrl(url));
|
|
1675
|
-
}
|
|
1676
|
-
function toRE(url) {
|
|
1677
|
-
const escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, "\\$1");
|
|
1678
|
-
return new RegExp(`(url\\(['"]?)(${escaped})(['"]?\\))`, "g");
|
|
1679
|
-
}
|
|
1680
|
-
const properties = [
|
|
1681
|
-
"background-image",
|
|
1682
|
-
"border-image-source",
|
|
1683
|
-
"-webkit-border-image",
|
|
1684
|
-
"-webkit-mask-image",
|
|
1685
|
-
"list-style-image"
|
|
1686
|
-
];
|
|
1687
|
-
function embedCssStyleImage(style, context) {
|
|
1688
|
-
return properties.map((property) => {
|
|
1689
|
-
const value = style.getPropertyValue(property);
|
|
1690
|
-
if (!value || value === "none") {
|
|
1691
|
-
return null;
|
|
1692
|
-
}
|
|
1693
|
-
if (IN_SAFARI || IN_FIREFOX) {
|
|
1694
|
-
context.drawImageCount++;
|
|
1695
|
-
}
|
|
1696
|
-
return replaceCssUrlToDataUrl(value, null, context, true).then((newValue) => {
|
|
1697
|
-
if (!newValue || value === newValue)
|
|
1698
|
-
return;
|
|
1699
|
-
style.setProperty(
|
|
1700
|
-
property,
|
|
1701
|
-
newValue,
|
|
1702
|
-
style.getPropertyPriority(property)
|
|
1703
|
-
);
|
|
1704
|
-
});
|
|
1705
|
-
}).filter(Boolean);
|
|
1706
|
-
}
|
|
1707
|
-
function embedImageElement(cloned, context) {
|
|
1708
|
-
if (isImageElement(cloned)) {
|
|
1709
|
-
const originalSrc = cloned.currentSrc || cloned.src;
|
|
1710
|
-
if (!isDataUrl(originalSrc)) {
|
|
1711
|
-
return [
|
|
1712
|
-
contextFetch(context, {
|
|
1713
|
-
url: originalSrc,
|
|
1714
|
-
imageDom: cloned,
|
|
1715
|
-
requestType: "image",
|
|
1716
|
-
responseType: "dataUrl"
|
|
1717
|
-
}).then((url) => {
|
|
1718
|
-
if (!url)
|
|
1719
|
-
return;
|
|
1720
|
-
cloned.srcset = "";
|
|
1721
|
-
cloned.dataset.originalSrc = originalSrc;
|
|
1722
|
-
cloned.src = url || "";
|
|
1723
|
-
})
|
|
1724
|
-
];
|
|
1725
|
-
}
|
|
1726
|
-
if (IN_SAFARI || IN_FIREFOX) {
|
|
1727
|
-
context.drawImageCount++;
|
|
1728
|
-
}
|
|
1729
|
-
} else if (isSVGElementNode(cloned) && !isDataUrl(cloned.href.baseVal)) {
|
|
1730
|
-
const originalSrc = cloned.href.baseVal;
|
|
1731
|
-
return [
|
|
1732
|
-
contextFetch(context, {
|
|
1733
|
-
url: originalSrc,
|
|
1734
|
-
imageDom: cloned,
|
|
1735
|
-
requestType: "image",
|
|
1736
|
-
responseType: "dataUrl"
|
|
1737
|
-
}).then((url) => {
|
|
1738
|
-
if (!url)
|
|
1739
|
-
return;
|
|
1740
|
-
cloned.dataset.originalSrc = originalSrc;
|
|
1741
|
-
cloned.href.baseVal = url || "";
|
|
1742
|
-
})
|
|
1743
|
-
];
|
|
1744
|
-
}
|
|
1745
|
-
return [];
|
|
1746
|
-
}
|
|
1747
|
-
function embedSvgUse(cloned, context) {
|
|
1748
|
-
const { ownerDocument, svgDefsElement } = context;
|
|
1749
|
-
const href = cloned.getAttribute("href") ?? cloned.getAttribute("xlink:href");
|
|
1750
|
-
if (!href)
|
|
1751
|
-
return [];
|
|
1752
|
-
const [svgUrl, id] = href.split("#");
|
|
1753
|
-
if (id) {
|
|
1754
|
-
const query = `#${id}`;
|
|
1755
|
-
const definition = context.shadowRoots.reduce(
|
|
1756
|
-
(res, root) => {
|
|
1757
|
-
return res ?? root.querySelector(`svg ${query}`);
|
|
1758
|
-
},
|
|
1759
|
-
ownerDocument == null ? void 0 : ownerDocument.querySelector(`svg ${query}`)
|
|
1760
|
-
);
|
|
1761
|
-
if (svgUrl) {
|
|
1762
|
-
cloned.setAttribute("href", query);
|
|
1763
|
-
}
|
|
1764
|
-
if (svgDefsElement == null ? void 0 : svgDefsElement.querySelector(query))
|
|
1765
|
-
return [];
|
|
1766
|
-
if (definition) {
|
|
1767
|
-
svgDefsElement == null ? void 0 : svgDefsElement.appendChild(definition.cloneNode(true));
|
|
1768
|
-
return [];
|
|
1769
|
-
} else if (svgUrl) {
|
|
1770
|
-
return [
|
|
1771
|
-
contextFetch(context, {
|
|
1772
|
-
url: svgUrl,
|
|
1773
|
-
responseType: "text"
|
|
1774
|
-
}).then((svgData) => {
|
|
1775
|
-
svgDefsElement == null ? void 0 : svgDefsElement.insertAdjacentHTML("beforeend", svgData);
|
|
1776
|
-
})
|
|
1777
|
-
];
|
|
1778
|
-
}
|
|
1779
|
-
}
|
|
1780
|
-
return [];
|
|
1781
|
-
}
|
|
1782
|
-
function embedNode(cloned, context) {
|
|
1783
|
-
const { tasks } = context;
|
|
1784
|
-
if (isElementNode(cloned)) {
|
|
1785
|
-
if (isImageElement(cloned) || isSVGImageElementNode(cloned)) {
|
|
1786
|
-
tasks.push(...embedImageElement(cloned, context));
|
|
1787
|
-
}
|
|
1788
|
-
if (isSVGUseElementNode(cloned)) {
|
|
1789
|
-
tasks.push(...embedSvgUse(cloned, context));
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
if (isHTMLElementNode(cloned)) {
|
|
1793
|
-
tasks.push(...embedCssStyleImage(cloned.style, context));
|
|
1794
|
-
}
|
|
1795
|
-
cloned.childNodes.forEach((child) => {
|
|
1796
|
-
embedNode(child, context);
|
|
1797
|
-
});
|
|
1798
|
-
}
|
|
1799
|
-
async function embedWebFont(clone, context) {
|
|
1800
|
-
const {
|
|
1801
|
-
ownerDocument,
|
|
1802
|
-
svgStyleElement,
|
|
1803
|
-
fontFamilies,
|
|
1804
|
-
fontCssTexts,
|
|
1805
|
-
tasks,
|
|
1806
|
-
font
|
|
1807
|
-
} = context;
|
|
1808
|
-
if (!ownerDocument || !svgStyleElement || !fontFamilies.size) {
|
|
1809
|
-
return;
|
|
1810
|
-
}
|
|
1811
|
-
if (font && font.cssText) {
|
|
1812
|
-
const cssText = filterPreferredFormat(font.cssText, context);
|
|
1813
|
-
svgStyleElement.appendChild(ownerDocument.createTextNode(`${cssText}
|
|
1814
|
-
`));
|
|
1815
|
-
} else {
|
|
1816
|
-
const styleSheets = Array.from(ownerDocument.styleSheets).filter((styleSheet) => {
|
|
1817
|
-
try {
|
|
1818
|
-
return "cssRules" in styleSheet && Boolean(styleSheet.cssRules.length);
|
|
1819
|
-
} catch (error) {
|
|
1820
|
-
context.log.warn(`Error while reading CSS rules from ${styleSheet.href}`, error);
|
|
1821
|
-
return false;
|
|
1822
|
-
}
|
|
1823
|
-
});
|
|
1824
|
-
const tempDoc = ownerDocument.implementation.createHTMLDocument("");
|
|
1825
|
-
const tempStyleEl = tempDoc.createElement("style");
|
|
1826
|
-
tempDoc.head.appendChild(tempStyleEl);
|
|
1827
|
-
const tempStyleSheet = tempStyleEl.sheet;
|
|
1828
|
-
await Promise.all(
|
|
1829
|
-
styleSheets.flatMap((styleSheet) => {
|
|
1830
|
-
return Array.from(styleSheet.cssRules).map(async (cssRule) => {
|
|
1831
|
-
if (isCSSImportRule(cssRule)) {
|
|
1832
|
-
const baseUrl = cssRule.href;
|
|
1833
|
-
let cssText = "";
|
|
1834
|
-
try {
|
|
1835
|
-
cssText = await contextFetch(context, {
|
|
1836
|
-
url: baseUrl,
|
|
1837
|
-
requestType: "text",
|
|
1838
|
-
responseType: "text"
|
|
1839
|
-
});
|
|
1840
|
-
} catch (error) {
|
|
1841
|
-
context.log.warn(`Error fetch remote css import from ${baseUrl}`, error);
|
|
1842
|
-
}
|
|
1843
|
-
const replacedCssText = cssText.replace(
|
|
1844
|
-
URL_RE,
|
|
1845
|
-
(raw, quotation, url) => raw.replace(url, resolveUrl(url, baseUrl))
|
|
1846
|
-
);
|
|
1847
|
-
for (const rule of parseCss(replacedCssText)) {
|
|
1848
|
-
try {
|
|
1849
|
-
tempStyleSheet.insertRule(rule, tempStyleSheet.cssRules.length);
|
|
1850
|
-
} catch (error) {
|
|
1851
|
-
context.log.warn("Error inserting rule from remote css import", { rule, error });
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
});
|
|
1856
|
-
})
|
|
1857
|
-
);
|
|
1858
|
-
if (tempStyleSheet.cssRules.length)
|
|
1859
|
-
styleSheets.push(tempStyleSheet);
|
|
1860
|
-
const cssRules = [];
|
|
1861
|
-
styleSheets.forEach((sheet) => {
|
|
1862
|
-
unwrapCssLayers(sheet.cssRules, cssRules);
|
|
1863
|
-
});
|
|
1864
|
-
cssRules.filter((cssRule) => {
|
|
1865
|
-
var _a2;
|
|
1866
|
-
return isCssFontFaceRule(cssRule) && hasCssUrl(cssRule.style.getPropertyValue("src")) && ((_a2 = splitFontFamily(cssRule.style.getPropertyValue("font-family"))) == null ? void 0 : _a2.some((val) => fontFamilies.has(val)));
|
|
1867
|
-
}).forEach((value) => {
|
|
1868
|
-
const rule = value;
|
|
1869
|
-
const cssText = fontCssTexts.get(rule.cssText);
|
|
1870
|
-
if (cssText) {
|
|
1871
|
-
svgStyleElement.appendChild(ownerDocument.createTextNode(`${cssText}
|
|
1872
|
-
`));
|
|
1873
|
-
} else {
|
|
1874
|
-
tasks.push(
|
|
1875
|
-
replaceCssUrlToDataUrl(
|
|
1876
|
-
rule.cssText,
|
|
1877
|
-
rule.parentStyleSheet ? rule.parentStyleSheet.href : null,
|
|
1878
|
-
context
|
|
1879
|
-
).then((cssText2) => {
|
|
1880
|
-
cssText2 = filterPreferredFormat(cssText2, context);
|
|
1881
|
-
fontCssTexts.set(rule.cssText, cssText2);
|
|
1882
|
-
svgStyleElement.appendChild(ownerDocument.createTextNode(`${cssText2}
|
|
1883
|
-
`));
|
|
1884
|
-
})
|
|
1885
|
-
);
|
|
1886
|
-
}
|
|
1887
|
-
});
|
|
1888
|
-
}
|
|
1889
|
-
}
|
|
1890
|
-
const COMMENTS_RE = /(\/\*[\s\S]*?\*\/)/g;
|
|
1891
|
-
const KEYFRAMES_RE = /((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi;
|
|
1892
|
-
function parseCss(source) {
|
|
1893
|
-
if (source == null)
|
|
1894
|
-
return [];
|
|
1895
|
-
const result = [];
|
|
1896
|
-
let cssText = source.replace(COMMENTS_RE, "");
|
|
1897
|
-
while (true) {
|
|
1898
|
-
const matches = KEYFRAMES_RE.exec(cssText);
|
|
1899
|
-
if (!matches)
|
|
1900
|
-
break;
|
|
1901
|
-
result.push(matches[0]);
|
|
1902
|
-
}
|
|
1903
|
-
cssText = cssText.replace(KEYFRAMES_RE, "");
|
|
1904
|
-
const IMPORT_RE = /@import[\s\S]*?url\([^)]*\)[\s\S]*?;/gi;
|
|
1905
|
-
const UNIFIED_RE = new RegExp(
|
|
1906
|
-
// eslint-disable-next-line
|
|
1907
|
-
"((\\s*?(?:\\/\\*[\\s\\S]*?\\*\\/)?\\s*?@media[\\s\\S]*?){([\\s\\S]*?)}\\s*?})|(([\\s\\S]*?){([\\s\\S]*?)})",
|
|
1908
|
-
"gi"
|
|
1909
|
-
);
|
|
1910
|
-
while (true) {
|
|
1911
|
-
let matches = IMPORT_RE.exec(cssText);
|
|
1912
|
-
if (!matches) {
|
|
1913
|
-
matches = UNIFIED_RE.exec(cssText);
|
|
1914
|
-
if (!matches) {
|
|
1915
|
-
break;
|
|
1916
|
-
} else {
|
|
1917
|
-
IMPORT_RE.lastIndex = UNIFIED_RE.lastIndex;
|
|
1918
|
-
}
|
|
1919
|
-
} else {
|
|
1920
|
-
UNIFIED_RE.lastIndex = IMPORT_RE.lastIndex;
|
|
1921
|
-
}
|
|
1922
|
-
result.push(matches[0]);
|
|
1923
|
-
}
|
|
1924
|
-
return result;
|
|
1925
|
-
}
|
|
1926
|
-
const URL_WITH_FORMAT_RE = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g;
|
|
1927
|
-
const FONT_SRC_RE = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g;
|
|
1928
|
-
function filterPreferredFormat(str, context) {
|
|
1929
|
-
const { font } = context;
|
|
1930
|
-
const preferredFormat = font ? font == null ? void 0 : font.preferredFormat : void 0;
|
|
1931
|
-
return preferredFormat ? str.replace(FONT_SRC_RE, (match) => {
|
|
1932
|
-
while (true) {
|
|
1933
|
-
const [src, , format] = URL_WITH_FORMAT_RE.exec(match) || [];
|
|
1934
|
-
if (!format)
|
|
1935
|
-
return "";
|
|
1936
|
-
if (format === preferredFormat)
|
|
1937
|
-
return `src: ${src};`;
|
|
1938
|
-
}
|
|
1939
|
-
}) : str;
|
|
1940
|
-
}
|
|
1941
|
-
function unwrapCssLayers(rules, out = []) {
|
|
1942
|
-
for (const rule of Array.from(rules)) {
|
|
1943
|
-
if (isLayerBlockRule(rule)) {
|
|
1944
|
-
out.push(...unwrapCssLayers(rule.cssRules));
|
|
1945
|
-
} else if ("cssRules" in rule) {
|
|
1946
|
-
unwrapCssLayers(rule.cssRules, out);
|
|
1947
|
-
} else {
|
|
1948
|
-
out.push(rule);
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
return out;
|
|
1952
|
-
}
|
|
1953
|
-
const SVG_EXTERNAL_RESOURCE_REGEX = /\bx?link:?href\s*=\s*["'](?!data:)[^"']+["']/i;
|
|
1954
|
-
function svgHasExternalResources(svg) {
|
|
1955
|
-
return SVG_EXTERNAL_RESOURCE_REGEX.test(svg.innerHTML);
|
|
1956
|
-
}
|
|
1957
|
-
async function domToForeignObjectSvg(node, options) {
|
|
1958
|
-
const context = await orCreateContext(node, options);
|
|
1959
|
-
if (isElementNode(context.node) && isSVGElementNode(context.node) && !svgHasExternalResources(context.node))
|
|
1960
|
-
return context.node;
|
|
1961
|
-
const {
|
|
1962
|
-
ownerDocument,
|
|
1963
|
-
log,
|
|
1964
|
-
tasks,
|
|
1965
|
-
svgStyleElement,
|
|
1966
|
-
svgDefsElement,
|
|
1967
|
-
svgStyles,
|
|
1968
|
-
font,
|
|
1969
|
-
progress,
|
|
1970
|
-
autoDestruct,
|
|
1971
|
-
onCloneNode,
|
|
1972
|
-
onEmbedNode,
|
|
1973
|
-
onCreateForeignObjectSvg
|
|
1974
|
-
} = context;
|
|
1975
|
-
log.time("clone node");
|
|
1976
|
-
const clone = await cloneNode(context.node, context, true);
|
|
1977
|
-
if (svgStyleElement && ownerDocument) {
|
|
1978
|
-
let allCssText = "";
|
|
1979
|
-
svgStyles.forEach((klasses, cssText) => {
|
|
1980
|
-
allCssText += `${klasses.join(",\n")} {
|
|
1981
|
-
${cssText}
|
|
1982
|
-
}
|
|
1983
|
-
`;
|
|
1984
|
-
});
|
|
1985
|
-
svgStyleElement.appendChild(ownerDocument.createTextNode(allCssText));
|
|
1986
|
-
}
|
|
1987
|
-
log.timeEnd("clone node");
|
|
1988
|
-
await (onCloneNode == null ? void 0 : onCloneNode(clone));
|
|
1989
|
-
if (font !== false && isElementNode(clone)) {
|
|
1990
|
-
log.time("embed web font");
|
|
1991
|
-
await embedWebFont(clone, context);
|
|
1992
|
-
log.timeEnd("embed web font");
|
|
1993
|
-
}
|
|
1994
|
-
log.time("embed node");
|
|
1995
|
-
embedNode(clone, context);
|
|
1996
|
-
const count = tasks.length;
|
|
1997
|
-
let current = 0;
|
|
1998
|
-
const runTask = async () => {
|
|
1999
|
-
while (true) {
|
|
2000
|
-
const task = tasks.pop();
|
|
2001
|
-
if (!task)
|
|
2002
|
-
break;
|
|
2003
|
-
try {
|
|
2004
|
-
await task;
|
|
2005
|
-
} catch (error) {
|
|
2006
|
-
context.log.warn("Failed to run task", error);
|
|
2007
|
-
}
|
|
2008
|
-
progress == null ? void 0 : progress(++current, count);
|
|
2009
|
-
}
|
|
2010
|
-
};
|
|
2011
|
-
progress == null ? void 0 : progress(current, count);
|
|
2012
|
-
await Promise.all([...Array.from({ length: 4 })].map(runTask));
|
|
2013
|
-
log.timeEnd("embed node");
|
|
2014
|
-
await (onEmbedNode == null ? void 0 : onEmbedNode(clone));
|
|
2015
|
-
const svg = createForeignObjectSvg(clone, context);
|
|
2016
|
-
svgDefsElement && svg.insertBefore(svgDefsElement, svg.children[0]);
|
|
2017
|
-
svgStyleElement && svg.insertBefore(svgStyleElement, svg.children[0]);
|
|
2018
|
-
autoDestruct && destroyContext(context);
|
|
2019
|
-
await (onCreateForeignObjectSvg == null ? void 0 : onCreateForeignObjectSvg(svg));
|
|
2020
|
-
return svg;
|
|
2021
|
-
}
|
|
2022
|
-
function createForeignObjectSvg(clone, context) {
|
|
2023
|
-
const { width, height } = context;
|
|
2024
|
-
const svg = createSvg(width, height, clone.ownerDocument);
|
|
2025
|
-
const foreignObject = svg.ownerDocument.createElementNS(svg.namespaceURI, "foreignObject");
|
|
2026
|
-
foreignObject.setAttributeNS(null, "x", "0%");
|
|
2027
|
-
foreignObject.setAttributeNS(null, "y", "0%");
|
|
2028
|
-
foreignObject.setAttributeNS(null, "width", "100%");
|
|
2029
|
-
foreignObject.setAttributeNS(null, "height", "100%");
|
|
2030
|
-
foreignObject.append(clone);
|
|
2031
|
-
svg.appendChild(foreignObject);
|
|
2032
|
-
return svg;
|
|
2033
|
-
}
|
|
2034
|
-
async function domToCanvas(node, options) {
|
|
2035
|
-
var _a2;
|
|
2036
|
-
const context = await orCreateContext(node, options);
|
|
2037
|
-
const svg = await domToForeignObjectSvg(context);
|
|
2038
|
-
const dataUrl = svgToDataUrl(svg, context.isEnable("removeControlCharacter"));
|
|
2039
|
-
if (!context.autoDestruct) {
|
|
2040
|
-
context.svgStyleElement = createStyleElement(context.ownerDocument);
|
|
2041
|
-
context.svgDefsElement = (_a2 = context.ownerDocument) == null ? void 0 : _a2.createElementNS(XMLNS, "defs");
|
|
2042
|
-
context.svgStyles.clear();
|
|
2043
|
-
}
|
|
2044
|
-
const image = createImage(dataUrl, svg.ownerDocument);
|
|
2045
|
-
return await imageToCanvas(image, context);
|
|
2046
|
-
}
|
|
2047
|
-
async function domToDataUrl(node, options) {
|
|
2048
|
-
const context = await orCreateContext(node, options);
|
|
2049
|
-
const { log, quality, type, dpi } = context;
|
|
2050
|
-
const canvas = await domToCanvas(context);
|
|
2051
|
-
log.time("canvas to data url");
|
|
2052
|
-
let dataUrl = canvas.toDataURL(type, quality);
|
|
2053
|
-
if (["image/png", "image/jpeg"].includes(type) && dpi && SUPPORT_ATOB && SUPPORT_BTOA) {
|
|
2054
|
-
const [format, body] = dataUrl.split(",");
|
|
2055
|
-
let headerLength = 0;
|
|
2056
|
-
let overwritepHYs = false;
|
|
2057
|
-
if (type === "image/png") {
|
|
2058
|
-
const b64Index = detectPhysChunkFromDataUrl(body);
|
|
2059
|
-
if (b64Index >= 0) {
|
|
2060
|
-
headerLength = Math.ceil((b64Index + 28) / 3) * 4;
|
|
2061
|
-
overwritepHYs = true;
|
|
2062
|
-
} else {
|
|
2063
|
-
headerLength = 33 / 3 * 4;
|
|
2064
|
-
}
|
|
2065
|
-
} else if (type === "image/jpeg") {
|
|
2066
|
-
headerLength = 18 / 3 * 4;
|
|
2067
|
-
}
|
|
2068
|
-
const stringHeader = body.substring(0, headerLength);
|
|
2069
|
-
const restOfData = body.substring(headerLength);
|
|
2070
|
-
const headerBytes = window.atob(stringHeader);
|
|
2071
|
-
const uint8Array = new Uint8Array(headerBytes.length);
|
|
2072
|
-
for (let i = 0; i < uint8Array.length; i++) {
|
|
2073
|
-
uint8Array[i] = headerBytes.charCodeAt(i);
|
|
2074
|
-
}
|
|
2075
|
-
const finalArray = type === "image/png" ? changePngDpi(uint8Array, dpi, overwritepHYs) : changeJpegDpi(uint8Array, dpi);
|
|
2076
|
-
const base64Header = window.btoa(String.fromCharCode(...finalArray));
|
|
2077
|
-
dataUrl = [format, ",", base64Header, restOfData].join("");
|
|
2078
|
-
}
|
|
2079
|
-
log.timeEnd("canvas to data url");
|
|
2080
|
-
return dataUrl;
|
|
2081
|
-
}
|
|
2082
|
-
async function domToWebp(node, options) {
|
|
2083
|
-
return domToDataUrl(
|
|
2084
|
-
await orCreateContext(node, { ...options, type: "image/webp" })
|
|
2085
|
-
);
|
|
2086
|
-
}
|
|
2087
|
-
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2088
|
-
__proto__: null,
|
|
2089
|
-
createContext,
|
|
2090
|
-
destroyContext,
|
|
2091
|
-
domToCanvas,
|
|
2092
|
-
domToDataUrl,
|
|
2093
|
-
domToForeignObjectSvg,
|
|
2094
|
-
domToWebp,
|
|
2095
|
-
loadMedia,
|
|
2096
|
-
waitUntilLoad
|
|
2097
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
2098
|
-
if (typeof window < "u" && window.IssueSticker) {
|
|
2099
|
-
var _ns = window.IssueSticker;
|
|
2100
|
-
window.IssueSticker = _ns.IssueSticker || _ns.default || _ns;
|
|
2101
|
-
}
|
|
2102
|
-
export {
|
|
2103
|
-
IssueSticker,
|
|
2104
|
-
IssueSticker as default
|
|
2105
|
-
};
|