@pixldocs/canvas-renderer 0.5.133 → 0.5.134

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.
@@ -16232,7 +16232,7 @@ class PixldocsRenderer {
16232
16232
  await this.waitForCanvasScene(container, cloned, i);
16233
16233
  }
16234
16234
  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"));
16235
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-8Q3O7Z_Q.cjs"));
16236
16236
  const prepared = preparePagesForExport(
16237
16237
  cloned.pages,
16238
16238
  canvasWidth,
@@ -18070,7 +18070,7 @@ async function rasterizeShadowMarkers(svg) {
18070
18070
  if ((_a = document.fonts) == null ? void 0 : _a.ready) await document.fonts.ready;
18071
18071
  } catch {
18072
18072
  }
18073
- const fontFaceCss = collectDocumentFontFaceCss();
18073
+ const fontFaceCss = await collectInlinedFontFaceCss();
18074
18074
  for (const marker of markers) {
18075
18075
  try {
18076
18076
  const blur = parseFloat(marker.getAttribute("data-blur") || "0");
@@ -18084,7 +18084,9 @@ async function rasterizeShadowMarkers(svg) {
18084
18084
  (_b = marker.parentNode) == null ? void 0 : _b.removeChild(marker);
18085
18085
  continue;
18086
18086
  }
18087
- const innerXml = Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18087
+ const innerXml = restoreSourceFontsForShadowRaster(
18088
+ Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("")
18089
+ );
18088
18090
  try {
18089
18091
  const fontSpecs = collectFontSpecsFromMarkup(innerXml);
18090
18092
  if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
@@ -18195,6 +18197,103 @@ function collectDocumentFontFaceCss() {
18195
18197
  cachedFontFaceCss = out.join("\n");
18196
18198
  return cachedFontFaceCss;
18197
18199
  }
18200
+ let cachedInlinedFontFaceCss = null;
18201
+ const fontUrlDataCache = /* @__PURE__ */ new Map();
18202
+ async function fetchFontAsDataUri(url) {
18203
+ if (fontUrlDataCache.has(url)) return fontUrlDataCache.get(url) ?? null;
18204
+ try {
18205
+ const resp = await fetch(url, { mode: "cors", credentials: "omit" });
18206
+ if (!resp.ok) {
18207
+ fontUrlDataCache.set(url, null);
18208
+ return null;
18209
+ }
18210
+ const blob = await resp.blob();
18211
+ const dataUri = await new Promise((resolve, reject) => {
18212
+ const fr = new FileReader();
18213
+ fr.onload = () => resolve(String(fr.result));
18214
+ fr.onerror = () => reject(fr.error);
18215
+ fr.readAsDataURL(blob);
18216
+ });
18217
+ fontUrlDataCache.set(url, dataUri);
18218
+ return dataUri;
18219
+ } catch {
18220
+ fontUrlDataCache.set(url, null);
18221
+ return null;
18222
+ }
18223
+ }
18224
+ async function inlineUrlsInCss(css) {
18225
+ const urlRe = /url\((['"]?)([^'")]+)\1\)/gi;
18226
+ const matches = [];
18227
+ let m;
18228
+ while ((m = urlRe.exec(css)) !== null) {
18229
+ const raw = m[2].trim();
18230
+ if (raw.startsWith("data:")) continue;
18231
+ let abs = raw;
18232
+ try {
18233
+ abs = new URL(raw, document.baseURI).toString();
18234
+ } catch {
18235
+ }
18236
+ matches.push({ full: m[0], url: abs });
18237
+ }
18238
+ if (matches.length === 0) return css;
18239
+ const unique = Array.from(new Set(matches.map((mm) => mm.url)));
18240
+ const results = await Promise.all(unique.map((u) => fetchFontAsDataUri(u)));
18241
+ const map = /* @__PURE__ */ new Map();
18242
+ unique.forEach((u, i) => map.set(u, results[i]));
18243
+ let out = css;
18244
+ for (const { full, url } of matches) {
18245
+ const data = map.get(url);
18246
+ if (!data) continue;
18247
+ const safeFull = full.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18248
+ out = out.replace(new RegExp(safeFull, "g"), `url("${data}")`);
18249
+ }
18250
+ return out;
18251
+ }
18252
+ async function collectInlinedFontFaceCss() {
18253
+ if (cachedInlinedFontFaceCss !== null) return cachedInlinedFontFaceCss;
18254
+ const raw = collectDocumentFontFaceCss();
18255
+ if (!raw) {
18256
+ cachedInlinedFontFaceCss = "";
18257
+ return "";
18258
+ }
18259
+ try {
18260
+ cachedInlinedFontFaceCss = await inlineUrlsInCss(raw);
18261
+ } catch {
18262
+ cachedInlinedFontFaceCss = raw;
18263
+ }
18264
+ return cachedInlinedFontFaceCss;
18265
+ }
18266
+ function restoreSourceFontsForShadowRaster(markup) {
18267
+ try {
18268
+ const parser = new DOMParser();
18269
+ const doc = parser.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${markup}</svg>`, "image/svg+xml");
18270
+ if (doc.querySelector("parsererror")) return markup;
18271
+ for (const node of Array.from(doc.querySelectorAll("text, tspan, textPath"))) {
18272
+ const family = node.getAttribute("data-source-font-family");
18273
+ const weight = node.getAttribute("data-source-font-weight");
18274
+ const style = node.getAttribute("data-source-font-style");
18275
+ if (!family && !weight && !style) continue;
18276
+ 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));
18277
+ if (family) {
18278
+ node.setAttribute("font-family", family);
18279
+ stylePairs.push(`font-family: ${family}`);
18280
+ }
18281
+ if (weight) {
18282
+ node.setAttribute("font-weight", weight);
18283
+ stylePairs.push(`font-weight: ${weight}`);
18284
+ }
18285
+ if (style) {
18286
+ node.setAttribute("font-style", style);
18287
+ stylePairs.push(`font-style: ${style}`);
18288
+ }
18289
+ if (stylePairs.length > 0) node.setAttribute("style", stylePairs.join("; "));
18290
+ }
18291
+ const root = doc.documentElement;
18292
+ return Array.from(root.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18293
+ } catch {
18294
+ return markup;
18295
+ }
18296
+ }
18198
18297
  async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
18199
18298
  try {
18200
18299
  const parser = new DOMParser();
@@ -18225,7 +18324,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18225
18324
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18226
18325
  sanitizeSvgTreeForPdf(svgToDraw);
18227
18326
  try {
18228
- const { bakeTextAnchorPositionsFromLiveSvg } = await Promise.resolve().then(() => require("./vectorPdfExport-DCNpWd6K.cjs"));
18327
+ const { bakeTextAnchorPositionsFromLiveSvg } = await Promise.resolve().then(() => require("./vectorPdfExport-8Q3O7Z_Q.cjs"));
18229
18328
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
18230
18329
  } catch (e) {
18231
18330
  console.warn("[canvas-renderer][pdf-export] anchor-bake pass failed (continuing):", e);
@@ -18567,4 +18666,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
18567
18666
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
18568
18667
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
18569
18668
  exports.warmTemplateFromForm = warmTemplateFromForm;
18570
- //# sourceMappingURL=index-D5rY5lp8.cjs.map
18669
+ //# sourceMappingURL=index-DmqoeVsF.cjs.map