@pixldocs/canvas-renderer 0.3.18 → 0.3.19
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/index.cjs +79 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +58 -0
- package/dist/index.js +80 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,15 @@ export declare function collectFontDescriptorsFromConfig(config: TemplateConfig)
|
|
|
43
43
|
*/
|
|
44
44
|
export declare function collectFontsFromConfig(config: TemplateConfig): Set<string>;
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Collect all image asset URLs from a TemplateConfig that the Fabric canvas
|
|
48
|
+
* will request during rendering. This is the canonical list — the same logic
|
|
49
|
+
* that `getExpectedImageCount` uses, but returning URLs instead of a count.
|
|
50
|
+
*
|
|
51
|
+
* Walks **all pages** and recurses into children / groups.
|
|
52
|
+
*/
|
|
53
|
+
export declare function collectImageUrls(config: TemplateConfig): string[];
|
|
54
|
+
|
|
46
55
|
export declare interface DynamicField {
|
|
47
56
|
id: string;
|
|
48
57
|
label: string;
|
|
@@ -316,4 +325,53 @@ export declare interface ThemeVariables {
|
|
|
316
325
|
[variableName: string]: string;
|
|
317
326
|
}
|
|
318
327
|
|
|
328
|
+
export declare interface WarmOptions {
|
|
329
|
+
/** AbortSignal to cancel in-flight prefetches (e.g. on route change). */
|
|
330
|
+
signal?: AbortSignal;
|
|
331
|
+
/** Image proxy base URL. Falls back to the value set via `setPackageApiUrl`. */
|
|
332
|
+
imageProxyUrl?: string;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Warm fonts **and** image assets for a fully-resolved `TemplateConfig`.
|
|
337
|
+
*
|
|
338
|
+
* Call this on idle / in the background before rendering so that `render()`
|
|
339
|
+
* resolves from browser caches instead of hitting the network.
|
|
340
|
+
*
|
|
341
|
+
* **Idempotent** — repeated calls for the same config are near-instant
|
|
342
|
+
* (fonts deduplicate internally; `fetch` hits HTTP cache).
|
|
343
|
+
*
|
|
344
|
+
* Does **not** mount a canvas or require React.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* import { warmResolvedTemplateForPreview } from '@pixldocs/canvas-renderer';
|
|
349
|
+
*
|
|
350
|
+
* const controller = new AbortController();
|
|
351
|
+
* await warmResolvedTemplateForPreview(resolvedConfig, { signal: controller.signal });
|
|
352
|
+
* // Later: renderer.render(resolvedConfig) — fonts & images are cached
|
|
353
|
+
* ```
|
|
354
|
+
*/
|
|
355
|
+
export declare function warmResolvedTemplateForPreview(config: TemplateConfig, options?: WarmOptions): Promise<void>;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Convenience: resolve a template from the database **and** warm its assets
|
|
359
|
+
* in a single call. Combines `resolveFromForm` + `warmResolvedTemplateForPreview`.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* import { warmTemplateFromForm } from '@pixldocs/canvas-renderer';
|
|
364
|
+
*
|
|
365
|
+
* await warmTemplateFromForm({
|
|
366
|
+
* templateId: 'dc3fbb17-...',
|
|
367
|
+
* formSchemaId: 'b04cd362-...',
|
|
368
|
+
* sectionState: { ... },
|
|
369
|
+
* supabaseUrl: '...',
|
|
370
|
+
* supabaseAnonKey: '...',
|
|
371
|
+
* signal: controller.signal,
|
|
372
|
+
* });
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
export declare function warmTemplateFromForm(options: ResolveFromFormOptions & WarmOptions): Promise<void>;
|
|
376
|
+
|
|
319
377
|
export { }
|
package/dist/index.js
CHANGED
|
@@ -10923,16 +10923,95 @@ class PixldocsRenderer {
|
|
|
10923
10923
|
});
|
|
10924
10924
|
}
|
|
10925
10925
|
}
|
|
10926
|
+
function collectImageUrls(config) {
|
|
10927
|
+
const urls = [];
|
|
10928
|
+
const walk = (nodes) => {
|
|
10929
|
+
for (const node of nodes) {
|
|
10930
|
+
if (!node || node.visible === false) continue;
|
|
10931
|
+
const src = typeof node.src === "string" ? node.src.trim() : "";
|
|
10932
|
+
const imageUrl = typeof node.imageUrl === "string" ? node.imageUrl.trim() : "";
|
|
10933
|
+
if (node.type === "image") {
|
|
10934
|
+
const url = src || imageUrl;
|
|
10935
|
+
if (url) urls.push(url);
|
|
10936
|
+
}
|
|
10937
|
+
if (Array.isArray(node.children) && node.children.length > 0) {
|
|
10938
|
+
walk(node.children);
|
|
10939
|
+
}
|
|
10940
|
+
}
|
|
10941
|
+
};
|
|
10942
|
+
for (const page of config.pages || []) {
|
|
10943
|
+
walk(page.children || []);
|
|
10944
|
+
}
|
|
10945
|
+
return urls;
|
|
10946
|
+
}
|
|
10947
|
+
function normalizeAssetUrl(rawUrl, imageProxyUrl) {
|
|
10948
|
+
if (!rawUrl) return null;
|
|
10949
|
+
if (rawUrl.startsWith("data:") || rawUrl.startsWith("blob:")) return null;
|
|
10950
|
+
try {
|
|
10951
|
+
const h = new URL(rawUrl).hostname.toLowerCase();
|
|
10952
|
+
if (h === "localhost" || h === "127.0.0.1" || h === "0.0.0.0" || h.endsWith(".local") || /^(10\.|192\.168\.|169\.254\.)/.test(h)) {
|
|
10953
|
+
return null;
|
|
10954
|
+
}
|
|
10955
|
+
} catch {
|
|
10956
|
+
return null;
|
|
10957
|
+
}
|
|
10958
|
+
const supabaseUrl = typeof globalThis.__VITE_SUPABASE_URL === "string" ? globalThis.__VITE_SUPABASE_URL : "";
|
|
10959
|
+
if (supabaseUrl && rawUrl.includes(supabaseUrl)) {
|
|
10960
|
+
const signedMatch = rawUrl.match(/\/storage\/v1\/object\/sign\/([^?]+)/);
|
|
10961
|
+
if (signedMatch) return `${supabaseUrl}/storage/v1/object/public/${signedMatch[1]}`;
|
|
10962
|
+
if (rawUrl.includes("/storage/v1/object/public/")) return rawUrl;
|
|
10963
|
+
}
|
|
10964
|
+
const proxyBase = imageProxyUrl ? imageProxyUrl.replace(/\/image-proxy(?:\?.*)?$/, "") : API_URL;
|
|
10965
|
+
if (proxyBase) {
|
|
10966
|
+
return `${proxyBase}/image-proxy?url=${encodeURIComponent(rawUrl)}`;
|
|
10967
|
+
}
|
|
10968
|
+
return rawUrl;
|
|
10969
|
+
}
|
|
10970
|
+
const CONCURRENCY = 6;
|
|
10971
|
+
async function prefetchUrls(urls, signal) {
|
|
10972
|
+
const unique = [...new Set(urls)];
|
|
10973
|
+
if (unique.length === 0) return;
|
|
10974
|
+
let i = 0;
|
|
10975
|
+
const next = async () => {
|
|
10976
|
+
while (i < unique.length) {
|
|
10977
|
+
if (signal == null ? void 0 : signal.aborted) return;
|
|
10978
|
+
const url = unique[i++];
|
|
10979
|
+
try {
|
|
10980
|
+
await fetch(url, { signal, mode: "cors", credentials: "omit" });
|
|
10981
|
+
} catch {
|
|
10982
|
+
}
|
|
10983
|
+
}
|
|
10984
|
+
};
|
|
10985
|
+
const workers = Array.from({ length: Math.min(CONCURRENCY, unique.length) }, () => next());
|
|
10986
|
+
await Promise.all(workers);
|
|
10987
|
+
}
|
|
10988
|
+
async function warmResolvedTemplateForPreview(config, options) {
|
|
10989
|
+
const { signal, imageProxyUrl } = options ?? {};
|
|
10990
|
+
await ensureFontsForResolvedConfig(config);
|
|
10991
|
+
if (signal == null ? void 0 : signal.aborted) return;
|
|
10992
|
+
const rawUrls = collectImageUrls(config);
|
|
10993
|
+
const resolvedUrls = rawUrls.map((u) => normalizeAssetUrl(u, imageProxyUrl)).filter((u) => u !== null);
|
|
10994
|
+
await prefetchUrls(resolvedUrls, signal);
|
|
10995
|
+
}
|
|
10996
|
+
async function warmTemplateFromForm(options) {
|
|
10997
|
+
const { signal, imageProxyUrl, ...resolveOpts } = options;
|
|
10998
|
+
const resolved = await resolveFromForm(resolveOpts);
|
|
10999
|
+
if (signal == null ? void 0 : signal.aborted) return;
|
|
11000
|
+
await warmResolvedTemplateForPreview(resolved.config, { signal, imageProxyUrl });
|
|
11001
|
+
}
|
|
10926
11002
|
export {
|
|
10927
11003
|
PixldocsPreview,
|
|
10928
11004
|
PixldocsRenderer,
|
|
10929
11005
|
applyThemeToConfig,
|
|
10930
11006
|
collectFontDescriptorsFromConfig,
|
|
10931
11007
|
collectFontsFromConfig,
|
|
11008
|
+
collectImageUrls,
|
|
10932
11009
|
ensureFontsForResolvedConfig,
|
|
10933
11010
|
loadGoogleFontCSS,
|
|
10934
11011
|
normalizeFontFamily,
|
|
10935
11012
|
resolveFromForm,
|
|
10936
|
-
resolveTemplateData
|
|
11013
|
+
resolveTemplateData,
|
|
11014
|
+
warmResolvedTemplateForPreview,
|
|
11015
|
+
warmTemplateFromForm
|
|
10937
11016
|
};
|
|
10938
11017
|
//# sourceMappingURL=index.js.map
|