@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.
@@ -16214,7 +16214,7 @@ class PixldocsRenderer {
16214
16214
  await this.waitForCanvasScene(container, cloned, i);
16215
16215
  }
16216
16216
  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");
16217
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-BA6bhLs-.js");
16218
16218
  const prepared = preparePagesForExport(
16219
16219
  cloned.pages,
16220
16220
  canvasWidth,
@@ -18052,7 +18052,7 @@ async function rasterizeShadowMarkers(svg) {
18052
18052
  if ((_a = document.fonts) == null ? void 0 : _a.ready) await document.fonts.ready;
18053
18053
  } catch {
18054
18054
  }
18055
- const fontFaceCss = collectDocumentFontFaceCss();
18055
+ const fontFaceCss = await collectInlinedFontFaceCss();
18056
18056
  for (const marker of markers) {
18057
18057
  try {
18058
18058
  const blur = parseFloat(marker.getAttribute("data-blur") || "0");
@@ -18066,7 +18066,9 @@ async function rasterizeShadowMarkers(svg) {
18066
18066
  (_b = marker.parentNode) == null ? void 0 : _b.removeChild(marker);
18067
18067
  continue;
18068
18068
  }
18069
- const innerXml = Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18069
+ const innerXml = restoreSourceFontsForShadowRaster(
18070
+ Array.from(marker.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("")
18071
+ );
18070
18072
  try {
18071
18073
  const fontSpecs = collectFontSpecsFromMarkup(innerXml);
18072
18074
  if (fontSpecs.length > 0 && ((_c = document.fonts) == null ? void 0 : _c.load)) {
@@ -18177,6 +18179,103 @@ function collectDocumentFontFaceCss() {
18177
18179
  cachedFontFaceCss = out.join("\n");
18178
18180
  return cachedFontFaceCss;
18179
18181
  }
18182
+ let cachedInlinedFontFaceCss = null;
18183
+ const fontUrlDataCache = /* @__PURE__ */ new Map();
18184
+ async function fetchFontAsDataUri(url) {
18185
+ if (fontUrlDataCache.has(url)) return fontUrlDataCache.get(url) ?? null;
18186
+ try {
18187
+ const resp = await fetch(url, { mode: "cors", credentials: "omit" });
18188
+ if (!resp.ok) {
18189
+ fontUrlDataCache.set(url, null);
18190
+ return null;
18191
+ }
18192
+ const blob = await resp.blob();
18193
+ const dataUri = await new Promise((resolve, reject) => {
18194
+ const fr = new FileReader();
18195
+ fr.onload = () => resolve(String(fr.result));
18196
+ fr.onerror = () => reject(fr.error);
18197
+ fr.readAsDataURL(blob);
18198
+ });
18199
+ fontUrlDataCache.set(url, dataUri);
18200
+ return dataUri;
18201
+ } catch {
18202
+ fontUrlDataCache.set(url, null);
18203
+ return null;
18204
+ }
18205
+ }
18206
+ async function inlineUrlsInCss(css) {
18207
+ const urlRe = /url\((['"]?)([^'")]+)\1\)/gi;
18208
+ const matches = [];
18209
+ let m;
18210
+ while ((m = urlRe.exec(css)) !== null) {
18211
+ const raw = m[2].trim();
18212
+ if (raw.startsWith("data:")) continue;
18213
+ let abs = raw;
18214
+ try {
18215
+ abs = new URL(raw, document.baseURI).toString();
18216
+ } catch {
18217
+ }
18218
+ matches.push({ full: m[0], url: abs });
18219
+ }
18220
+ if (matches.length === 0) return css;
18221
+ const unique = Array.from(new Set(matches.map((mm) => mm.url)));
18222
+ const results = await Promise.all(unique.map((u) => fetchFontAsDataUri(u)));
18223
+ const map = /* @__PURE__ */ new Map();
18224
+ unique.forEach((u, i) => map.set(u, results[i]));
18225
+ let out = css;
18226
+ for (const { full, url } of matches) {
18227
+ const data = map.get(url);
18228
+ if (!data) continue;
18229
+ const safeFull = full.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18230
+ out = out.replace(new RegExp(safeFull, "g"), `url("${data}")`);
18231
+ }
18232
+ return out;
18233
+ }
18234
+ async function collectInlinedFontFaceCss() {
18235
+ if (cachedInlinedFontFaceCss !== null) return cachedInlinedFontFaceCss;
18236
+ const raw = collectDocumentFontFaceCss();
18237
+ if (!raw) {
18238
+ cachedInlinedFontFaceCss = "";
18239
+ return "";
18240
+ }
18241
+ try {
18242
+ cachedInlinedFontFaceCss = await inlineUrlsInCss(raw);
18243
+ } catch {
18244
+ cachedInlinedFontFaceCss = raw;
18245
+ }
18246
+ return cachedInlinedFontFaceCss;
18247
+ }
18248
+ function restoreSourceFontsForShadowRaster(markup) {
18249
+ try {
18250
+ const parser = new DOMParser();
18251
+ const doc = parser.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${markup}</svg>`, "image/svg+xml");
18252
+ if (doc.querySelector("parsererror")) return markup;
18253
+ for (const node of Array.from(doc.querySelectorAll("text, tspan, textPath"))) {
18254
+ const family = node.getAttribute("data-source-font-family");
18255
+ const weight = node.getAttribute("data-source-font-weight");
18256
+ const style = node.getAttribute("data-source-font-style");
18257
+ if (!family && !weight && !style) continue;
18258
+ 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));
18259
+ if (family) {
18260
+ node.setAttribute("font-family", family);
18261
+ stylePairs.push(`font-family: ${family}`);
18262
+ }
18263
+ if (weight) {
18264
+ node.setAttribute("font-weight", weight);
18265
+ stylePairs.push(`font-weight: ${weight}`);
18266
+ }
18267
+ if (style) {
18268
+ node.setAttribute("font-style", style);
18269
+ stylePairs.push(`font-style: ${style}`);
18270
+ }
18271
+ if (stylePairs.length > 0) node.setAttribute("style", stylePairs.join("; "));
18272
+ }
18273
+ const root = doc.documentElement;
18274
+ return Array.from(root.childNodes).map((n) => n instanceof Element ? new XMLSerializer().serializeToString(n) : "").join("");
18275
+ } catch {
18276
+ return markup;
18277
+ }
18278
+ }
18180
18279
  async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
18181
18280
  try {
18182
18281
  const parser = new DOMParser();
@@ -18207,7 +18306,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18207
18306
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18208
18307
  sanitizeSvgTreeForPdf(svgToDraw);
18209
18308
  try {
18210
- const { bakeTextAnchorPositionsFromLiveSvg } = await import("./vectorPdfExport-BQO8W14A.js");
18309
+ const { bakeTextAnchorPositionsFromLiveSvg } = await import("./vectorPdfExport-BA6bhLs-.js");
18211
18310
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
18212
18311
  } catch (e) {
18213
18312
  console.warn("[canvas-renderer][pdf-export] anchor-bake pass failed (continuing):", e);
@@ -18552,4 +18651,4 @@ export {
18552
18651
  collectFontDescriptorsFromConfig as y,
18553
18652
  collectFontsFromConfig as z
18554
18653
  };
18555
- //# sourceMappingURL=index-DMkFzgNL.js.map
18654
+ //# sourceMappingURL=index-Sc4qRn5o.js.map