@pixldocs/canvas-renderer 0.5.190 → 0.5.191
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 +40 -0
- package/dist/{index-BUm3wqlB.cjs → index-BJR7zaam.cjs} +129 -9
- package/dist/{index-BUm3wqlB.cjs.map → index-BJR7zaam.cjs.map} +1 -1
- package/dist/{index-Dt4aPZtQ.js → index-C3kuDISv.js} +129 -9
- package/dist/{index-Dt4aPZtQ.js.map → index-C3kuDISv.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +38 -0
- package/dist/index.js +1 -1
- package/dist/{vectorPdfExport-DFGqTzvI.js → vectorPdfExport-CrTGqxx6.js} +7 -7
- package/dist/{vectorPdfExport-DFGqTzvI.js.map → vectorPdfExport-CrTGqxx6.js.map} +1 -1
- package/dist/{vectorPdfExport-Cgw8dB-L.cjs → vectorPdfExport-D_2mdcwO.cjs} +7 -7
- package/dist/{vectorPdfExport-Cgw8dB-L.cjs.map → vectorPdfExport-D_2mdcwO.cjs.map} +1 -1
- package/package.json +1 -1
|
@@ -16889,9 +16889,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
|
|
|
16889
16889
|
}
|
|
16890
16890
|
return svgString;
|
|
16891
16891
|
}
|
|
16892
|
-
const resolvedPackageVersion = "0.5.
|
|
16892
|
+
const resolvedPackageVersion = "0.5.191";
|
|
16893
16893
|
const PACKAGE_VERSION = resolvedPackageVersion;
|
|
16894
|
-
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.
|
|
16894
|
+
const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.191";
|
|
16895
16895
|
const roundParityValue = (value) => {
|
|
16896
16896
|
if (typeof value !== "number") return value;
|
|
16897
16897
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -16918,6 +16918,96 @@ function isFabricTextboxLike(obj) {
|
|
|
16918
16918
|
function isFabricGroupLike(obj) {
|
|
16919
16919
|
return !!obj && (obj instanceof fabric.Group || obj.type === "group" || Array.isArray(obj._objects) && typeof obj.getObjects === "function");
|
|
16920
16920
|
}
|
|
16921
|
+
function configHasUserDataImage(config) {
|
|
16922
|
+
let found = false;
|
|
16923
|
+
const isRasterDataUrl = (u) => typeof u === "string" && /^data:image\/(jpeg|jpg|png|webp)[;,]/i.test(u);
|
|
16924
|
+
const walk = (nodes) => {
|
|
16925
|
+
if (found || !Array.isArray(nodes)) return;
|
|
16926
|
+
for (const node of nodes) {
|
|
16927
|
+
if (!node || typeof node !== "object") continue;
|
|
16928
|
+
if (node.type === "image" && (isRasterDataUrl(node.src) || isRasterDataUrl(node.imageUrl))) {
|
|
16929
|
+
found = true;
|
|
16930
|
+
return;
|
|
16931
|
+
}
|
|
16932
|
+
if (Array.isArray(node.children)) walk(node.children);
|
|
16933
|
+
}
|
|
16934
|
+
};
|
|
16935
|
+
for (const page of config.pages ?? []) {
|
|
16936
|
+
walk((page == null ? void 0 : page.children) ?? []);
|
|
16937
|
+
if (found) break;
|
|
16938
|
+
}
|
|
16939
|
+
return found;
|
|
16940
|
+
}
|
|
16941
|
+
function detectSafariOrIos() {
|
|
16942
|
+
try {
|
|
16943
|
+
if (typeof navigator === "undefined") return false;
|
|
16944
|
+
const ua = navigator.userAgent || "";
|
|
16945
|
+
const vendor = navigator.vendor || "";
|
|
16946
|
+
const isIOS = /iPad|iPhone|iPod/.test(ua) || // iPadOS 13+ reports as Mac with touch
|
|
16947
|
+
/Macintosh/.test(ua) && typeof navigator.maxTouchPoints === "number" && navigator.maxTouchPoints > 1;
|
|
16948
|
+
const isSafariDesktop = /Safari/.test(ua) && /Apple/.test(vendor) && !/Chrome|CriOS|Chromium|Edg|FxiOS/.test(ua);
|
|
16949
|
+
return isIOS || isSafariDesktop;
|
|
16950
|
+
} catch {
|
|
16951
|
+
return false;
|
|
16952
|
+
}
|
|
16953
|
+
}
|
|
16954
|
+
async function downscaleConfigRasterImages(config, maxEdgePx) {
|
|
16955
|
+
if (!maxEdgePx || maxEdgePx <= 0) return 0;
|
|
16956
|
+
if (typeof document === "undefined") return 0;
|
|
16957
|
+
const targets = [];
|
|
16958
|
+
const isRasterDataUrl = (u) => typeof u === "string" && /^data:image\/(jpeg|jpg|png|webp)[;,]/i.test(u);
|
|
16959
|
+
const walk = (nodes) => {
|
|
16960
|
+
if (!Array.isArray(nodes)) return;
|
|
16961
|
+
for (const node of nodes) {
|
|
16962
|
+
if (!node || typeof node !== "object") continue;
|
|
16963
|
+
if (node.type === "image") {
|
|
16964
|
+
if (isRasterDataUrl(node.src)) targets.push({ node, field: "src" });
|
|
16965
|
+
else if (isRasterDataUrl(node.imageUrl)) targets.push({ node, field: "imageUrl" });
|
|
16966
|
+
}
|
|
16967
|
+
if (Array.isArray(node.children)) walk(node.children);
|
|
16968
|
+
}
|
|
16969
|
+
};
|
|
16970
|
+
for (const page of config.pages ?? []) walk((page == null ? void 0 : page.children) ?? []);
|
|
16971
|
+
if (targets.length === 0) return 0;
|
|
16972
|
+
const shrinkOne = async (dataUrl) => {
|
|
16973
|
+
try {
|
|
16974
|
+
const img = await new Promise((resolve, reject) => {
|
|
16975
|
+
const el = new Image();
|
|
16976
|
+
el.onload = () => resolve(el);
|
|
16977
|
+
el.onerror = (e) => reject(e);
|
|
16978
|
+
el.decoding = "sync";
|
|
16979
|
+
el.src = dataUrl;
|
|
16980
|
+
});
|
|
16981
|
+
const w = img.naturalWidth, h = img.naturalHeight;
|
|
16982
|
+
if (!w || !h) return null;
|
|
16983
|
+
const longest = Math.max(w, h);
|
|
16984
|
+
if (longest <= maxEdgePx) return null;
|
|
16985
|
+
const scale = maxEdgePx / longest;
|
|
16986
|
+
const tw = Math.max(1, Math.round(w * scale));
|
|
16987
|
+
const th = Math.max(1, Math.round(h * scale));
|
|
16988
|
+
const canvas = document.createElement("canvas");
|
|
16989
|
+
canvas.width = tw;
|
|
16990
|
+
canvas.height = th;
|
|
16991
|
+
const ctx = canvas.getContext("2d");
|
|
16992
|
+
if (!ctx) return null;
|
|
16993
|
+
ctx.fillStyle = "#ffffff";
|
|
16994
|
+
ctx.fillRect(0, 0, tw, th);
|
|
16995
|
+
ctx.drawImage(img, 0, 0, tw, th);
|
|
16996
|
+
return canvas.toDataURL("image/jpeg", 0.85);
|
|
16997
|
+
} catch {
|
|
16998
|
+
return null;
|
|
16999
|
+
}
|
|
17000
|
+
};
|
|
17001
|
+
let shrunk = 0;
|
|
17002
|
+
for (const { node, field } of targets) {
|
|
17003
|
+
const next = await shrinkOne(String(node[field]));
|
|
17004
|
+
if (next) {
|
|
17005
|
+
node[field] = next;
|
|
17006
|
+
shrunk++;
|
|
17007
|
+
}
|
|
17008
|
+
}
|
|
17009
|
+
return shrunk;
|
|
17010
|
+
}
|
|
16921
17011
|
let __underlineFixInstalled = false;
|
|
16922
17012
|
function installUnderlineFix(fab) {
|
|
16923
17013
|
var _a;
|
|
@@ -17270,7 +17360,9 @@ class PixldocsRenderer {
|
|
|
17270
17360
|
async renderPdf(templateConfig, options) {
|
|
17271
17361
|
return this.renderPdfViaClientExport(templateConfig, {
|
|
17272
17362
|
title: options == null ? void 0 : options.title,
|
|
17273
|
-
textMode: options == null ? void 0 : options.textMode
|
|
17363
|
+
textMode: options == null ? void 0 : options.textMode,
|
|
17364
|
+
forcePerElementPdf: options == null ? void 0 : options.forcePerElementPdf,
|
|
17365
|
+
maxImageEdgePx: options == null ? void 0 : options.maxImageEdgePx
|
|
17274
17366
|
});
|
|
17275
17367
|
}
|
|
17276
17368
|
/**
|
|
@@ -17278,7 +17370,7 @@ class PixldocsRenderer {
|
|
|
17278
17370
|
* This is the primary PDF export API — mirrors renderFromForm() but returns a PDF.
|
|
17279
17371
|
*/
|
|
17280
17372
|
async renderPdfFromForm(options) {
|
|
17281
|
-
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode } = options;
|
|
17373
|
+
const { templateId, formSchemaId, sectionState, themeId, watermark, watermarkOptions, prefetched, title, fontBaseUrl, textMode, forcePerElementPdf, maxImageEdgePx } = options;
|
|
17282
17374
|
const resolved = await resolveFromForm({
|
|
17283
17375
|
templateId,
|
|
17284
17376
|
formSchemaId,
|
|
@@ -17299,7 +17391,9 @@ class PixldocsRenderer {
|
|
|
17299
17391
|
return this.renderPdfViaClientExport(configToRender, {
|
|
17300
17392
|
title: title ?? resolved.config.name,
|
|
17301
17393
|
watermark: shouldWatermark,
|
|
17302
|
-
textMode
|
|
17394
|
+
textMode,
|
|
17395
|
+
forcePerElementPdf,
|
|
17396
|
+
maxImageEdgePx
|
|
17303
17397
|
});
|
|
17304
17398
|
}
|
|
17305
17399
|
async renderById(templateId, formData, options) {
|
|
@@ -17340,6 +17434,31 @@ class PixldocsRenderer {
|
|
|
17340
17434
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
17341
17435
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
17342
17436
|
const cloned = JSON.parse(JSON.stringify(templateConfig));
|
|
17437
|
+
const callForce = options.forcePerElementPdf;
|
|
17438
|
+
const cfgForce = this.config.forcePerElementPdf;
|
|
17439
|
+
const forceMode = callForce !== void 0 ? callForce : cfgForce !== void 0 ? cfgForce : "auto";
|
|
17440
|
+
const hasUserDataImage = configHasUserDataImage(cloned);
|
|
17441
|
+
const isSafariLike = detectSafariOrIos();
|
|
17442
|
+
const shouldForcePerElement = forceMode === true ? true : forceMode === false ? false : hasUserDataImage && isSafariLike;
|
|
17443
|
+
const maxEdgeOpt = options.maxImageEdgePx ?? this.config.maxImageEdgePx;
|
|
17444
|
+
const effectiveMaxEdge = typeof maxEdgeOpt === "number" ? Math.max(0, maxEdgeOpt | 0) : shouldForcePerElement ? 2048 : 0;
|
|
17445
|
+
if (effectiveMaxEdge > 0) {
|
|
17446
|
+
try {
|
|
17447
|
+
const downscaled = await downscaleConfigRasterImages(cloned, effectiveMaxEdge);
|
|
17448
|
+
if (downscaled > 0) {
|
|
17449
|
+
console.log(`[canvas-renderer][pdf-unified] downscaled ${downscaled} raster image(s) to <=${effectiveMaxEdge}px edge`);
|
|
17450
|
+
}
|
|
17451
|
+
} catch (e) {
|
|
17452
|
+
console.warn("[canvas-renderer][pdf-unified] image downscale pass failed (continuing with originals):", e);
|
|
17453
|
+
}
|
|
17454
|
+
}
|
|
17455
|
+
console.log("[canvas-renderer][pdf-unified] export switches", {
|
|
17456
|
+
forceMode,
|
|
17457
|
+
hasUserDataImage,
|
|
17458
|
+
isSafariLike,
|
|
17459
|
+
shouldForcePerElement,
|
|
17460
|
+
effectiveMaxEdge
|
|
17461
|
+
});
|
|
17343
17462
|
const stampPrefix = `__pixldocs_pdf_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
17344
17463
|
const pageIds = cloned.pages.map((p, i) => {
|
|
17345
17464
|
const id = `${stampPrefix}_p${i}`;
|
|
@@ -17399,7 +17518,7 @@ class PixldocsRenderer {
|
|
|
17399
17518
|
await this.waitForCanvasScene(container, cloned, i);
|
|
17400
17519
|
}
|
|
17401
17520
|
console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
|
|
17402
|
-
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-
|
|
17521
|
+
const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CrTGqxx6.js");
|
|
17403
17522
|
const prepared = preparePagesForExport(
|
|
17404
17523
|
cloned.pages,
|
|
17405
17524
|
canvasWidth,
|
|
@@ -17409,7 +17528,8 @@ class PixldocsRenderer {
|
|
|
17409
17528
|
title: options.title,
|
|
17410
17529
|
watermark: !!options.watermark,
|
|
17411
17530
|
returnBlob: true,
|
|
17412
|
-
pdfTextMode: options.textMode ?? (cloned == null ? void 0 : cloned.pdfTextMode) ?? ((_a = cloned.canvas) == null ? void 0 : _a.n) ?? "auto"
|
|
17531
|
+
pdfTextMode: options.textMode ?? (cloned == null ? void 0 : cloned.pdfTextMode) ?? ((_a = cloned.canvas) == null ? void 0 : _a.n) ?? "auto",
|
|
17532
|
+
skipLiveCanvasSvgFastPath: shouldForcePerElement
|
|
17413
17533
|
});
|
|
17414
17534
|
if (!result || typeof result === "undefined") {
|
|
17415
17535
|
throw new Error("exportMultiPagePdf returned no blob (returnBlob path failed)");
|
|
@@ -19544,7 +19664,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
|
|
|
19544
19664
|
if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
|
|
19545
19665
|
sanitizeSvgTreeForPdf(svgToDraw);
|
|
19546
19666
|
try {
|
|
19547
|
-
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-
|
|
19667
|
+
const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CrTGqxx6.js");
|
|
19548
19668
|
try {
|
|
19549
19669
|
await logTextMeasurementDiagnostic(svgToDraw);
|
|
19550
19670
|
} catch {
|
|
@@ -19944,4 +20064,4 @@ export {
|
|
|
19944
20064
|
buildTeaserBlurFlatKeys as y,
|
|
19945
20065
|
collectFontDescriptorsFromConfig as z
|
|
19946
20066
|
};
|
|
19947
|
-
//# sourceMappingURL=index-
|
|
20067
|
+
//# sourceMappingURL=index-C3kuDISv.js.map
|