@pixldocs/canvas-renderer 0.5.133 → 0.5.135

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.
@@ -14633,6 +14633,26 @@ function normalizeFontFamily(fontStack) {
14633
14633
  const loadedFonts = /* @__PURE__ */ new Set();
14634
14634
  const loadingPromises = /* @__PURE__ */ new Map();
14635
14635
  const registeredLocalFontFaces = /* @__PURE__ */ new Set();
14636
+ let localFontFaceStyleEl = null;
14637
+ function ensureLocalFontFaceStyle() {
14638
+ if (typeof document === "undefined") return null;
14639
+ if (localFontFaceStyleEl && localFontFaceStyleEl.isConnected) return localFontFaceStyleEl;
14640
+ try {
14641
+ localFontFaceStyleEl = document.createElement("style");
14642
+ localFontFaceStyleEl.setAttribute("data-pixldocs-local-fontfaces", "1");
14643
+ document.head.appendChild(localFontFaceStyleEl);
14644
+ return localFontFaceStyleEl;
14645
+ } catch {
14646
+ return null;
14647
+ }
14648
+ }
14649
+ function appendLocalFontFaceRule(family, weight, style, file) {
14650
+ const styleEl = ensureLocalFontFaceStyle();
14651
+ if (!styleEl) return;
14652
+ const cssText = `@font-face{font-family:"${family}";src:url("/fonts/${file}");font-weight:${weight};font-style:${style};font-display:swap;}
14653
+ `;
14654
+ styleEl.appendChild(document.createTextNode(cssText));
14655
+ }
14636
14656
  const LOCAL_FONT_FACE_VARIANTS = [
14637
14657
  { key: "regular", weight: 400, style: "normal" },
14638
14658
  { key: "bold", weight: 700, style: "normal" },
@@ -14662,6 +14682,7 @@ async function registerLocalFontFaces(fontFamily) {
14662
14682
  style: variant.style
14663
14683
  });
14664
14684
  document.fonts.add(face);
14685
+ appendLocalFontFaceRule(fontFamily, variant.weight, variant.style, file);
14665
14686
  loads.push(face.load().catch(() => void 0));
14666
14687
  } catch {
14667
14688
  }
@@ -15813,7 +15834,7 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
15813
15834
  }
15814
15835
  return svgString;
15815
15836
  }
15816
- const PACKAGE_VERSION = "0.5.131";
15837
+ const PACKAGE_VERSION = "0.5.135";
15817
15838
  const roundParityValue = (value) => {
15818
15839
  if (typeof value !== "number") return value;
15819
15840
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16232,7 +16253,7 @@ class PixldocsRenderer {
16232
16253
  await this.waitForCanvasScene(container, cloned, i);
16233
16254
  }
16234
16255
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16235
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-DCNpWd6K.cjs"));
16256
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-DFgDiZck.cjs"));
16236
16257
  const prepared = preparePagesForExport(
16237
16258
  cloned.pages,
16238
16259
  canvasWidth,
@@ -18070,7 +18091,7 @@ async function rasterizeShadowMarkers(svg) {
18070
18091
  if ((_a = document.fonts) == null ? void 0 : _a.ready) await document.fonts.ready;
18071
18092
  } catch {
18072
18093
  }
18073
- const fontFaceCss = collectDocumentFontFaceCss();
18094
+ const fontFaceCss = await collectInlinedFontFaceCss();
18074
18095
  for (const marker of markers) {
18075
18096
  try {
18076
18097
  const blur = parseFloat(marker.getAttribute("data-blur") || "0");
@@ -18084,7 +18105,9 @@ async function rasterizeShadowMarkers(svg) {
18084
18105
  (_b = marker.parentNode) == null ? void 0 : _b.removeChild(marker);
18085
18106
  continue;
18086
18107
  }
18087
- const innerXml = Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18108
+ const innerXml = restoreSourceFontsForShadowRaster(
18109
+ Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("")
18110
+ );
18088
18111
  try {
18089
18112
  const fontSpecs = collectFontSpecsFromMarkup(innerXml);
18090
18113
  if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
@@ -18133,7 +18156,6 @@ function rasterSvgToPngDataUrl(svgMarkup, pxW, pxH) {
18133
18156
  const blob = new Blob([svgMarkup], { type: "image/svg+xml;charset=utf-8" });
18134
18157
  const url = URL.createObjectURL(blob);
18135
18158
  const img = new Image();
18136
- img.crossOrigin = "anonymous";
18137
18159
  const cleanup = () => {
18138
18160
  try {
18139
18161
  URL.revokeObjectURL(url);
@@ -18151,6 +18173,7 @@ function rasterSvgToPngDataUrl(svgMarkup, pxW, pxH) {
18151
18173
  resolve(null);
18152
18174
  return;
18153
18175
  }
18176
+ ctx.clearRect(0, 0, pxW, pxH);
18154
18177
  ctx.drawImage(img, 0, 0, pxW, pxH);
18155
18178
  const dataUrl = canvas.toDataURL("image/png");
18156
18179
  cleanup();
@@ -18195,6 +18218,103 @@ function collectDocumentFontFaceCss() {
18195
18218
  cachedFontFaceCss = out.join("\n");
18196
18219
  return cachedFontFaceCss;
18197
18220
  }
18221
+ let cachedInlinedFontFaceCss = null;
18222
+ const fontUrlDataCache = /* @__PURE__ */ new Map();
18223
+ async function fetchFontAsDataUri(url) {
18224
+ if (fontUrlDataCache.has(url)) return fontUrlDataCache.get(url) ?? null;
18225
+ try {
18226
+ const resp = await fetch(url, { mode: "cors", credentials: "omit" });
18227
+ if (!resp.ok) {
18228
+ fontUrlDataCache.set(url, null);
18229
+ return null;
18230
+ }
18231
+ const blob = await resp.blob();
18232
+ const dataUri = await new Promise((resolve, reject) => {
18233
+ const fr = new FileReader();
18234
+ fr.onload = () => resolve(String(fr.result));
18235
+ fr.onerror = () => reject(fr.error);
18236
+ fr.readAsDataURL(blob);
18237
+ });
18238
+ fontUrlDataCache.set(url, dataUri);
18239
+ return dataUri;
18240
+ } catch {
18241
+ fontUrlDataCache.set(url, null);
18242
+ return null;
18243
+ }
18244
+ }
18245
+ async function inlineUrlsInCss(css) {
18246
+ const urlRe = /url\((['"]?)([^'")]+)\1\)/gi;
18247
+ const matches = [];
18248
+ let m;
18249
+ while ((m = urlRe.exec(css)) !== null) {
18250
+ const raw = m[2].trim();
18251
+ if (raw.startsWith("data:")) continue;
18252
+ let abs = raw;
18253
+ try {
18254
+ abs = new URL(raw, document.baseURI).toString();
18255
+ } catch {
18256
+ }
18257
+ matches.push({ full: m[0], url: abs });
18258
+ }
18259
+ if (matches.length === 0) return css;
18260
+ const unique = Array.from(new Set(matches.map((mm) => mm.url)));
18261
+ const results = await Promise.all(unique.map((u) => fetchFontAsDataUri(u)));
18262
+ const map = /* @__PURE__ */ new Map();
18263
+ unique.forEach((u, i) => map.set(u, results[i]));
18264
+ let out = css;
18265
+ for (const { full, url } of matches) {
18266
+ const data = map.get(url);
18267
+ if (!data) continue;
18268
+ const safeFull = full.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18269
+ out = out.replace(new RegExp(safeFull, "g"), `url("${data}")`);
18270
+ }
18271
+ return out;
18272
+ }
18273
+ async function collectInlinedFontFaceCss() {
18274
+ if (cachedInlinedFontFaceCss !== null) return cachedInlinedFontFaceCss;
18275
+ const raw = collectDocumentFontFaceCss();
18276
+ if (!raw) {
18277
+ cachedInlinedFontFaceCss = "";
18278
+ return "";
18279
+ }
18280
+ try {
18281
+ cachedInlinedFontFaceCss = await inlineUrlsInCss(raw);
18282
+ } catch {
18283
+ cachedInlinedFontFaceCss = raw;
18284
+ }
18285
+ return cachedInlinedFontFaceCss;
18286
+ }
18287
+ function restoreSourceFontsForShadowRaster(markup) {
18288
+ try {
18289
+ const parser = new DOMParser();
18290
+ const doc = parser.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${markup}</svg>`, "image/svg+xml");
18291
+ if (doc.querySelector("parsererror")) return markup;
18292
+ for (const node of Array.from(doc.querySelectorAll("text, tspan, textPath"))) {
18293
+ const family = node.getAttribute("data-source-font-family");
18294
+ const weight = node.getAttribute("data-source-font-weight");
18295
+ const style = node.getAttribute("data-source-font-style");
18296
+ if (!family && !weight && !style) continue;
18297
+ const stylePairs = (node.getAttribute("style") || "").split(";").map((part) => part.trim()).filter(Boolean).filter((part) => !/^font-family\s*:/i.test(part) && !/^font-weight\s*:/i.test(part) && !/^font-style\s*:/i.test(part));
18298
+ if (family) {
18299
+ node.setAttribute("font-family", family);
18300
+ stylePairs.push(`font-family: ${family}`);
18301
+ }
18302
+ if (weight) {
18303
+ node.setAttribute("font-weight", weight);
18304
+ stylePairs.push(`font-weight: ${weight}`);
18305
+ }
18306
+ if (style) {
18307
+ node.setAttribute("font-style", style);
18308
+ stylePairs.push(`font-style: ${style}`);
18309
+ }
18310
+ if (stylePairs.length > 0) node.setAttribute("style", stylePairs.join("; "));
18311
+ }
18312
+ const root = doc.documentElement;
18313
+ return Array.from(root.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18314
+ } catch {
18315
+ return markup;
18316
+ }
18317
+ }
18198
18318
  async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
18199
18319
  try {
18200
18320
  const parser = new DOMParser();
@@ -18225,7 +18345,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18225
18345
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18226
18346
  sanitizeSvgTreeForPdf(svgToDraw);
18227
18347
  try {
18228
- const { bakeTextAnchorPositionsFromLiveSvg } = await Promise.resolve().then(() => require("./vectorPdfExport-DCNpWd6K.cjs"));
18348
+ const { bakeTextAnchorPositionsFromLiveSvg } = await Promise.resolve().then(() => require("./vectorPdfExport-DFgDiZck.cjs"));
18229
18349
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
18230
18350
  } catch (e) {
18231
18351
  console.warn("[canvas-renderer][pdf-export] anchor-bake pass failed (continuing):", e);
@@ -18567,4 +18687,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
18567
18687
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
18568
18688
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
18569
18689
  exports.warmTemplateFromForm = warmTemplateFromForm;
18570
- //# sourceMappingURL=index-D5rY5lp8.cjs.map
18690
+ //# sourceMappingURL=index-BCvB875s.cjs.map