wasm-html-to-image 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core-orchestrate.js +1 -1
- package/dist/core-resources.d.ts +2 -0
- package/dist/core-resources.js +29 -2
- package/dist/diagnostics.d.ts +5 -0
- package/dist/html-to-image-wasm.js +3 -3
- package/dist/html-to-image.wasm +0 -0
- package/dist/web-workers.js +37 -40
- package/dist/workers-parent.js +10 -20
- package/package.json +2 -2
package/dist/core-orchestrate.js
CHANGED
|
@@ -132,7 +132,7 @@ export function createOrchestration(module, options) {
|
|
|
132
132
|
limits,
|
|
133
133
|
resolveResource,
|
|
134
134
|
diag,
|
|
135
|
-
usage: { resourceCount: 0, totalResourceBytes: 0 },
|
|
135
|
+
usage: { resourceCount: 0, totalResourceBytes: 0, fontsSkippedByCount: 0 },
|
|
136
136
|
t0,
|
|
137
137
|
emitLog,
|
|
138
138
|
addTime,
|
package/dist/core-resources.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface DiagState {
|
|
|
37
37
|
export interface ResourceUsage {
|
|
38
38
|
resourceCount: number;
|
|
39
39
|
totalResourceBytes: number;
|
|
40
|
+
/** Font files dropped because `maxResourceCount` was reached (across all rounds). */
|
|
41
|
+
fontsSkippedByCount: number;
|
|
40
42
|
}
|
|
41
43
|
/** Resolution context threaded through HTML discovery (internal). */
|
|
42
44
|
export interface ResolveContext {
|
package/dist/core-resources.js
CHANGED
|
@@ -108,7 +108,8 @@ async function fetchResourceBytesInner(url, baseUrl, userAgent, timeoutMs, confi
|
|
|
108
108
|
const headers = userAgent && isNodeRuntime() ? { "User-Agent": userAgent } : undefined;
|
|
109
109
|
// Abort hung connections so one stalled server cannot outlive `timeoutMs`.
|
|
110
110
|
const signal = timeoutMs !== undefined
|
|
111
|
-
?
|
|
111
|
+
? // Node >= 24 requires an integer delay; the remaining budget is fractional.
|
|
112
|
+
AbortSignal.timeout(Math.max(1, Math.ceil(timeoutMs)))
|
|
112
113
|
: undefined;
|
|
113
114
|
const fetchBytes = async (target) => {
|
|
114
115
|
// Servers may vary the body by User-Agent (e.g. woff2 vs ttf CSS).
|
|
@@ -440,7 +441,16 @@ export async function resolveHtmlResources(module, satoruInst, htmls, width, hei
|
|
|
440
441
|
// later sheet must not land before (and so lose to) a large earlier one. They are
|
|
441
442
|
// buffered here and injected in discovery order once the whole round has settled.
|
|
442
443
|
const loadedCss = [];
|
|
443
|
-
|
|
444
|
+
// When maxResourceCount cuts a round short, what is dropped should be the least harmful: a missing
|
|
445
|
+
// image leaves a hole, a missing font turns the whole text into tofu. Stylesheets go first (they
|
|
446
|
+
// cascade by document order and may reveal more), then fonts, then images; discovery order is
|
|
447
|
+
// kept within each kind.
|
|
448
|
+
const rank = (t) => (t === "css" ? 0 : t === "font" ? 1 : 2);
|
|
449
|
+
const ordered = pending
|
|
450
|
+
.map((r, i) => ({ r, i }))
|
|
451
|
+
.sort((a, b) => rank(a.r.type) - rank(b.r.type) || a.i - b.i)
|
|
452
|
+
.map((e) => e.r);
|
|
453
|
+
await mapWithLimit(ordered, FETCH_CONCURRENCY, async (r) => {
|
|
444
454
|
const diag = ctx.diag;
|
|
445
455
|
const entry = diag
|
|
446
456
|
? {
|
|
@@ -482,6 +492,8 @@ export async function resolveHtmlResources(module, satoruInst, htmls, width, hei
|
|
|
482
492
|
if (ctx.limits.maxResourceCount !== undefined &&
|
|
483
493
|
ctx.usage.resourceCount >= ctx.limits.maxResourceCount) {
|
|
484
494
|
const message = `Maximum resource count (${ctx.limits.maxResourceCount}) exceeded`;
|
|
495
|
+
if (r.type === "font")
|
|
496
|
+
ctx.usage.fontsSkippedByCount++;
|
|
485
497
|
skipWithError(DIAGNOSTIC_CODES.LIMIT_RESOURCE_COUNT, message);
|
|
486
498
|
return;
|
|
487
499
|
}
|
|
@@ -546,6 +558,21 @@ export async function resolveHtmlResources(module, satoruInst, htmls, width, hei
|
|
|
546
558
|
(await addRes(satoruInst, css.url, 3, bytes));
|
|
547
559
|
}
|
|
548
560
|
}
|
|
561
|
+
if (ctx.usage.fontsSkippedByCount > 0) {
|
|
562
|
+
// Text in those fonts renders as tofu: say what to change instead of leaving a silent bad image.
|
|
563
|
+
// One message for the whole render, however many discovery rounds hit the limit.
|
|
564
|
+
const message = `${ctx.usage.fontsSkippedByCount} font file(s) were not loaded because maxResourceCount ` +
|
|
565
|
+
`(${ctx.limits.maxResourceCount}) was reached; text using them may render as missing glyphs. ` +
|
|
566
|
+
"Raise limits.maxResourceCount (a Google Fonts stylesheet alone can reference over a hundred files).";
|
|
567
|
+
ctx.diag?.warnings.push({
|
|
568
|
+
code: DIAGNOSTIC_CODES.LIMIT_RESOURCE_COUNT,
|
|
569
|
+
message,
|
|
570
|
+
});
|
|
571
|
+
ctx.emitLog(LogLevel.Warning, message);
|
|
572
|
+
if (ctx.limits.strictFonts) {
|
|
573
|
+
throw new Error(`[${DIAGNOSTIC_CODES.LIMIT_RESOURCE_COUNT}] ${message}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
549
576
|
// Merge the C++ collect-phase breakdown into the JS timings.
|
|
550
577
|
if (profileEnabled && ctx.diag) {
|
|
551
578
|
const getProfile = module.satoru_get_collect_profile;
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -108,6 +108,11 @@ export interface RenderLimits {
|
|
|
108
108
|
maxTotalResourceBytes?: number;
|
|
109
109
|
/** Maximum number of resources to load. */
|
|
110
110
|
maxResourceCount?: number;
|
|
111
|
+
/**
|
|
112
|
+
* Throw (code `LIMIT_RESOURCE_COUNT`) instead of rendering when font files had to be skipped
|
|
113
|
+
* because of `maxResourceCount`, so text is never silently drawn as missing glyphs. Default `false`.
|
|
114
|
+
*/
|
|
115
|
+
strictFonts?: boolean;
|
|
111
116
|
/** Allowed URL protocols (e.g. `["http:", "https:"]`). */
|
|
112
117
|
allowedProtocols?: string[];
|
|
113
118
|
/** Allowed hostnames. */
|