@pixldocs/canvas-renderer 0.5.52 → 0.5.54
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 +107 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +107 -7
- package/dist/index.js.map +1 -1
- package/dist/svgTextToPath-BP0Kppla.js +1083 -0
- package/dist/svgTextToPath-BP0Kppla.js.map +1 -0
- package/dist/svgTextToPath-BTHnqJpM.cjs +1105 -0
- package/dist/svgTextToPath-BTHnqJpM.cjs.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { FormConfig } from '../../../src/lib/formsApi';
|
|
2
|
+
import { getProxiedImageUrl } from '../../../src/lib/canvasImageLoader';
|
|
2
3
|
import { InferredSection } from '../../../src/lib/inferFormSchemaFromTemplate';
|
|
4
|
+
import { isBundledAssetUrl } from '../../../src/lib/canvasImageLoader';
|
|
5
|
+
import { isPrivateUrl } from '../../../src/lib/canvasImageLoader';
|
|
3
6
|
import { jsPDF } from 'jspdf';
|
|
4
7
|
import { JSX as JSX_2 } from 'react/jsx-runtime';
|
|
5
8
|
import { SectionFormState } from '../../../src/lib/inferFormSchemaFromTemplate';
|
|
9
|
+
import { setBundledAssetPrefixes } from '../../../src/lib/canvasImageLoader';
|
|
6
10
|
import { SmartElementProps } from '../../../shared/smart-elements/types';
|
|
7
11
|
import { SmartElementType } from '../../../shared/smart-elements/types';
|
|
8
12
|
|
|
@@ -200,11 +204,17 @@ declare type FormDefSection = {
|
|
|
200
204
|
*/
|
|
201
205
|
export declare function getEmbeddedJsPDFFontName(fontName: string, weight: number, isItalic?: boolean): string;
|
|
202
206
|
|
|
207
|
+
export { getProxiedImageUrl }
|
|
208
|
+
|
|
203
209
|
export { InferredSection }
|
|
204
210
|
|
|
211
|
+
export { isBundledAssetUrl }
|
|
212
|
+
|
|
205
213
|
/** Check if a font is in our local mapping */
|
|
206
214
|
export declare function isFontAvailable(fontName: string): boolean;
|
|
207
215
|
|
|
216
|
+
export { isPrivateUrl }
|
|
217
|
+
|
|
208
218
|
/**
|
|
209
219
|
* Load a Google Font by injecting a <link> stylesheet.
|
|
210
220
|
* Resolves when the font is ready for use.
|
|
@@ -221,7 +231,7 @@ export declare function normalizeFontFamily(fontStack: string): string;
|
|
|
221
231
|
* Package version banner. Bump alongside package.json so we can confirm
|
|
222
232
|
* (via browser:log) that the deployed bundle matches the expected build.
|
|
223
233
|
*/
|
|
224
|
-
export declare const PACKAGE_VERSION = "0.5.
|
|
234
|
+
export declare const PACKAGE_VERSION = "0.5.54";
|
|
225
235
|
|
|
226
236
|
export declare interface PageSettings {
|
|
227
237
|
backgroundColor?: string;
|
|
@@ -540,6 +550,8 @@ export declare function rewriteSvgFontsForJsPDF(svgStr: string): string;
|
|
|
540
550
|
|
|
541
551
|
export { SectionFormState }
|
|
542
552
|
|
|
553
|
+
export { setBundledAssetPrefixes }
|
|
554
|
+
|
|
543
555
|
export { SmartElementProps }
|
|
544
556
|
|
|
545
557
|
export { SmartElementType }
|
package/dist/index.js
CHANGED
|
@@ -2839,6 +2839,49 @@ function isPrivateUrl(url) {
|
|
|
2839
2839
|
return false;
|
|
2840
2840
|
}
|
|
2841
2841
|
}
|
|
2842
|
+
const DEFAULT_BUNDLED_PREFIXES = ["/pixldocs-bundled-assets/"];
|
|
2843
|
+
let bundledPrefixes = [...DEFAULT_BUNDLED_PREFIXES];
|
|
2844
|
+
function setBundledAssetPrefixes(prefixes) {
|
|
2845
|
+
const combined = /* @__PURE__ */ new Set([...DEFAULT_BUNDLED_PREFIXES]);
|
|
2846
|
+
for (const p of prefixes || []) {
|
|
2847
|
+
if (typeof p === "string" && p.startsWith("/")) combined.add(p);
|
|
2848
|
+
}
|
|
2849
|
+
bundledPrefixes = Array.from(combined);
|
|
2850
|
+
}
|
|
2851
|
+
function pathnameStartsWithBundledPrefix(pathname) {
|
|
2852
|
+
return bundledPrefixes.some((prefix) => pathname.startsWith(prefix));
|
|
2853
|
+
}
|
|
2854
|
+
function isBundledAssetUrl(url) {
|
|
2855
|
+
if (!url) return false;
|
|
2856
|
+
if (url.startsWith("/") && !url.startsWith("//")) {
|
|
2857
|
+
return pathnameStartsWithBundledPrefix(url);
|
|
2858
|
+
}
|
|
2859
|
+
try {
|
|
2860
|
+
const parsed = new URL(url);
|
|
2861
|
+
if (typeof window !== "undefined" && parsed.origin !== window.location.origin) {
|
|
2862
|
+
return false;
|
|
2863
|
+
}
|
|
2864
|
+
return pathnameStartsWithBundledPrefix(parsed.pathname);
|
|
2865
|
+
} catch {
|
|
2866
|
+
return false;
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
function resolveBundledAssetUrl(url) {
|
|
2870
|
+
if (!url) return null;
|
|
2871
|
+
if (url.startsWith("/") && !url.startsWith("//") && pathnameStartsWithBundledPrefix(url)) {
|
|
2872
|
+
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
2873
|
+
return origin ? new URL(url, origin).toString() : url;
|
|
2874
|
+
}
|
|
2875
|
+
try {
|
|
2876
|
+
const parsed = new URL(url);
|
|
2877
|
+
if (typeof window !== "undefined" && parsed.origin !== window.location.origin) return null;
|
|
2878
|
+
if (pathnameStartsWithBundledPrefix(parsed.pathname)) return parsed.toString();
|
|
2879
|
+
} catch {
|
|
2880
|
+
return null;
|
|
2881
|
+
}
|
|
2882
|
+
return null;
|
|
2883
|
+
}
|
|
2884
|
+
const loggedPrivateSkips = /* @__PURE__ */ new Set();
|
|
2842
2885
|
function toPublicStorageUrl(url) {
|
|
2843
2886
|
try {
|
|
2844
2887
|
const parsed = new URL(url);
|
|
@@ -2856,8 +2899,17 @@ function toPublicStorageUrl(url) {
|
|
|
2856
2899
|
function getProxiedImageUrl(imageUrl) {
|
|
2857
2900
|
if (!imageUrl) return "";
|
|
2858
2901
|
if (imageUrl.startsWith("data:") || imageUrl.startsWith("blob:")) return imageUrl;
|
|
2902
|
+
const bundled = resolveBundledAssetUrl(imageUrl);
|
|
2903
|
+
if (bundled) return bundled;
|
|
2904
|
+
if (imageUrl.startsWith("/") && !imageUrl.startsWith("//")) {
|
|
2905
|
+
if (typeof window !== "undefined") return new URL(imageUrl, window.location.origin).toString();
|
|
2906
|
+
return imageUrl;
|
|
2907
|
+
}
|
|
2859
2908
|
if (isPrivateUrl(imageUrl)) {
|
|
2860
|
-
|
|
2909
|
+
if (!loggedPrivateSkips.has(imageUrl)) {
|
|
2910
|
+
loggedPrivateSkips.add(imageUrl);
|
|
2911
|
+
console.debug("[image-proxy] Skipping private URL:", imageUrl.substring(0, 80));
|
|
2912
|
+
}
|
|
2861
2913
|
return "";
|
|
2862
2914
|
}
|
|
2863
2915
|
const publicUrl = toPublicStorageUrl(imageUrl);
|
|
@@ -4799,7 +4851,13 @@ function extractTextBgConfig(element) {
|
|
|
4799
4851
|
rxTL: Math.max(0, Number(element.textBgRxTL ?? 0)) || 0,
|
|
4800
4852
|
rxTR: Math.max(0, Number(element.textBgRxTR ?? 0)) || 0,
|
|
4801
4853
|
rxBR: Math.max(0, Number(element.textBgRxBR ?? 0)) || 0,
|
|
4802
|
-
rxBL: Math.max(0, Number(element.textBgRxBL ?? 0)) || 0
|
|
4854
|
+
rxBL: Math.max(0, Number(element.textBgRxBL ?? 0)) || 0,
|
|
4855
|
+
opacity: (() => {
|
|
4856
|
+
const n = Number(element.textBgOpacity);
|
|
4857
|
+
if (!Number.isFinite(n)) return void 0;
|
|
4858
|
+
return Math.max(0, Math.min(1, n));
|
|
4859
|
+
})(),
|
|
4860
|
+
shadowAffectsBg: element.textShadowAffectsBg !== false
|
|
4803
4861
|
};
|
|
4804
4862
|
}
|
|
4805
4863
|
function hasTextBackground(cfg) {
|
|
@@ -4860,6 +4918,13 @@ function applyTextBackground(obj, cfg) {
|
|
|
4860
4918
|
const bgW = w + pL + pR;
|
|
4861
4919
|
const bgH = h + pT + pB;
|
|
4862
4920
|
ctx.save();
|
|
4921
|
+
const suppressShadowOnBg = bg.shadowAffectsBg === false;
|
|
4922
|
+
if (suppressShadowOnBg) {
|
|
4923
|
+
ctx.shadowColor = "transparent";
|
|
4924
|
+
ctx.shadowBlur = 0;
|
|
4925
|
+
ctx.shadowOffsetX = 0;
|
|
4926
|
+
ctx.shadowOffsetY = 0;
|
|
4927
|
+
}
|
|
4863
4928
|
buildRoundedRectPath2D(
|
|
4864
4929
|
ctx,
|
|
4865
4930
|
x,
|
|
@@ -4871,6 +4936,8 @@ function applyTextBackground(obj, cfg) {
|
|
|
4871
4936
|
bg.rxBR ?? 0,
|
|
4872
4937
|
bg.rxBL ?? 0
|
|
4873
4938
|
);
|
|
4939
|
+
const op = typeof bg.opacity === "number" ? Math.max(0, Math.min(1, bg.opacity)) : 1;
|
|
4940
|
+
if (op < 1) ctx.globalAlpha = (ctx.globalAlpha ?? 1) * op;
|
|
4874
4941
|
ctx.fillStyle = bg.color;
|
|
4875
4942
|
ctx.fill();
|
|
4876
4943
|
ctx.restore();
|
|
@@ -4916,7 +4983,9 @@ function applyTextBackground(obj, cfg) {
|
|
|
4916
4983
|
(bg == null ? void 0 : bg.rxBL) ?? 0
|
|
4917
4984
|
);
|
|
4918
4985
|
const bgFill = (bg == null ? void 0 : bg.color) || "";
|
|
4919
|
-
const
|
|
4986
|
+
const bgOpacity = typeof (bg == null ? void 0 : bg.opacity) === "number" ? Math.max(0, Math.min(1, bg.opacity)) : 1;
|
|
4987
|
+
const bgOpacityAttr = bgOpacity < 1 ? ` fill-opacity="${bgOpacity}"` : "";
|
|
4988
|
+
const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}"${bgOpacityAttr} />` : "";
|
|
4920
4989
|
svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
|
|
4921
4990
|
svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
|
|
4922
4991
|
let bgShadowMarker = "";
|
|
@@ -4933,7 +5002,7 @@ function applyTextBackground(obj, cfg) {
|
|
|
4933
5002
|
const bh = h + pT + pB + pad * 2;
|
|
4934
5003
|
const dataAttrs = `data-blur="${blur.toFixed(3)}" data-ox="${ox.toFixed(3)}" data-oy="${oy.toFixed(3)}" data-bx="${bx.toFixed(3)}" data-by="${by.toFixed(3)}" data-bw="${bw.toFixed(3)}" data-bh="${bh.toFixed(3)}" data-color="${escapeXmlAttr(shadowColor)}"`;
|
|
4935
5004
|
const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
|
|
4936
|
-
if (hasBg) {
|
|
5005
|
+
if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
|
|
4937
5006
|
const shadowBgPath = `<path d="${bgD}" fill="${escapeXmlAttr(shadowColor)}" />`;
|
|
4938
5007
|
bgShadowMarker = wrapShadow(shadowBgPath);
|
|
4939
5008
|
}
|
|
@@ -12152,7 +12221,20 @@ function PixldocsPreview(props) {
|
|
|
12152
12221
|
onDynamicFieldClick,
|
|
12153
12222
|
onReady,
|
|
12154
12223
|
onError,
|
|
12155
|
-
|
|
12224
|
+
// Default `false` so PageCanvas blocks textbox creation until the host
|
|
12225
|
+
// browser actually has the @font-face rules registered. This matters for
|
|
12226
|
+
// `overflowPolicy: 'auto-shrink'` text — `createText` runs the shrink
|
|
12227
|
+
// loop synchronously at mount time using whatever font metrics Fabric
|
|
12228
|
+
// can measure right then. If the real font hasn't loaded yet, Fabric
|
|
12229
|
+
// falls back to the system font (typically narrower), the shrink loop
|
|
12230
|
+
// decides "fits, no shrink needed", and when the real font finally
|
|
12231
|
+
// loads the text overflows the box.
|
|
12232
|
+
//
|
|
12233
|
+
// The renderer's imperative PNG/PDF paths (`renderPageViaPreviewCanvas`,
|
|
12234
|
+
// `captureSvgViaPreviewCanvas`) already pass `skipFontReadyWait: false`
|
|
12235
|
+
// for this exact reason — that's why the downloaded PDF was correct
|
|
12236
|
+
// while the on-screen preview wasn't.
|
|
12237
|
+
skipFontReadyWait = false
|
|
12156
12238
|
} = props;
|
|
12157
12239
|
useEffect(() => {
|
|
12158
12240
|
setPackageApiUrl(imageProxyUrl);
|
|
@@ -12321,7 +12403,7 @@ function PixldocsPreview(props) {
|
|
|
12321
12403
|
!canvasSettled && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
|
|
12322
12404
|
] });
|
|
12323
12405
|
}
|
|
12324
|
-
const PACKAGE_VERSION = "0.5.
|
|
12406
|
+
const PACKAGE_VERSION = "0.5.54";
|
|
12325
12407
|
let __underlineFixInstalled = false;
|
|
12326
12408
|
function installUnderlineFix(fab) {
|
|
12327
12409
|
var _a;
|
|
@@ -15245,7 +15327,14 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
|
|
|
15245
15327
|
const hasGradient = !!((_b = (_a = page.backgroundGradient) == null ? void 0 : _a.stops) == null ? void 0 : _b.length);
|
|
15246
15328
|
drawPageBackground(pdf, i, page.width, page.height, page.backgroundColor, page.backgroundGradient);
|
|
15247
15329
|
const shouldStripBg = stripPageBackground ?? hasGradient;
|
|
15248
|
-
let
|
|
15330
|
+
let pageSvg = page.svg;
|
|
15331
|
+
try {
|
|
15332
|
+
const mod = await import("./svgTextToPath-BP0Kppla.js");
|
|
15333
|
+
pageSvg = await mod.convertAllTextToPath(pageSvg, fontBaseUrl);
|
|
15334
|
+
} catch (outlineErr) {
|
|
15335
|
+
console.warn(`[canvas-renderer pdf] page ${i + 1}: text outliner unavailable, continuing with text-as-text`, outlineErr);
|
|
15336
|
+
}
|
|
15337
|
+
let processedSvg = await prepareLiveCanvasSvgForPdf(pageSvg, page.width, page.height, `page-${i + 1}`, {
|
|
15249
15338
|
stripPageBackground: shouldStripBg
|
|
15250
15339
|
});
|
|
15251
15340
|
if (processedSvg) {
|
|
@@ -15304,9 +15393,16 @@ function collectImageUrls(config) {
|
|
|
15304
15393
|
function normalizeAssetUrl(rawUrl, imageProxyUrl) {
|
|
15305
15394
|
if (!rawUrl) return null;
|
|
15306
15395
|
if (rawUrl.startsWith("data:") || rawUrl.startsWith("blob:")) return null;
|
|
15396
|
+
if (rawUrl.startsWith("/") && !rawUrl.startsWith("//")) {
|
|
15397
|
+
if (typeof window !== "undefined") return new URL(rawUrl, window.location.origin).toString();
|
|
15398
|
+
return null;
|
|
15399
|
+
}
|
|
15307
15400
|
try {
|
|
15308
15401
|
const h = new URL(rawUrl).hostname.toLowerCase();
|
|
15309
15402
|
if (h === "localhost" || h === "127.0.0.1" || h === "0.0.0.0" || h.endsWith(".local") || /^(10\.|192\.168\.|169\.254\.)/.test(h)) {
|
|
15403
|
+
if (typeof window !== "undefined" && new URL(rawUrl).origin === window.location.origin) {
|
|
15404
|
+
return rawUrl;
|
|
15405
|
+
}
|
|
15310
15406
|
return null;
|
|
15311
15407
|
}
|
|
15312
15408
|
} catch {
|
|
@@ -15374,13 +15470,17 @@ export {
|
|
|
15374
15470
|
ensureFontsForResolvedConfig,
|
|
15375
15471
|
extractFontFamiliesFromSvgs,
|
|
15376
15472
|
getEmbeddedJsPDFFontName,
|
|
15473
|
+
getProxiedImageUrl,
|
|
15474
|
+
isBundledAssetUrl,
|
|
15377
15475
|
isFontAvailable,
|
|
15476
|
+
isPrivateUrl,
|
|
15378
15477
|
loadGoogleFontCSS,
|
|
15379
15478
|
normalizeFontFamily,
|
|
15380
15479
|
resolveFontWeight,
|
|
15381
15480
|
resolveFromForm,
|
|
15382
15481
|
resolveTemplateData,
|
|
15383
15482
|
rewriteSvgFontsForJsPDF,
|
|
15483
|
+
setBundledAssetPrefixes,
|
|
15384
15484
|
warmResolvedTemplateForPreview,
|
|
15385
15485
|
warmTemplateFromForm
|
|
15386
15486
|
};
|