@pixldocs/canvas-renderer 0.5.51 → 0.5.53

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 CHANGED
@@ -2858,6 +2858,49 @@ function isPrivateUrl(url) {
2858
2858
  return false;
2859
2859
  }
2860
2860
  }
2861
+ const DEFAULT_BUNDLED_PREFIXES = ["/pixldocs-bundled-assets/"];
2862
+ let bundledPrefixes = [...DEFAULT_BUNDLED_PREFIXES];
2863
+ function setBundledAssetPrefixes(prefixes) {
2864
+ const combined = /* @__PURE__ */ new Set([...DEFAULT_BUNDLED_PREFIXES]);
2865
+ for (const p of prefixes || []) {
2866
+ if (typeof p === "string" && p.startsWith("/")) combined.add(p);
2867
+ }
2868
+ bundledPrefixes = Array.from(combined);
2869
+ }
2870
+ function pathnameStartsWithBundledPrefix(pathname) {
2871
+ return bundledPrefixes.some((prefix) => pathname.startsWith(prefix));
2872
+ }
2873
+ function isBundledAssetUrl(url) {
2874
+ if (!url) return false;
2875
+ if (url.startsWith("/") && !url.startsWith("//")) {
2876
+ return pathnameStartsWithBundledPrefix(url);
2877
+ }
2878
+ try {
2879
+ const parsed = new URL(url);
2880
+ if (typeof window !== "undefined" && parsed.origin !== window.location.origin) {
2881
+ return false;
2882
+ }
2883
+ return pathnameStartsWithBundledPrefix(parsed.pathname);
2884
+ } catch {
2885
+ return false;
2886
+ }
2887
+ }
2888
+ function resolveBundledAssetUrl(url) {
2889
+ if (!url) return null;
2890
+ if (url.startsWith("/") && !url.startsWith("//") && pathnameStartsWithBundledPrefix(url)) {
2891
+ const origin = typeof window !== "undefined" ? window.location.origin : "";
2892
+ return origin ? new URL(url, origin).toString() : url;
2893
+ }
2894
+ try {
2895
+ const parsed = new URL(url);
2896
+ if (typeof window !== "undefined" && parsed.origin !== window.location.origin) return null;
2897
+ if (pathnameStartsWithBundledPrefix(parsed.pathname)) return parsed.toString();
2898
+ } catch {
2899
+ return null;
2900
+ }
2901
+ return null;
2902
+ }
2903
+ const loggedPrivateSkips = /* @__PURE__ */ new Set();
2861
2904
  function toPublicStorageUrl(url) {
2862
2905
  try {
2863
2906
  const parsed = new URL(url);
@@ -2875,8 +2918,17 @@ function toPublicStorageUrl(url) {
2875
2918
  function getProxiedImageUrl(imageUrl) {
2876
2919
  if (!imageUrl) return "";
2877
2920
  if (imageUrl.startsWith("data:") || imageUrl.startsWith("blob:")) return imageUrl;
2921
+ const bundled = resolveBundledAssetUrl(imageUrl);
2922
+ if (bundled) return bundled;
2923
+ if (imageUrl.startsWith("/") && !imageUrl.startsWith("//")) {
2924
+ if (typeof window !== "undefined") return new URL(imageUrl, window.location.origin).toString();
2925
+ return imageUrl;
2926
+ }
2878
2927
  if (isPrivateUrl(imageUrl)) {
2879
- console.warn("[image-proxy] Skipping private URL:", imageUrl.substring(0, 80));
2928
+ if (!loggedPrivateSkips.has(imageUrl)) {
2929
+ loggedPrivateSkips.add(imageUrl);
2930
+ console.debug("[image-proxy] Skipping private URL:", imageUrl.substring(0, 80));
2931
+ }
2880
2932
  return "";
2881
2933
  }
2882
2934
  const publicUrl = toPublicStorageUrl(imageUrl);
@@ -4818,7 +4870,13 @@ function extractTextBgConfig(element) {
4818
4870
  rxTL: Math.max(0, Number(element.textBgRxTL ?? 0)) || 0,
4819
4871
  rxTR: Math.max(0, Number(element.textBgRxTR ?? 0)) || 0,
4820
4872
  rxBR: Math.max(0, Number(element.textBgRxBR ?? 0)) || 0,
4821
- rxBL: Math.max(0, Number(element.textBgRxBL ?? 0)) || 0
4873
+ rxBL: Math.max(0, Number(element.textBgRxBL ?? 0)) || 0,
4874
+ opacity: (() => {
4875
+ const n = Number(element.textBgOpacity);
4876
+ if (!Number.isFinite(n)) return void 0;
4877
+ return Math.max(0, Math.min(1, n));
4878
+ })(),
4879
+ shadowAffectsBg: element.textShadowAffectsBg !== false
4822
4880
  };
4823
4881
  }
4824
4882
  function hasTextBackground(cfg) {
@@ -4879,6 +4937,13 @@ function applyTextBackground(obj, cfg) {
4879
4937
  const bgW = w + pL + pR;
4880
4938
  const bgH = h + pT + pB;
4881
4939
  ctx.save();
4940
+ const suppressShadowOnBg = bg.shadowAffectsBg === false;
4941
+ if (suppressShadowOnBg) {
4942
+ ctx.shadowColor = "transparent";
4943
+ ctx.shadowBlur = 0;
4944
+ ctx.shadowOffsetX = 0;
4945
+ ctx.shadowOffsetY = 0;
4946
+ }
4882
4947
  buildRoundedRectPath2D(
4883
4948
  ctx,
4884
4949
  x,
@@ -4890,6 +4955,8 @@ function applyTextBackground(obj, cfg) {
4890
4955
  bg.rxBR ?? 0,
4891
4956
  bg.rxBL ?? 0
4892
4957
  );
4958
+ const op = typeof bg.opacity === "number" ? Math.max(0, Math.min(1, bg.opacity)) : 1;
4959
+ if (op < 1) ctx.globalAlpha = (ctx.globalAlpha ?? 1) * op;
4893
4960
  ctx.fillStyle = bg.color;
4894
4961
  ctx.fill();
4895
4962
  ctx.restore();
@@ -4935,7 +5002,9 @@ function applyTextBackground(obj, cfg) {
4935
5002
  (bg == null ? void 0 : bg.rxBL) ?? 0
4936
5003
  );
4937
5004
  const bgFill = (bg == null ? void 0 : bg.color) || "";
4938
- const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}" />` : "";
5005
+ const bgOpacity = typeof (bg == null ? void 0 : bg.opacity) === "number" ? Math.max(0, Math.min(1, bg.opacity)) : 1;
5006
+ const bgOpacityAttr = bgOpacity < 1 ? ` fill-opacity="${bgOpacity}"` : "";
5007
+ const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}"${bgOpacityAttr} />` : "";
4939
5008
  svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
4940
5009
  svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
4941
5010
  let bgShadowMarker = "";
@@ -4952,7 +5021,7 @@ function applyTextBackground(obj, cfg) {
4952
5021
  const bh = h + pT + pB + pad * 2;
4953
5022
  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)}"`;
4954
5023
  const wrapShadow = (markup) => blur <= 0 ? `<g transform="translate(${ox.toFixed(3)} ${oy.toFixed(3)})">${markup}</g>` : `<g class="__pdShadowRaster" ${dataAttrs}>${markup}</g>`;
4955
- if (hasBg) {
5024
+ if (hasBg && (bg == null ? void 0 : bg.shadowAffectsBg) !== false) {
4956
5025
  const shadowBgPath = `<path d="${bgD}" fill="${escapeXmlAttr(shadowColor)}" />`;
4957
5026
  bgShadowMarker = wrapShadow(shadowBgPath);
4958
5027
  }
@@ -12340,7 +12409,7 @@ function PixldocsPreview(props) {
12340
12409
  !canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
12341
12410
  ] });
12342
12411
  }
12343
- const PACKAGE_VERSION = "0.5.50";
12412
+ const PACKAGE_VERSION = "0.5.52";
12344
12413
  let __underlineFixInstalled = false;
12345
12414
  function installUnderlineFix(fab) {
12346
12415
  var _a;
@@ -14004,6 +14073,7 @@ const SVG_STYLE_PROPS = /* @__PURE__ */ new Set([
14004
14073
  const GRADIENT_ATTRS_LINEAR = ["x1", "y1", "x2", "y2", "gradientUnits", "gradientTransform", "spreadMethod"];
14005
14074
  const GRADIENT_ATTRS_RADIAL = ["cx", "cy", "r", "fx", "fy", "gradientUnits", "gradientTransform", "spreadMethod"];
14006
14075
  const URL_GRADIENT_RE = /^\s*url\s*\(\s*(['"]?)([^)]+?)\1\s*\)/i;
14076
+ const SHADOW_RASTER_ALPHA_COMPENSATION = 0.84;
14007
14077
  function parseColor(color) {
14008
14078
  if (!color) return null;
14009
14079
  const raw = color.trim().toLowerCase();
@@ -15049,6 +15119,7 @@ async function rasterizeShadowMarkers(svg) {
15049
15119
  img.setAttribute("y", String(by));
15050
15120
  img.setAttribute("width", String(bw));
15051
15121
  img.setAttribute("height", String(bh));
15122
+ img.setAttribute("opacity", String(SHADOW_RASTER_ALPHA_COMPENSATION));
15052
15123
  img.setAttribute("preserveAspectRatio", "none");
15053
15124
  img.setAttributeNS(XLINK_NS, "xlink:href", dataUrl);
15054
15125
  img.setAttribute("href", dataUrl);
@@ -15262,7 +15333,14 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15262
15333
  const hasGradient = !!((_b = (_a = page.backgroundGradient) == null ? void 0 : _a.stops) == null ? void 0 : _b.length);
15263
15334
  drawPageBackground(pdf, i, page.width, page.height, page.backgroundColor, page.backgroundGradient);
15264
15335
  const shouldStripBg = stripPageBackground ?? hasGradient;
15265
- let processedSvg = await prepareLiveCanvasSvgForPdf(page.svg, page.width, page.height, `page-${i + 1}`, {
15336
+ let pageSvg = page.svg;
15337
+ try {
15338
+ const mod = await Promise.resolve().then(() => require("./svgTextToPath-BTHnqJpM.cjs"));
15339
+ pageSvg = await mod.convertAllTextToPath(pageSvg, fontBaseUrl);
15340
+ } catch (outlineErr) {
15341
+ console.warn(`[canvas-renderer pdf] page ${i + 1}: text outliner unavailable, continuing with text-as-text`, outlineErr);
15342
+ }
15343
+ let processedSvg = await prepareLiveCanvasSvgForPdf(pageSvg, page.width, page.height, `page-${i + 1}`, {
15266
15344
  stripPageBackground: shouldStripBg
15267
15345
  });
15268
15346
  if (processedSvg) {
@@ -15321,9 +15399,16 @@ function collectImageUrls(config) {
15321
15399
  function normalizeAssetUrl(rawUrl, imageProxyUrl) {
15322
15400
  if (!rawUrl) return null;
15323
15401
  if (rawUrl.startsWith("data:") || rawUrl.startsWith("blob:")) return null;
15402
+ if (rawUrl.startsWith("/") && !rawUrl.startsWith("//")) {
15403
+ if (typeof window !== "undefined") return new URL(rawUrl, window.location.origin).toString();
15404
+ return null;
15405
+ }
15324
15406
  try {
15325
15407
  const h = new URL(rawUrl).hostname.toLowerCase();
15326
15408
  if (h === "localhost" || h === "127.0.0.1" || h === "0.0.0.0" || h.endsWith(".local") || /^(10\.|192\.168\.|169\.254\.)/.test(h)) {
15409
+ if (typeof window !== "undefined" && new URL(rawUrl).origin === window.location.origin) {
15410
+ return rawUrl;
15411
+ }
15327
15412
  return null;
15328
15413
  }
15329
15414
  } catch {
@@ -15390,13 +15475,17 @@ exports.embedFontsInPdf = embedFontsInPdf;
15390
15475
  exports.ensureFontsForResolvedConfig = ensureFontsForResolvedConfig;
15391
15476
  exports.extractFontFamiliesFromSvgs = extractFontFamiliesFromSvgs;
15392
15477
  exports.getEmbeddedJsPDFFontName = getEmbeddedJsPDFFontName;
15478
+ exports.getProxiedImageUrl = getProxiedImageUrl;
15479
+ exports.isBundledAssetUrl = isBundledAssetUrl;
15393
15480
  exports.isFontAvailable = isFontAvailable;
15481
+ exports.isPrivateUrl = isPrivateUrl;
15394
15482
  exports.loadGoogleFontCSS = loadGoogleFontCSS;
15395
15483
  exports.normalizeFontFamily = normalizeFontFamily;
15396
15484
  exports.resolveFontWeight = resolveFontWeight;
15397
15485
  exports.resolveFromForm = resolveFromForm;
15398
15486
  exports.resolveTemplateData = resolveTemplateData;
15399
15487
  exports.rewriteSvgFontsForJsPDF = rewriteSvgFontsForJsPDF;
15488
+ exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
15400
15489
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
15401
15490
  exports.warmTemplateFromForm = warmTemplateFromForm;
15402
15491
  //# sourceMappingURL=index.cjs.map