@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.
@@ -14615,6 +14615,26 @@ function normalizeFontFamily(fontStack) {
14615
14615
  const loadedFonts = /* @__PURE__ */ new Set();
14616
14616
  const loadingPromises = /* @__PURE__ */ new Map();
14617
14617
  const registeredLocalFontFaces = /* @__PURE__ */ new Set();
14618
+ let localFontFaceStyleEl = null;
14619
+ function ensureLocalFontFaceStyle() {
14620
+ if (typeof document === "undefined") return null;
14621
+ if (localFontFaceStyleEl && localFontFaceStyleEl.isConnected) return localFontFaceStyleEl;
14622
+ try {
14623
+ localFontFaceStyleEl = document.createElement("style");
14624
+ localFontFaceStyleEl.setAttribute("data-pixldocs-local-fontfaces", "1");
14625
+ document.head.appendChild(localFontFaceStyleEl);
14626
+ return localFontFaceStyleEl;
14627
+ } catch {
14628
+ return null;
14629
+ }
14630
+ }
14631
+ function appendLocalFontFaceRule(family, weight, style, file) {
14632
+ const styleEl = ensureLocalFontFaceStyle();
14633
+ if (!styleEl) return;
14634
+ const cssText = `@font-face{font-family:"${family}";src:url("/fonts/${file}");font-weight:${weight};font-style:${style};font-display:swap;}
14635
+ `;
14636
+ styleEl.appendChild(document.createTextNode(cssText));
14637
+ }
14618
14638
  const LOCAL_FONT_FACE_VARIANTS = [
14619
14639
  { key: "regular", weight: 400, style: "normal" },
14620
14640
  { key: "bold", weight: 700, style: "normal" },
@@ -14644,6 +14664,7 @@ async function registerLocalFontFaces(fontFamily) {
14644
14664
  style: variant.style
14645
14665
  });
14646
14666
  document.fonts.add(face);
14667
+ appendLocalFontFaceRule(fontFamily, variant.weight, variant.style, file);
14647
14668
  loads.push(face.load().catch(() => void 0));
14648
14669
  } catch {
14649
14670
  }
@@ -15795,7 +15816,7 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
15795
15816
  }
15796
15817
  return svgString;
15797
15818
  }
15798
- const PACKAGE_VERSION = "0.5.131";
15819
+ const PACKAGE_VERSION = "0.5.135";
15799
15820
  const roundParityValue = (value) => {
15800
15821
  if (typeof value !== "number") return value;
15801
15822
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16214,7 +16235,7 @@ class PixldocsRenderer {
16214
16235
  await this.waitForCanvasScene(container, cloned, i);
16215
16236
  }
16216
16237
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16217
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BQO8W14A.js");
16238
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CyHRXea-.js");
16218
16239
  const prepared = preparePagesForExport(
16219
16240
  cloned.pages,
16220
16241
  canvasWidth,
@@ -18052,7 +18073,7 @@ async function rasterizeShadowMarkers(svg) {
18052
18073
  if ((_a = document.fonts) == null ? void 0 : _a.ready) await document.fonts.ready;
18053
18074
  } catch {
18054
18075
  }
18055
- const fontFaceCss = collectDocumentFontFaceCss();
18076
+ const fontFaceCss = await collectInlinedFontFaceCss();
18056
18077
  for (const marker of markers) {
18057
18078
  try {
18058
18079
  const blur = parseFloat(marker.getAttribute("data-blur") || "0");
@@ -18066,7 +18087,9 @@ async function rasterizeShadowMarkers(svg) {
18066
18087
  (_b = marker.parentNode) == null ? void 0 : _b.removeChild(marker);
18067
18088
  continue;
18068
18089
  }
18069
- const innerXml = Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18090
+ const innerXml = restoreSourceFontsForShadowRaster(
18091
+ Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("")
18092
+ );
18070
18093
  try {
18071
18094
  const fontSpecs = collectFontSpecsFromMarkup(innerXml);
18072
18095
  if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
@@ -18115,7 +18138,6 @@ function rasterSvgToPngDataUrl(svgMarkup, pxW, pxH) {
18115
18138
  const blob = new Blob([svgMarkup], { type: "image/svg+xml;charset=utf-8" });
18116
18139
  const url = URL.createObjectURL(blob);
18117
18140
  const img = new Image();
18118
- img.crossOrigin = "anonymous";
18119
18141
  const cleanup = () => {
18120
18142
  try {
18121
18143
  URL.revokeObjectURL(url);
@@ -18133,6 +18155,7 @@ function rasterSvgToPngDataUrl(svgMarkup, pxW, pxH) {
18133
18155
  resolve(null);
18134
18156
  return;
18135
18157
  }
18158
+ ctx.clearRect(0, 0, pxW, pxH);
18136
18159
  ctx.drawImage(img, 0, 0, pxW, pxH);
18137
18160
  const dataUrl = canvas.toDataURL("image/png");
18138
18161
  cleanup();
@@ -18177,6 +18200,103 @@ function collectDocumentFontFaceCss() {
18177
18200
  cachedFontFaceCss = out.join("\n");
18178
18201
  return cachedFontFaceCss;
18179
18202
  }
18203
+ let cachedInlinedFontFaceCss = null;
18204
+ const fontUrlDataCache = /* @__PURE__ */ new Map();
18205
+ async function fetchFontAsDataUri(url) {
18206
+ if (fontUrlDataCache.has(url)) return fontUrlDataCache.get(url) ?? null;
18207
+ try {
18208
+ const resp = await fetch(url, { mode: "cors", credentials: "omit" });
18209
+ if (!resp.ok) {
18210
+ fontUrlDataCache.set(url, null);
18211
+ return null;
18212
+ }
18213
+ const blob = await resp.blob();
18214
+ const dataUri = await new Promise((resolve, reject) => {
18215
+ const fr = new FileReader();
18216
+ fr.onload = () => resolve(String(fr.result));
18217
+ fr.onerror = () => reject(fr.error);
18218
+ fr.readAsDataURL(blob);
18219
+ });
18220
+ fontUrlDataCache.set(url, dataUri);
18221
+ return dataUri;
18222
+ } catch {
18223
+ fontUrlDataCache.set(url, null);
18224
+ return null;
18225
+ }
18226
+ }
18227
+ async function inlineUrlsInCss(css) {
18228
+ const urlRe = /url\((['"]?)([^'")]+)\1\)/gi;
18229
+ const matches = [];
18230
+ let m;
18231
+ while ((m = urlRe.exec(css)) !== null) {
18232
+ const raw = m[2].trim();
18233
+ if (raw.startsWith("data:")) continue;
18234
+ let abs = raw;
18235
+ try {
18236
+ abs = new URL(raw, document.baseURI).toString();
18237
+ } catch {
18238
+ }
18239
+ matches.push({ full: m[0], url: abs });
18240
+ }
18241
+ if (matches.length === 0) return css;
18242
+ const unique = Array.from(new Set(matches.map((mm) => mm.url)));
18243
+ const results = await Promise.all(unique.map((u) => fetchFontAsDataUri(u)));
18244
+ const map = /* @__PURE__ */ new Map();
18245
+ unique.forEach((u, i) => map.set(u, results[i]));
18246
+ let out = css;
18247
+ for (const { full, url } of matches) {
18248
+ const data = map.get(url);
18249
+ if (!data) continue;
18250
+ const safeFull = full.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18251
+ out = out.replace(new RegExp(safeFull, "g"), `url("${data}")`);
18252
+ }
18253
+ return out;
18254
+ }
18255
+ async function collectInlinedFontFaceCss() {
18256
+ if (cachedInlinedFontFaceCss !== null) return cachedInlinedFontFaceCss;
18257
+ const raw = collectDocumentFontFaceCss();
18258
+ if (!raw) {
18259
+ cachedInlinedFontFaceCss = "";
18260
+ return "";
18261
+ }
18262
+ try {
18263
+ cachedInlinedFontFaceCss = await inlineUrlsInCss(raw);
18264
+ } catch {
18265
+ cachedInlinedFontFaceCss = raw;
18266
+ }
18267
+ return cachedInlinedFontFaceCss;
18268
+ }
18269
+ function restoreSourceFontsForShadowRaster(markup) {
18270
+ try {
18271
+ const parser = new DOMParser();
18272
+ const doc = parser.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${markup}</svg>`, "image/svg+xml");
18273
+ if (doc.querySelector("parsererror")) return markup;
18274
+ for (const node of Array.from(doc.querySelectorAll("text, tspan, textPath"))) {
18275
+ const family = node.getAttribute("data-source-font-family");
18276
+ const weight = node.getAttribute("data-source-font-weight");
18277
+ const style = node.getAttribute("data-source-font-style");
18278
+ if (!family && !weight && !style) continue;
18279
+ 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));
18280
+ if (family) {
18281
+ node.setAttribute("font-family", family);
18282
+ stylePairs.push(`font-family: ${family}`);
18283
+ }
18284
+ if (weight) {
18285
+ node.setAttribute("font-weight", weight);
18286
+ stylePairs.push(`font-weight: ${weight}`);
18287
+ }
18288
+ if (style) {
18289
+ node.setAttribute("font-style", style);
18290
+ stylePairs.push(`font-style: ${style}`);
18291
+ }
18292
+ if (stylePairs.length > 0) node.setAttribute("style", stylePairs.join("; "));
18293
+ }
18294
+ const root = doc.documentElement;
18295
+ return Array.from(root.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18296
+ } catch {
18297
+ return markup;
18298
+ }
18299
+ }
18180
18300
  async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
18181
18301
  try {
18182
18302
  const parser = new DOMParser();
@@ -18207,7 +18327,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18207
18327
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18208
18328
  sanitizeSvgTreeForPdf(svgToDraw);
18209
18329
  try {
18210
- const { bakeTextAnchorPositionsFromLiveSvg } = await import("./vectorPdfExport-BQO8W14A.js");
18330
+ const { bakeTextAnchorPositionsFromLiveSvg } = await import("./vectorPdfExport-CyHRXea-.js");
18211
18331
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
18212
18332
  } catch (e) {
18213
18333
  console.warn("[canvas-renderer][pdf-export] anchor-bake pass failed (continuing):", e);
@@ -18552,4 +18672,4 @@ export {
18552
18672
  collectFontDescriptorsFromConfig as y,
18553
18673
  collectFontsFromConfig as z
18554
18674
  };
18555
- //# sourceMappingURL=index-DMkFzgNL.js.map
18675
+ //# sourceMappingURL=index-WM3oV4wa.js.map