html2canvas-pro 2.4.5 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -13
- package/dist/html2canvas-pro.cjs +3425 -1677
- package/dist/html2canvas-pro.cjs.map +1 -1
- package/dist/html2canvas-pro.esm.js +3425 -1677
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +3479 -1731
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +5 -5
- package/dist/types/core/cache-storage.d.ts +22 -1
- package/dist/types/core/context.d.ts +10 -1
- package/dist/types/core/logger.d.ts +0 -3
- package/dist/types/core/render-element.d.ts +11 -0
- package/dist/types/core/util.d.ts +6 -0
- package/dist/types/css/index.d.ts +77 -46
- package/dist/types/css/parse.d.ts +15 -0
- package/dist/types/css/property-descriptors/accent-color.d.ts +5 -0
- package/dist/types/css/property-descriptors/backdrop-filter.d.ts +9 -0
- package/dist/types/css/property-descriptors/background-blend-mode.d.ts +16 -16
- package/dist/types/css/property-descriptors/border-image-width.d.ts +36 -0
- package/dist/types/css/property-descriptors/clip-path.d.ts +16 -2
- package/dist/types/css/property-descriptors/isolation.d.ts +6 -0
- package/dist/types/css/property-descriptors/mask.d.ts +25 -0
- package/dist/types/css/property-descriptors/mix-blend-mode.d.ts +16 -16
- package/dist/types/css/property-descriptors/outline.d.ts +15 -0
- package/dist/types/css/property-descriptors/text-emphasis.d.ts +22 -0
- package/dist/types/css/property-descriptors/text-shadow.d.ts +1 -1
- package/dist/types/css/property-descriptors/webkit-box-reflect.d.ts +19 -0
- package/dist/types/css/property-descriptors/webkit-text-fill-color.d.ts +9 -0
- package/dist/types/css/syntax/token-constants.d.ts +1 -1
- package/dist/types/css/types/color-math.d.ts +7 -1
- package/dist/types/css/types/color-spaces/a98.d.ts +2 -1
- package/dist/types/css/types/color-spaces/p3.d.ts +5 -4
- package/dist/types/css/types/color-spaces/pro-photo.d.ts +5 -4
- package/dist/types/css/types/color-spaces/rec2020.d.ts +5 -4
- package/dist/types/css/types/color-spaces/srgb.d.ts +5 -4
- package/dist/types/css/types/color-utilities.d.ts +11 -11
- package/dist/types/css/types/color.d.ts +1 -0
- package/dist/types/css/types/functions/conic-gradient.d.ts +17 -0
- package/dist/types/css/types/functions/image-set.d.ts +11 -0
- package/dist/types/css/types/functions/repeating-radial-gradient.d.ts +8 -0
- package/dist/types/css/types/image.d.ts +17 -2
- package/dist/types/css/types/safe-eval.d.ts +0 -6
- package/dist/types/dom/copy-css-styles.d.ts +8 -0
- package/dist/types/dom/document-cloner.d.ts +3 -13
- package/dist/types/dom/iframe-mount.d.ts +37 -0
- package/dist/types/dom/pseudo-content.d.ts +33 -0
- package/dist/types/dom/replaced-elements/iframe-element-container.d.ts +2 -2
- package/dist/types/dom/replaced-elements/input-element-container.d.ts +1 -1
- package/dist/types/options.d.ts +8 -2
- package/dist/types/render/canvas/background-renderer.d.ts +28 -0
- package/dist/types/render/canvas/border-image-renderer.d.ts +50 -1
- package/dist/types/render/canvas/canvas-renderer.d.ts +29 -15
- package/dist/types/render/canvas/effects-renderer.d.ts +8 -0
- package/dist/types/render/canvas/mask-renderer.d.ts +36 -0
- package/dist/types/render/canvas/text-clip-renderer.d.ts +56 -0
- package/dist/types/render/canvas/text-renderer.d.ts +22 -0
- package/dist/types/render/stacking-context.d.ts +4 -1
- package/package.json +41 -42
- package/dist/lib/config.js +0 -49
- package/dist/lib/core/abort-helper.js +0 -20
- package/dist/lib/core/background-parser.js +0 -41
- package/dist/lib/core/bitwise.js +0 -5
- package/dist/lib/core/cache-storage.js +0 -283
- package/dist/lib/core/config-assembler.js +0 -88
- package/dist/lib/core/constants.js +0 -25
- package/dist/lib/core/context.js +0 -19
- package/dist/lib/core/debugger.js +0 -27
- package/dist/lib/core/features.js +0 -190
- package/dist/lib/core/logger.js +0 -56
- package/dist/lib/core/lru-map.js +0 -66
- package/dist/lib/core/origin-checker.js +0 -53
- package/dist/lib/core/performance-monitor.js +0 -185
- package/dist/lib/core/render-element.js +0 -131
- package/dist/lib/core/util.js +0 -4
- package/dist/lib/core/validator.js +0 -500
- package/dist/lib/css/grouped/background-styles.js +0 -36
- package/dist/lib/css/grouped/border-styles.js +0 -75
- package/dist/lib/css/grouped/font-styles.js +0 -93
- package/dist/lib/css/grouped/layout-styles.js +0 -127
- package/dist/lib/css/index.js +0 -339
- package/dist/lib/css/layout/bounds.js +0 -52
- package/dist/lib/css/layout/text.js +0 -133
- package/dist/lib/css/property-descriptor.js +0 -2
- package/dist/lib/css/property-descriptors/background-blend-mode.js +0 -41
- package/dist/lib/css/property-descriptors/background-clip.js +0 -25
- package/dist/lib/css/property-descriptors/background-color.js +0 -10
- package/dist/lib/css/property-descriptors/background-image.js +0 -24
- package/dist/lib/css/property-descriptors/background-origin.js +0 -23
- package/dist/lib/css/property-descriptors/background-position.js +0 -19
- package/dist/lib/css/property-descriptors/background-repeat.js +0 -33
- package/dist/lib/css/property-descriptors/background-size.js +0 -23
- package/dist/lib/css/property-descriptors/border-color.js +0 -14
- package/dist/lib/css/property-descriptors/border-image-repeat.js +0 -42
- package/dist/lib/css/property-descriptors/border-image-slice.js +0 -45
- package/dist/lib/css/property-descriptors/border-image-source.js +0 -22
- package/dist/lib/css/property-descriptors/border-radius.js +0 -15
- package/dist/lib/css/property-descriptors/border-style.js +0 -26
- package/dist/lib/css/property-descriptors/border-width.js +0 -20
- package/dist/lib/css/property-descriptors/box-decoration-break.js +0 -18
- package/dist/lib/css/property-descriptors/box-shadow.js +0 -54
- package/dist/lib/css/property-descriptors/clip-path.js +0 -189
- package/dist/lib/css/property-descriptors/color.js +0 -10
- package/dist/lib/css/property-descriptors/content.js +0 -19
- package/dist/lib/css/property-descriptors/counter-increment.js +0 -35
- package/dist/lib/css/property-descriptors/counter-reset.js +0 -18
- package/dist/lib/css/property-descriptors/direction.js +0 -18
- package/dist/lib/css/property-descriptors/display.js +0 -81
- package/dist/lib/css/property-descriptors/duration.js +0 -14
- package/dist/lib/css/property-descriptors/filter.js +0 -86
- package/dist/lib/css/property-descriptors/float.js +0 -22
- package/dist/lib/css/property-descriptors/font-family.js +0 -47
- package/dist/lib/css/property-descriptors/font-size.js +0 -10
- package/dist/lib/css/property-descriptors/font-style.js +0 -20
- package/dist/lib/css/property-descriptors/font-variant-ligatures.js +0 -34
- package/dist/lib/css/property-descriptors/font-variant.js +0 -13
- package/dist/lib/css/property-descriptors/font-weight.js +0 -25
- package/dist/lib/css/property-descriptors/image-rendering.js +0 -33
- package/dist/lib/css/property-descriptors/letter-spacing.js +0 -21
- package/dist/lib/css/property-descriptors/line-break.js +0 -23
- package/dist/lib/css/property-descriptors/line-height.js +0 -24
- package/dist/lib/css/property-descriptors/list-style-image.js +0 -17
- package/dist/lib/css/property-descriptors/list-style-position.js +0 -18
- package/dist/lib/css/property-descriptors/list-style-type.js +0 -122
- package/dist/lib/css/property-descriptors/margin.js +0 -13
- package/dist/lib/css/property-descriptors/mix-blend-mode.js +0 -31
- package/dist/lib/css/property-descriptors/object-fit.js +0 -28
- package/dist/lib/css/property-descriptors/object-position.js +0 -42
- package/dist/lib/css/property-descriptors/opacity.js +0 -16
- package/dist/lib/css/property-descriptors/overflow-wrap.js +0 -18
- package/dist/lib/css/property-descriptors/overflow.js +0 -27
- package/dist/lib/css/property-descriptors/padding.js +0 -14
- package/dist/lib/css/property-descriptors/paint-order.js +0 -33
- package/dist/lib/css/property-descriptors/position.js +0 -22
- package/dist/lib/css/property-descriptors/quotes.js +0 -41
- package/dist/lib/css/property-descriptors/rotate.js +0 -27
- package/dist/lib/css/property-descriptors/text-align.js +0 -21
- package/dist/lib/css/property-descriptors/text-decoration-color.js +0 -10
- package/dist/lib/css/property-descriptors/text-decoration-line.js +0 -28
- package/dist/lib/css/property-descriptors/text-decoration-style.js +0 -24
- package/dist/lib/css/property-descriptors/text-decoration-thickness.js +0 -26
- package/dist/lib/css/property-descriptors/text-overflow.js +0 -18
- package/dist/lib/css/property-descriptors/text-shadow.js +0 -46
- package/dist/lib/css/property-descriptors/text-transform.js +0 -20
- package/dist/lib/css/property-descriptors/text-underline-offset.js +0 -23
- package/dist/lib/css/property-descriptors/transform-origin.js +0 -24
- package/dist/lib/css/property-descriptors/transform.js +0 -57
- package/dist/lib/css/property-descriptors/visibility.js +0 -20
- package/dist/lib/css/property-descriptors/webkit-line-clamp.js +0 -26
- package/dist/lib/css/property-descriptors/webkit-text-stroke-color.js +0 -10
- package/dist/lib/css/property-descriptors/webkit-text-stroke-width.js +0 -16
- package/dist/lib/css/property-descriptors/white-space.js +0 -32
- package/dist/lib/css/property-descriptors/word-break.js +0 -26
- package/dist/lib/css/property-descriptors/writing-mode.js +0 -28
- package/dist/lib/css/property-descriptors/z-index.js +0 -19
- package/dist/lib/css/property-descriptors/zoom.js +0 -18
- package/dist/lib/css/syntax/parser.js +0 -141
- package/dist/lib/css/syntax/token-constants.js +0 -214
- package/dist/lib/css/syntax/token-singletons.js +0 -36
- package/dist/lib/css/syntax/token-types.js +0 -10
- package/dist/lib/css/syntax/tokenizer.js +0 -502
- package/dist/lib/css/type-descriptor.js +0 -2
- package/dist/lib/css/types/angle.js +0 -80
- package/dist/lib/css/types/color-math.js +0 -25
- package/dist/lib/css/types/color-spaces/a98.js +0 -78
- package/dist/lib/css/types/color-spaces/p3.js +0 -86
- package/dist/lib/css/types/color-spaces/pro-photo.js +0 -83
- package/dist/lib/css/types/color-spaces/rec2020.js +0 -85
- package/dist/lib/css/types/color-spaces/srgb.js +0 -79
- package/dist/lib/css/types/color-utilities.js +0 -342
- package/dist/lib/css/types/color.js +0 -400
- package/dist/lib/css/types/functions/-prefix-linear-gradient.js +0 -32
- package/dist/lib/css/types/functions/-prefix-radial-gradient.js +0 -83
- package/dist/lib/css/types/functions/-webkit-gradient.js +0 -59
- package/dist/lib/css/types/functions/counter.js +0 -367
- package/dist/lib/css/types/functions/gradient.js +0 -163
- package/dist/lib/css/types/functions/linear-gradient.js +0 -27
- package/dist/lib/css/types/functions/radial-gradient.js +0 -90
- package/dist/lib/css/types/functions/repeating-linear-gradient.js +0 -9
- package/dist/lib/css/types/image.js +0 -62
- package/dist/lib/css/types/index.js +0 -2
- package/dist/lib/css/types/length-percentage.js +0 -197
- package/dist/lib/css/types/length.js +0 -5
- package/dist/lib/css/types/safe-eval.js +0 -80
- package/dist/lib/css/types/time.js +0 -17
- package/dist/lib/dom/document-cloner.js +0 -618
- package/dist/lib/dom/dom-normalizer.js +0 -115
- package/dist/lib/dom/element-container.js +0 -71
- package/dist/lib/dom/elements/li-element-container.js +0 -11
- package/dist/lib/dom/elements/ol-element-container.js +0 -12
- package/dist/lib/dom/elements/select-element-container.js +0 -12
- package/dist/lib/dom/elements/textarea-element-container.js +0 -11
- package/dist/lib/dom/node-parser.js +0 -125
- package/dist/lib/dom/node-type-guards.js +0 -81
- package/dist/lib/dom/replaced-elements/canvas-element-container.js +0 -13
- package/dist/lib/dom/replaced-elements/iframe-element-container.js +0 -38
- package/dist/lib/dom/replaced-elements/image-element-container.js +0 -14
- package/dist/lib/dom/replaced-elements/index.js +0 -2
- package/dist/lib/dom/replaced-elements/input-element-container.js +0 -89
- package/dist/lib/dom/replaced-elements/svg-element-container.js +0 -57
- package/dist/lib/dom/slot-cloner.js +0 -176
- package/dist/lib/dom/text-container.js +0 -35
- package/dist/lib/index.js +0 -49
- package/dist/lib/options.js +0 -2
- package/dist/lib/render/background.js +0 -188
- package/dist/lib/render/bezier-curve.js +0 -34
- package/dist/lib/render/border.js +0 -104
- package/dist/lib/render/bound-curves.js +0 -188
- package/dist/lib/render/box-sizing.js +0 -20
- package/dist/lib/render/canvas/background-renderer.js +0 -338
- package/dist/lib/render/canvas/border-image-renderer.js +0 -153
- package/dist/lib/render/canvas/border-renderer.js +0 -184
- package/dist/lib/render/canvas/box-shadow-geometry.js +0 -52
- package/dist/lib/render/canvas/box-shadow-painter.js +0 -194
- package/dist/lib/render/canvas/box-shadow-transform.js +0 -42
- package/dist/lib/render/canvas/canvas-path.js +0 -25
- package/dist/lib/render/canvas/canvas-renderer.js +0 -610
- package/dist/lib/render/canvas/content-renderer.js +0 -270
- package/dist/lib/render/canvas/effects-renderer.js +0 -171
- package/dist/lib/render/canvas/filter-surface.js +0 -270
- package/dist/lib/render/canvas/font-utils.js +0 -46
- package/dist/lib/render/canvas/foreignobject-renderer.js +0 -38
- package/dist/lib/render/canvas/surface-bounds.js +0 -64
- package/dist/lib/render/canvas/text/text-decoration-renderer.js +0 -99
- package/dist/lib/render/canvas/text-renderer.js +0 -486
- package/dist/lib/render/effects.js +0 -231
- package/dist/lib/render/font-metrics.js +0 -53
- package/dist/lib/render/object-fit.js +0 -91
- package/dist/lib/render/path.js +0 -26
- package/dist/lib/render/renderer-interface.js +0 -2
- package/dist/lib/render/stacking-context.js +0 -341
- package/dist/lib/render/vector.js +0 -16
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Cache = void 0;
|
|
4
|
-
const features_1 = require("./features");
|
|
5
|
-
class Cache {
|
|
6
|
-
constructor(context, _options) {
|
|
7
|
-
this.context = context;
|
|
8
|
-
this._options = _options;
|
|
9
|
-
this._cache = new Map();
|
|
10
|
-
this._pendingOperations = new Map();
|
|
11
|
-
/** When true, addImage() collects URLs without starting loads. */
|
|
12
|
-
this._deferMode = false;
|
|
13
|
-
/** URLs collected during defer mode, pending batch preload. */
|
|
14
|
-
this._collectedUrls = new Set();
|
|
15
|
-
// Default cache size: 100 items
|
|
16
|
-
this.maxSize = _options.maxCacheSize ?? 100;
|
|
17
|
-
if (this.maxSize < 1) {
|
|
18
|
-
throw new Error('Cache maxSize must be at least 1');
|
|
19
|
-
}
|
|
20
|
-
if (this.maxSize > 10000) {
|
|
21
|
-
this.context.logger.warn(`Cache maxSize ${this.maxSize} is very large and may cause memory issues. ` +
|
|
22
|
-
`Consider using a smaller value (recommended: 100-1000).`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Enter defer mode: subsequent addImage() calls only collect URLs.
|
|
27
|
-
* Call preloadAll() to exit defer mode and batch-load all URLs.
|
|
28
|
-
*/
|
|
29
|
-
startDefer() {
|
|
30
|
-
this._deferMode = true;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Exit defer mode and load all collected URLs in parallel, respecting
|
|
34
|
-
* an optional concurrency cap to avoid overwhelming the browser's network
|
|
35
|
-
* stack (default: 10 concurrent loads).
|
|
36
|
-
* After this call returns, all images are either loaded (cache hit) or
|
|
37
|
-
* failed (logged). Subsequent cache.match() calls return immediately.
|
|
38
|
-
*
|
|
39
|
-
* @param concurrency - Max concurrent image loads (1–100, default 10).
|
|
40
|
-
*/
|
|
41
|
-
async preloadAll(concurrency = 10) {
|
|
42
|
-
this._deferMode = false;
|
|
43
|
-
const urls = Array.from(this._collectedUrls);
|
|
44
|
-
this._collectedUrls.clear();
|
|
45
|
-
if (urls.length === 0) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const limit = Math.max(1, Math.min(concurrency, 100));
|
|
49
|
-
this.context.logger.debug(`Preloading ${urls.length} image(s) with concurrency ${limit}`);
|
|
50
|
-
// Load in batches to respect the concurrency cap while maximising
|
|
51
|
-
// parallelism within each batch.
|
|
52
|
-
for (let i = 0; i < urls.length; i += limit) {
|
|
53
|
-
const batch = urls.slice(i, i + limit);
|
|
54
|
-
const operations = batch.map((url) => this._addImageWithPending(url));
|
|
55
|
-
await Promise.allSettled(operations);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
addImage(src) {
|
|
59
|
-
// ── Defer mode: collect only ──────────────────────────────
|
|
60
|
-
if (this._deferMode) {
|
|
61
|
-
if (!this.has(src) && (isBlobImage(src) || isRenderable(src))) {
|
|
62
|
-
this._collectedUrls.add(src);
|
|
63
|
-
}
|
|
64
|
-
return Promise.resolve();
|
|
65
|
-
}
|
|
66
|
-
// ── Normal mode: immediate load ───────────────────────────
|
|
67
|
-
// Wait for any pending operations on this key
|
|
68
|
-
const pending = this._pendingOperations.get(src);
|
|
69
|
-
if (pending) {
|
|
70
|
-
return pending;
|
|
71
|
-
}
|
|
72
|
-
if (this.has(src)) {
|
|
73
|
-
// Move to end for LRU ordering
|
|
74
|
-
const entry = this._cache.get(src);
|
|
75
|
-
this._cache.delete(src);
|
|
76
|
-
this._cache.set(src, entry);
|
|
77
|
-
return Promise.resolve();
|
|
78
|
-
}
|
|
79
|
-
if (isBlobImage(src) || isRenderable(src)) {
|
|
80
|
-
return this._addImageWithPending(src);
|
|
81
|
-
}
|
|
82
|
-
return Promise.resolve();
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Shared helper: enqueues loading for a single URL with pending-operation
|
|
86
|
-
* deduplication and error swallowing. Used by both addImage() (normal mode)
|
|
87
|
-
* and preloadAll() (batch mode).
|
|
88
|
-
*/
|
|
89
|
-
_addImageWithPending(src) {
|
|
90
|
-
const pending = this._pendingOperations.get(src);
|
|
91
|
-
if (pending) {
|
|
92
|
-
return pending;
|
|
93
|
-
}
|
|
94
|
-
const operation = this._addImageInternal(src);
|
|
95
|
-
this._pendingOperations.set(src, operation);
|
|
96
|
-
operation.finally(() => {
|
|
97
|
-
this._pendingOperations.delete(src);
|
|
98
|
-
});
|
|
99
|
-
return operation;
|
|
100
|
-
}
|
|
101
|
-
async _addImageInternal(src) {
|
|
102
|
-
const timeoutMs = this._options.imageTimeout ?? 15000;
|
|
103
|
-
const imageWithTimeout = this.withTimeout(this.loadImage(src), timeoutMs, `Timed out (${timeoutMs}ms) loading image`);
|
|
104
|
-
// Handle errors to prevent unhandled rejections
|
|
105
|
-
imageWithTimeout.catch((error) => {
|
|
106
|
-
this.context.logger.error(`Failed to load image ${src}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
107
|
-
});
|
|
108
|
-
// Store the promise with timeout in cache
|
|
109
|
-
this.set(src, imageWithTimeout);
|
|
110
|
-
}
|
|
111
|
-
withTimeout(promise, timeoutMs, message) {
|
|
112
|
-
if (timeoutMs <= 0) {
|
|
113
|
-
return promise;
|
|
114
|
-
}
|
|
115
|
-
let timeoutId;
|
|
116
|
-
const timeout = new Promise((_, reject) => {
|
|
117
|
-
timeoutId = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
118
|
-
});
|
|
119
|
-
return Promise.race([promise, timeout]).finally(() => {
|
|
120
|
-
if (timeoutId !== undefined) {
|
|
121
|
-
clearTimeout(timeoutId);
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
match(src) {
|
|
126
|
-
const entry = this._cache.get(src);
|
|
127
|
-
if (entry) {
|
|
128
|
-
// Move to end for LRU ordering (O(1))
|
|
129
|
-
this._cache.delete(src);
|
|
130
|
-
this._cache.set(src, entry);
|
|
131
|
-
return entry.value;
|
|
132
|
-
}
|
|
133
|
-
return undefined;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Set a value in cache with LRU eviction (O(1) via Map insertion order).
|
|
137
|
-
* Map preserves insertion order; delete+set on access moves items to the end.
|
|
138
|
-
* The first key in Map.keys() is always the least recently used.
|
|
139
|
-
*/
|
|
140
|
-
set(key, value) {
|
|
141
|
-
if (this._cache.has(key)) {
|
|
142
|
-
// Update existing entry: move to end of Map
|
|
143
|
-
this._cache.delete(key);
|
|
144
|
-
}
|
|
145
|
-
else if (this._cache.size >= this.maxSize) {
|
|
146
|
-
// Evict LRU (first key = least recently used) — O(1)
|
|
147
|
-
const lruKey = this._cache.keys().next().value;
|
|
148
|
-
if (lruKey !== undefined) {
|
|
149
|
-
this._cache.delete(lruKey);
|
|
150
|
-
this.context.logger.debug(`Cache: Evicted LRU entry: ${lruKey}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
this._cache.set(key, { value });
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Get cache size
|
|
157
|
-
*/
|
|
158
|
-
size() {
|
|
159
|
-
return this._cache.size;
|
|
160
|
-
}
|
|
161
|
-
/**
|
|
162
|
-
* Get max cache size
|
|
163
|
-
*/
|
|
164
|
-
getMaxSize() {
|
|
165
|
-
return this.maxSize;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Clear all cache entries
|
|
169
|
-
*/
|
|
170
|
-
clear() {
|
|
171
|
-
this._cache.clear();
|
|
172
|
-
}
|
|
173
|
-
async loadImage(key) {
|
|
174
|
-
const originChecker = this.context.originChecker;
|
|
175
|
-
const defaultIsSameOrigin = (src) => originChecker.isSameOrigin(src);
|
|
176
|
-
const isSameOrigin = typeof this._options.customIsSameOrigin === 'function'
|
|
177
|
-
? await this._options.customIsSameOrigin(key, defaultIsSameOrigin)
|
|
178
|
-
: defaultIsSameOrigin(key);
|
|
179
|
-
// With allowTaint disabled (the default), a cross-origin image is safe to
|
|
180
|
-
// draw only when the server sends CORS headers. Instead of skipping such
|
|
181
|
-
// images outright, still ATTEMPT a CORS load: it succeeds for CORS-enabled
|
|
182
|
-
// hosts (CDNs, avatar services, picsum, ...) and fails cleanly for hosts
|
|
183
|
-
// without CORS headers, where the image is skipped exactly as before
|
|
184
|
-
// (issue #229). An explicit proxy takes precedence so existing setups
|
|
185
|
-
// that rely on proxying keep working.
|
|
186
|
-
const canAttemptCors = !isSameOrigin &&
|
|
187
|
-
this._options.allowTaint === false &&
|
|
188
|
-
!isInlineImage(key) &&
|
|
189
|
-
!isBlobImage(key) &&
|
|
190
|
-
typeof this._options.proxy !== 'string';
|
|
191
|
-
const useCORS = !isInlineImage(key) &&
|
|
192
|
-
(this._options.useCORS === true || canAttemptCors) &&
|
|
193
|
-
features_1.FEATURES.SUPPORT_CORS_IMAGES &&
|
|
194
|
-
!isSameOrigin;
|
|
195
|
-
const useProxy = !isInlineImage(key) &&
|
|
196
|
-
!isSameOrigin &&
|
|
197
|
-
!isBlobImage(key) &&
|
|
198
|
-
typeof this._options.proxy === 'string' &&
|
|
199
|
-
features_1.FEATURES.SUPPORT_CORS_XHR &&
|
|
200
|
-
!useCORS;
|
|
201
|
-
if (!isSameOrigin &&
|
|
202
|
-
this._options.allowTaint === false &&
|
|
203
|
-
!isInlineImage(key) &&
|
|
204
|
-
!isBlobImage(key) &&
|
|
205
|
-
!useProxy &&
|
|
206
|
-
!useCORS) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
let src = key;
|
|
210
|
-
if (useProxy) {
|
|
211
|
-
src = await this.proxy(src);
|
|
212
|
-
}
|
|
213
|
-
this.context.logger.debug(`Added image ${key.substring(0, 256)}`);
|
|
214
|
-
return await new Promise((resolve, reject) => {
|
|
215
|
-
const img = new Image();
|
|
216
|
-
img.onload = () => resolve(img);
|
|
217
|
-
img.onerror = reject;
|
|
218
|
-
//ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
|
|
219
|
-
if (isInlineBase64Image(src) || useCORS) {
|
|
220
|
-
img.crossOrigin = 'anonymous';
|
|
221
|
-
}
|
|
222
|
-
img.src = src;
|
|
223
|
-
if (img.complete === true) {
|
|
224
|
-
// Inline XML images may fail to parse, throwing an Error later on
|
|
225
|
-
setTimeout(() => resolve(img), 500);
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
has(key) {
|
|
230
|
-
return this._cache.has(key);
|
|
231
|
-
}
|
|
232
|
-
keys() {
|
|
233
|
-
return Promise.resolve(Array.from(this._cache.keys()));
|
|
234
|
-
}
|
|
235
|
-
proxy(src) {
|
|
236
|
-
const proxy = this._options.proxy;
|
|
237
|
-
if (!proxy) {
|
|
238
|
-
throw new Error('No proxy defined');
|
|
239
|
-
}
|
|
240
|
-
const key = src.substring(0, 256);
|
|
241
|
-
return new Promise((resolve, reject) => {
|
|
242
|
-
const responseType = features_1.FEATURES.SUPPORT_RESPONSE_TYPE ? 'blob' : 'text';
|
|
243
|
-
const xhr = new XMLHttpRequest();
|
|
244
|
-
xhr.onload = () => {
|
|
245
|
-
if (xhr.status === 200) {
|
|
246
|
-
if (responseType === 'text') {
|
|
247
|
-
resolve(xhr.response);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
const reader = new FileReader();
|
|
251
|
-
reader.addEventListener('load', () => resolve(reader.result), false);
|
|
252
|
-
reader.addEventListener('error', (e) => reject(e), false);
|
|
253
|
-
reader.readAsDataURL(xhr.response);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
reject(`Failed to proxy resource ${key} with status code ${xhr.status}`);
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
xhr.onerror = reject;
|
|
261
|
-
const queryString = proxy.indexOf('?') > -1 ? '&' : '?';
|
|
262
|
-
xhr.open('GET', `${proxy}${queryString}url=${encodeURIComponent(src)}&responseType=${responseType}`);
|
|
263
|
-
if (responseType !== 'text' && xhr instanceof XMLHttpRequest) {
|
|
264
|
-
xhr.responseType = responseType;
|
|
265
|
-
}
|
|
266
|
-
if (this._options.imageTimeout) {
|
|
267
|
-
const timeout = this._options.imageTimeout;
|
|
268
|
-
xhr.timeout = timeout;
|
|
269
|
-
xhr.ontimeout = () => reject(`Timed out (${timeout}ms) proxying ${key}`);
|
|
270
|
-
}
|
|
271
|
-
xhr.send();
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
exports.Cache = Cache;
|
|
276
|
-
const INLINE_SVG = /^data:image\/svg\+xml/i;
|
|
277
|
-
const INLINE_BASE64 = /^data:image\/.*;base64,/i;
|
|
278
|
-
const INLINE_IMG = /^data:image\/.*/i;
|
|
279
|
-
const isRenderable = (src) => features_1.FEATURES.SUPPORT_SVG_DRAWING || !isSVG(src);
|
|
280
|
-
const isInlineImage = (src) => INLINE_IMG.test(src);
|
|
281
|
-
const isInlineBase64Image = (src) => INLINE_BASE64.test(src);
|
|
282
|
-
const isBlobImage = (src) => src.substring(0, 4) === 'blob';
|
|
283
|
-
const isSVG = (src) => src.slice(-3).toLowerCase() === 'svg' || INLINE_SVG.test(src);
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.assembleRenderOptions = exports.assembleCloneOptions = exports.assembleWindowOptions = exports.assembleContextOptions = exports.assembleResourceOptions = exports.coerceNumberOptions = void 0;
|
|
4
|
-
const constants_1 = require("./constants");
|
|
5
|
-
/**
|
|
6
|
-
* Coerce known numeric options from string (or other) values to actual numbers.
|
|
7
|
-
* Mutates the opts object in place — this is intentionally a normalisation
|
|
8
|
-
* (not pure) step that runs once at the beginning of renderElement.
|
|
9
|
-
*/
|
|
10
|
-
const coerceNumberOptions = (opts) => {
|
|
11
|
-
const numKeys = [
|
|
12
|
-
'scale',
|
|
13
|
-
'width',
|
|
14
|
-
'height',
|
|
15
|
-
'imageTimeout',
|
|
16
|
-
'x',
|
|
17
|
-
'y',
|
|
18
|
-
'windowWidth',
|
|
19
|
-
'windowHeight',
|
|
20
|
-
'scrollX',
|
|
21
|
-
'scrollY'
|
|
22
|
-
];
|
|
23
|
-
numKeys.forEach((key) => {
|
|
24
|
-
const v = opts[key];
|
|
25
|
-
if (v !== undefined && v !== null && typeof v !== 'number') {
|
|
26
|
-
const n = Number(v);
|
|
27
|
-
if (!Number.isNaN(n)) {
|
|
28
|
-
opts[key] = n;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
};
|
|
33
|
-
exports.coerceNumberOptions = coerceNumberOptions;
|
|
34
|
-
/** Assemble resource loading options from user-provided Options. */
|
|
35
|
-
const assembleResourceOptions = (opts) => ({
|
|
36
|
-
allowTaint: opts.allowTaint ?? false,
|
|
37
|
-
imageTimeout: opts.imageTimeout ?? constants_1.DEFAULT_IMAGE_TIMEOUT_MS,
|
|
38
|
-
proxy: opts.proxy,
|
|
39
|
-
useCORS: opts.useCORS ?? false,
|
|
40
|
-
customIsSameOrigin: opts.customIsSameOrigin,
|
|
41
|
-
maxCacheSize: opts.maxCacheSize
|
|
42
|
-
});
|
|
43
|
-
exports.assembleResourceOptions = assembleResourceOptions;
|
|
44
|
-
/** Assemble context (logging + cache) options, extending resource options. */
|
|
45
|
-
const assembleContextOptions = (opts, config, resourceOptions) => ({
|
|
46
|
-
logging: opts.logging ?? true,
|
|
47
|
-
cache: opts.cache ?? config.cache,
|
|
48
|
-
...resourceOptions
|
|
49
|
-
});
|
|
50
|
-
exports.assembleContextOptions = assembleContextOptions;
|
|
51
|
-
const DEFAULT_WINDOW_WIDTH = 800;
|
|
52
|
-
const DEFAULT_WINDOW_HEIGHT = 600;
|
|
53
|
-
const DEFAULT_SCROLL = 0;
|
|
54
|
-
const assembleWindowOptions = (opts, defaultView) => {
|
|
55
|
-
const win = defaultView;
|
|
56
|
-
return {
|
|
57
|
-
windowWidth: opts.windowWidth ?? win.innerWidth ?? DEFAULT_WINDOW_WIDTH,
|
|
58
|
-
windowHeight: opts.windowHeight ?? win.innerHeight ?? DEFAULT_WINDOW_HEIGHT,
|
|
59
|
-
scrollX: opts.scrollX ?? win.pageXOffset ?? DEFAULT_SCROLL,
|
|
60
|
-
scrollY: opts.scrollY ?? win.pageYOffset ?? DEFAULT_SCROLL
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
exports.assembleWindowOptions = assembleWindowOptions;
|
|
64
|
-
/** Assemble DOM cloning options. */
|
|
65
|
-
const assembleCloneOptions = (opts, config, foreignObjectRendering) => ({
|
|
66
|
-
allowTaint: opts.allowTaint ?? false,
|
|
67
|
-
onclone: opts.onclone,
|
|
68
|
-
ignoreElements: opts.ignoreElements,
|
|
69
|
-
iframeContainer: opts.iframeContainer,
|
|
70
|
-
inlineImages: foreignObjectRendering,
|
|
71
|
-
copyStyles: foreignObjectRendering,
|
|
72
|
-
cspNonce: opts.cspNonce ?? config.cspNonce
|
|
73
|
-
});
|
|
74
|
-
exports.assembleCloneOptions = assembleCloneOptions;
|
|
75
|
-
/** Assemble canvas rendering options. */
|
|
76
|
-
const assembleRenderOptions = (opts, backgroundColor, left, top, width, height, devicePixelRatio) => ({
|
|
77
|
-
canvas: opts.canvas,
|
|
78
|
-
backgroundColor,
|
|
79
|
-
signal: opts.signal,
|
|
80
|
-
scale: opts.scale ?? devicePixelRatio ?? 1,
|
|
81
|
-
x: (opts.x ?? 0) + left,
|
|
82
|
-
y: (opts.y ?? 0) + top,
|
|
83
|
-
width: opts.width ?? Math.ceil(width),
|
|
84
|
-
height: opts.height ?? Math.ceil(height),
|
|
85
|
-
imageSmoothing: opts.imageSmoothing,
|
|
86
|
-
imageSmoothingQuality: opts.imageSmoothingQuality
|
|
87
|
-
});
|
|
88
|
-
exports.assembleRenderOptions = assembleRenderOptions;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Shared numeric constants used across html2canvas-pro.
|
|
4
|
-
* Centralising magic numbers for maintainability.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.RESOURCE_KEY_LOG_LENGTH = exports.INLINE_IMAGE_RESOLVE_DELAY_MS = exports.IFRAME_READY_POLL_MS = exports.SHADOW_MASK_OFFSET = exports.DEFAULT_IMAGE_TIMEOUT_MS = exports.MAX_IMAGE_CACHE_SIZE = exports.DEFAULT_IMAGE_CACHE_SIZE = exports.PATTERN_CACHE_MAX = exports.PARSE_CACHE_MAX_PER_DESCRIPTOR = void 0;
|
|
8
|
-
/** Maximum entries in the CSS parse cache per descriptor (LRU). */
|
|
9
|
-
exports.PARSE_CACHE_MAX_PER_DESCRIPTOR = 200;
|
|
10
|
-
/** Maximum cached background-image patterns per render session (LRU). */
|
|
11
|
-
exports.PATTERN_CACHE_MAX = 50;
|
|
12
|
-
/** Maximum size of the image-resource cache (entries). */
|
|
13
|
-
exports.DEFAULT_IMAGE_CACHE_SIZE = 100;
|
|
14
|
-
/** Maximum allowed image-resource cache size. */
|
|
15
|
-
exports.MAX_IMAGE_CACHE_SIZE = 10000;
|
|
16
|
-
/** Default image-load timeout in milliseconds. */
|
|
17
|
-
exports.DEFAULT_IMAGE_TIMEOUT_MS = 15000;
|
|
18
|
-
/** Z-axis mask offset used during box-shadow rendering. */
|
|
19
|
-
exports.SHADOW_MASK_OFFSET = 10000;
|
|
20
|
-
/** Polling interval (ms) when waiting for the cloned iframe to become ready. */
|
|
21
|
-
exports.IFRAME_READY_POLL_MS = 50;
|
|
22
|
-
/** Deferred resolution delay (ms) for inline XML images that may fail to parse. */
|
|
23
|
-
exports.INLINE_IMAGE_RESOLVE_DELAY_MS = 500;
|
|
24
|
-
/** Maximum characters logged for image/resource keys. */
|
|
25
|
-
exports.RESOURCE_KEY_LOG_LENGTH = 256;
|
package/dist/lib/core/context.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Context = void 0;
|
|
4
|
-
const logger_1 = require("./logger");
|
|
5
|
-
const cache_storage_1 = require("./cache-storage");
|
|
6
|
-
const origin_checker_1 = require("./origin-checker");
|
|
7
|
-
class Context {
|
|
8
|
-
constructor(options, windowBounds, config) {
|
|
9
|
-
this.windowBounds = windowBounds;
|
|
10
|
-
this.instanceName = `#${Context.instanceCount++}`;
|
|
11
|
-
this.config = config;
|
|
12
|
-
this.logger = new logger_1.Logger({ id: this.instanceName, enabled: options.logging });
|
|
13
|
-
this.originChecker = new origin_checker_1.OriginChecker(config.window);
|
|
14
|
-
this.cache = options.cache ?? config.cache ?? new cache_storage_1.Cache(this, options);
|
|
15
|
-
this.onError = options.onError;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
exports.Context = Context;
|
|
19
|
-
Context.instanceCount = 1;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isDebugging = void 0;
|
|
4
|
-
const elementDebuggerAttribute = 'data-html2canvas-debug';
|
|
5
|
-
const getElementDebugType = (element) => {
|
|
6
|
-
if (typeof element.getAttribute !== 'function') {
|
|
7
|
-
return 0 /* DebuggerType.NONE */;
|
|
8
|
-
}
|
|
9
|
-
const attribute = element.getAttribute(elementDebuggerAttribute);
|
|
10
|
-
switch (attribute) {
|
|
11
|
-
case 'all':
|
|
12
|
-
return 1 /* DebuggerType.ALL */;
|
|
13
|
-
case 'clone':
|
|
14
|
-
return 2 /* DebuggerType.CLONE */;
|
|
15
|
-
case 'parse':
|
|
16
|
-
return 3 /* DebuggerType.PARSE */;
|
|
17
|
-
case 'render':
|
|
18
|
-
return 4 /* DebuggerType.RENDER */;
|
|
19
|
-
default:
|
|
20
|
-
return 0 /* DebuggerType.NONE */;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
const isDebugging = (element, type) => {
|
|
24
|
-
const elementType = getElementDebugType(element);
|
|
25
|
-
return elementType === 1 /* DebuggerType.ALL */ || type === elementType;
|
|
26
|
-
};
|
|
27
|
-
exports.isDebugging = isDebugging;
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FEATURES = exports.loadSerializedSVG = exports.createForeignObjectSVG = void 0;
|
|
4
|
-
const css_line_break_1 = require("css-line-break");
|
|
5
|
-
const testRangeBounds = (document) => {
|
|
6
|
-
const TEST_HEIGHT = 123;
|
|
7
|
-
if (document.createRange) {
|
|
8
|
-
const range = document.createRange();
|
|
9
|
-
if (range.getBoundingClientRect) {
|
|
10
|
-
const testElement = document.createElement('boundtest');
|
|
11
|
-
testElement.style.height = `${TEST_HEIGHT}px`;
|
|
12
|
-
testElement.style.display = 'block';
|
|
13
|
-
document.body.appendChild(testElement);
|
|
14
|
-
range.selectNode(testElement);
|
|
15
|
-
const rangeBounds = range.getBoundingClientRect();
|
|
16
|
-
const rangeHeight = Math.round(rangeBounds.height);
|
|
17
|
-
document.body.removeChild(testElement);
|
|
18
|
-
if (rangeHeight === TEST_HEIGHT) {
|
|
19
|
-
return true;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
};
|
|
25
|
-
const testIOSLineBreak = (document) => {
|
|
26
|
-
const testElement = document.createElement('boundtest');
|
|
27
|
-
testElement.style.width = '50px';
|
|
28
|
-
testElement.style.display = 'block';
|
|
29
|
-
testElement.style.fontSize = '12px';
|
|
30
|
-
testElement.style.letterSpacing = '0px';
|
|
31
|
-
testElement.style.wordSpacing = '0px';
|
|
32
|
-
document.body.appendChild(testElement);
|
|
33
|
-
const range = document.createRange();
|
|
34
|
-
testElement.innerHTML = typeof ''.repeat === 'function' ? '👨'.repeat(10) : '';
|
|
35
|
-
const node = testElement.firstChild;
|
|
36
|
-
const textList = (0, css_line_break_1.toCodePoints)(node.data).map((i) => (0, css_line_break_1.fromCodePoint)(i));
|
|
37
|
-
let offset = 0;
|
|
38
|
-
let prev = {};
|
|
39
|
-
// ios 13 does not handle range getBoundingClientRect line changes correctly #2177
|
|
40
|
-
const supports = textList.every((text, i) => {
|
|
41
|
-
range.setStart(node, offset);
|
|
42
|
-
range.setEnd(node, offset + text.length);
|
|
43
|
-
const rect = range.getBoundingClientRect();
|
|
44
|
-
offset += text.length;
|
|
45
|
-
const boundAhead = rect.x > prev.x || rect.y > prev.y;
|
|
46
|
-
prev = rect;
|
|
47
|
-
if (i === 0) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
return boundAhead;
|
|
51
|
-
});
|
|
52
|
-
document.body.removeChild(testElement);
|
|
53
|
-
return supports;
|
|
54
|
-
};
|
|
55
|
-
const testCORS = () => typeof new Image().crossOrigin !== 'undefined';
|
|
56
|
-
const testResponseType = () => typeof new XMLHttpRequest().responseType === 'string';
|
|
57
|
-
const testSVG = (document) => {
|
|
58
|
-
const img = new Image();
|
|
59
|
-
const canvas = document.createElement('canvas');
|
|
60
|
-
const ctx = canvas.getContext('2d');
|
|
61
|
-
if (!ctx) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>`;
|
|
65
|
-
try {
|
|
66
|
-
ctx.drawImage(img, 0, 0);
|
|
67
|
-
canvas.toDataURL();
|
|
68
|
-
}
|
|
69
|
-
catch (e) {
|
|
70
|
-
return false;
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
};
|
|
74
|
-
const isGreenPixel = (data) => data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;
|
|
75
|
-
const testForeignObject = (document) => {
|
|
76
|
-
const canvas = document.createElement('canvas');
|
|
77
|
-
const size = 100;
|
|
78
|
-
canvas.width = size;
|
|
79
|
-
canvas.height = size;
|
|
80
|
-
const ctx = canvas.getContext('2d');
|
|
81
|
-
if (!ctx) {
|
|
82
|
-
return Promise.reject(new Error('Failed to get 2D rendering context'));
|
|
83
|
-
}
|
|
84
|
-
ctx.fillStyle = 'rgb(0, 255, 0)';
|
|
85
|
-
ctx.fillRect(0, 0, size, size);
|
|
86
|
-
const img = new Image();
|
|
87
|
-
const greenImageSrc = canvas.toDataURL();
|
|
88
|
-
img.src = greenImageSrc;
|
|
89
|
-
const svg = (0, exports.createForeignObjectSVG)(size, size, 0, 0, img);
|
|
90
|
-
ctx.fillStyle = 'red';
|
|
91
|
-
ctx.fillRect(0, 0, size, size);
|
|
92
|
-
return (0, exports.loadSerializedSVG)(svg)
|
|
93
|
-
.then((img) => {
|
|
94
|
-
ctx.drawImage(img, 0, 0);
|
|
95
|
-
const data = ctx.getImageData(0, 0, size, size).data;
|
|
96
|
-
ctx.fillStyle = 'red';
|
|
97
|
-
ctx.fillRect(0, 0, size, size);
|
|
98
|
-
const node = document.createElement('div');
|
|
99
|
-
node.style.backgroundImage = `url(${greenImageSrc})`;
|
|
100
|
-
node.style.height = `${size}px`;
|
|
101
|
-
// Firefox 55 does not render inline <img /> tags
|
|
102
|
-
return isGreenPixel(data)
|
|
103
|
-
? (0, exports.loadSerializedSVG)((0, exports.createForeignObjectSVG)(size, size, 0, 0, node))
|
|
104
|
-
: Promise.reject(new Error('ForeignObject rendering not supported'));
|
|
105
|
-
})
|
|
106
|
-
.then((img) => {
|
|
107
|
-
ctx.drawImage(img, 0, 0);
|
|
108
|
-
// Edge does not render background-images
|
|
109
|
-
return isGreenPixel(ctx.getImageData(0, 0, size, size).data);
|
|
110
|
-
})
|
|
111
|
-
.catch(() => false);
|
|
112
|
-
};
|
|
113
|
-
const createForeignObjectSVG = (width, height, x, y, node) => {
|
|
114
|
-
const xmlns = 'http://www.w3.org/2000/svg';
|
|
115
|
-
const svg = document.createElementNS(xmlns, 'svg');
|
|
116
|
-
const foreignObject = document.createElementNS(xmlns, 'foreignObject');
|
|
117
|
-
svg.setAttributeNS(null, 'width', width.toString());
|
|
118
|
-
svg.setAttributeNS(null, 'height', height.toString());
|
|
119
|
-
foreignObject.setAttributeNS(null, 'width', '100%');
|
|
120
|
-
foreignObject.setAttributeNS(null, 'height', '100%');
|
|
121
|
-
foreignObject.setAttributeNS(null, 'x', x.toString());
|
|
122
|
-
foreignObject.setAttributeNS(null, 'y', y.toString());
|
|
123
|
-
foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
|
|
124
|
-
svg.appendChild(foreignObject);
|
|
125
|
-
foreignObject.appendChild(node);
|
|
126
|
-
return svg;
|
|
127
|
-
};
|
|
128
|
-
exports.createForeignObjectSVG = createForeignObjectSVG;
|
|
129
|
-
const loadSerializedSVG = (svg) => {
|
|
130
|
-
return new Promise((resolve, reject) => {
|
|
131
|
-
const img = new Image();
|
|
132
|
-
img.onload = () => resolve(img);
|
|
133
|
-
img.onerror = reject;
|
|
134
|
-
img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
|
|
135
|
-
});
|
|
136
|
-
};
|
|
137
|
-
exports.loadSerializedSVG = loadSerializedSVG;
|
|
138
|
-
exports.FEATURES = {
|
|
139
|
-
get SUPPORT_RANGE_BOUNDS() {
|
|
140
|
-
'use strict';
|
|
141
|
-
const value = testRangeBounds(document);
|
|
142
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_RANGE_BOUNDS', { value });
|
|
143
|
-
return value;
|
|
144
|
-
},
|
|
145
|
-
get SUPPORT_WORD_BREAKING() {
|
|
146
|
-
'use strict';
|
|
147
|
-
const value = exports.FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);
|
|
148
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_WORD_BREAKING', { value });
|
|
149
|
-
return value;
|
|
150
|
-
},
|
|
151
|
-
get SUPPORT_SVG_DRAWING() {
|
|
152
|
-
'use strict';
|
|
153
|
-
const value = testSVG(document);
|
|
154
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_SVG_DRAWING', { value });
|
|
155
|
-
return value;
|
|
156
|
-
},
|
|
157
|
-
get SUPPORT_FOREIGNOBJECT_DRAWING() {
|
|
158
|
-
'use strict';
|
|
159
|
-
const value = typeof Array.from === 'function' && typeof window.fetch === 'function'
|
|
160
|
-
? testForeignObject(document)
|
|
161
|
-
: Promise.resolve(false);
|
|
162
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', { value });
|
|
163
|
-
return value;
|
|
164
|
-
},
|
|
165
|
-
get SUPPORT_CORS_IMAGES() {
|
|
166
|
-
'use strict';
|
|
167
|
-
const value = testCORS();
|
|
168
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_CORS_IMAGES', { value });
|
|
169
|
-
return value;
|
|
170
|
-
},
|
|
171
|
-
get SUPPORT_RESPONSE_TYPE() {
|
|
172
|
-
'use strict';
|
|
173
|
-
const value = testResponseType();
|
|
174
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_RESPONSE_TYPE', { value });
|
|
175
|
-
return value;
|
|
176
|
-
},
|
|
177
|
-
get SUPPORT_CORS_XHR() {
|
|
178
|
-
'use strict';
|
|
179
|
-
const value = 'withCredentials' in new XMLHttpRequest();
|
|
180
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_CORS_XHR', { value });
|
|
181
|
-
return value;
|
|
182
|
-
},
|
|
183
|
-
get SUPPORT_NATIVE_TEXT_SEGMENTATION() {
|
|
184
|
-
'use strict';
|
|
185
|
-
// Intl.Segmenter is TC39 Stage 4 but not yet in TS lib types
|
|
186
|
-
const value = !!(typeof Intl !== 'undefined' && Intl.Segmenter);
|
|
187
|
-
Object.defineProperty(exports.FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', { value });
|
|
188
|
-
return value;
|
|
189
|
-
}
|
|
190
|
-
};
|