@pixldocs/canvas-renderer 0.5.155 → 0.5.157

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.
@@ -1,8 +1,8 @@
1
1
  import { jsPDF, ShadingPattern } from "jspdf";
2
2
  import { svg2pdf } from "svg2pdf.js";
3
3
  import * as fabric from "fabric";
4
- import { g as getCanvasForPage, c as captureFabricCanvasSvgForPdf, f as findNodeById, a as getAbsoluteBounds, p as parseTextMarkdown, r as renderSmartElementToSvg, n as normalizeShapeType, h as hasEdgeFade, b as getProxiedImageUrl, d as bakeEdgeFade, i as isElement, e as isGroup, j as buildRoundedTrianglePath, A as API_URL, k as getImageProxyFetchOptions, l as getRoundedRectRadii, T as TRIANGLE_STROKE_MITER_LIMIT, m as getTrianglePoints } from "./index-BQA8_wgq.js";
5
- import { resetPdfFontRegistry, FONT_FALLBACK_SYMBOLS, FONT_FALLBACK_MATH, FONT_FALLBACK_DEVANAGARI, embedFontWithGoogleFallback, getEmbeddedVariantsList, isFontAvailable, isFamilyEmbedded, resolveBestRegisteredVariant, getEmbeddedJsPDFFontName, resolveFontWeight, doesVariantSupportChar } from "./pdfFonts-b3_bv7F0.js";
4
+ import { g as getCanvasForPage, c as captureFabricCanvasSvgForPdf, f as findNodeById, a as getAbsoluteBounds, p as parseTextMarkdown, r as renderSmartElementToSvg, n as normalizeShapeType, h as hasEdgeFade, b as getProxiedImageUrl, d as bakeEdgeFade, i as isElement, e as isGroup, j as buildRoundedTrianglePath, A as API_URL, k as getImageProxyFetchOptions, l as getRoundedRectRadii, T as TRIANGLE_STROKE_MITER_LIMIT, m as getTrianglePoints } from "./index-xn-L7QHB.js";
5
+ import { r as resetPdfFontRegistry, F as FONT_FALLBACK_SYMBOLS, a as FONT_FALLBACK_MATH, b as FONT_FALLBACK_DEVANAGARI, e as embedFontWithGoogleFallback, g as getEmbeddedVariantsList, i as isFontAvailable, c as isFamilyEmbedded, d as resolveBestRegisteredVariant, f as getEmbeddedJsPDFFontName, h as convertAllTextToPath, j as resolveFontWeight, k as doesVariantSupportChar } from "./svgTextToPath-V1vC0SQt.js";
6
6
  async function embedFontsForSvg(pdf, svgStr) {
7
7
  var _a;
8
8
  const {
@@ -12,7 +12,7 @@ async function embedFontsForSvg(pdf, svgStr) {
12
12
  FONT_FALLBACK_SYMBOLS: FONT_FALLBACK_SYMBOLS2,
13
13
  FONT_FALLBACK_DEVANAGARI: FONT_FALLBACK_DEVANAGARI2,
14
14
  FONT_FALLBACK_MATH: FONT_FALLBACK_MATH2
15
- } = await import("./pdfFonts-b3_bv7F0.js");
15
+ } = await import("./svgTextToPath-V1vC0SQt.js").then((n) => n.p);
16
16
  const parser = new DOMParser();
17
17
  const doc = parser.parseFromString(svgStr, "image/svg+xml");
18
18
  const textEls = Array.from(doc.querySelectorAll("text, tspan, textPath"));
@@ -1308,50 +1308,44 @@ async function bakeTextAnchorPositionsFromLiveSvg(svg) {
1308
1308
  }
1309
1309
  }
1310
1310
  }
1311
- function promoteFabricLineAnchorsToSelectableText(svg) {
1311
+ function appendInvisibleSelectableTextLayer(svg) {
1312
+ var _a;
1312
1313
  const doc = svg.ownerDocument;
1313
1314
  if (!doc) return;
1314
- const lineTspans = Array.from(svg.querySelectorAll('tspan[data-pd-line-anchor="1"]'));
1315
- if (lineTspans.length === 0) return;
1315
+ const texts = Array.from(svg.querySelectorAll("text"));
1316
+ if (texts.length === 0) return;
1316
1317
  const SVG_NS = "http://www.w3.org/2000/svg";
1317
- const touchedParents = /* @__PURE__ */ new Set();
1318
- let promoted = 0;
1319
- for (const tspan of lineTspans) {
1320
- const parentText = tspan.parentElement;
1321
- if (!parentText || parentText.tagName.toLowerCase() !== "text" || !parentText.parentNode) continue;
1322
- const rawWidth = Number.parseFloat(tspan.getAttribute("data-pd-line-width") || "");
1323
- const rawX = Number.parseFloat(tspan.getAttribute("x") || parentText.getAttribute("x") || "");
1324
- if (!Number.isFinite(rawWidth) || rawWidth <= 0 || !Number.isFinite(rawX)) continue;
1325
- const anchor = (tspan.getAttribute("text-anchor") || "start").trim().toLowerCase();
1326
- if (anchor !== "middle" && anchor !== "end") continue;
1327
- const startX = anchor === "end" ? rawX - rawWidth : anchor === "middle" ? rawX - rawWidth / 2 : rawX;
1328
- const y = tspan.getAttribute("y") || parentText.getAttribute("y") || "0";
1329
- const wrapper = doc.createElementNS(SVG_NS, "text");
1330
- for (const attr of Array.from(parentText.attributes)) {
1331
- if (["x", "y", "dx", "dy", "text-anchor", "textLength", "lengthAdjust"].includes(attr.name)) continue;
1332
- wrapper.setAttribute(attr.name, attr.value);
1333
- }
1334
- for (const attr of Array.from(tspan.attributes)) {
1335
- if (["x", "y", "dx", "dy", "text-anchor", "data-pd-line-anchor", "data-pd-line-width", "textLength", "lengthAdjust"].includes(attr.name)) continue;
1336
- wrapper.setAttribute(attr.name, attr.value);
1337
- }
1338
- wrapper.setAttribute("x", startX.toFixed(3));
1339
- wrapper.setAttribute("y", y);
1340
- wrapper.setAttribute("text-anchor", "start");
1341
- wrapper.setAttribute("textLength", rawWidth.toFixed(3));
1342
- wrapper.setAttribute("lengthAdjust", "spacing");
1343
- wrapper.textContent = tspan.textContent || "";
1344
- parentText.parentNode.insertBefore(wrapper, parentText);
1345
- tspan.remove();
1346
- touchedParents.add(parentText);
1347
- promoted++;
1348
- }
1349
- for (const parentText of touchedParents) {
1350
- if (!parentText.parentNode) continue;
1351
- const hasText = Array.from(parentText.childNodes).some((node) => (node.textContent || "").trim().length > 0);
1352
- if (!hasText) parentText.parentNode.removeChild(parentText);
1353
- }
1354
- if (promoted > 0) console.log(`[Vector PDF][parity] promoted ${promoted} Fabric line anchor(s) to selectable fixed-width text`);
1318
+ const layer = doc.createElementNS(SVG_NS, "g");
1319
+ layer.setAttribute("data-pd-selectable-layer", "1");
1320
+ layer.setAttribute("fill", "none");
1321
+ layer.setAttribute("stroke", "none");
1322
+ layer.setAttribute("style", "fill: none; stroke: none;");
1323
+ let cloned = 0;
1324
+ for (const text of texts) {
1325
+ if ((_a = text.closest) == null ? void 0 : _a.call(text, '[data-pd-selectable-layer="1"]')) continue;
1326
+ if (!(text.textContent || "").trim()) continue;
1327
+ const clone = text.cloneNode(true);
1328
+ clone.setAttribute("fill", "none");
1329
+ clone.setAttribute("stroke", "none");
1330
+ clone.setAttribute("style", "fill: none; stroke: none;");
1331
+ clone.removeAttribute("opacity");
1332
+ clone.removeAttribute("fill-opacity");
1333
+ clone.removeAttribute("stroke-opacity");
1334
+ for (const child of Array.from(clone.querySelectorAll("*"))) {
1335
+ child.setAttribute("fill", "none");
1336
+ child.setAttribute("stroke", "none");
1337
+ child.setAttribute("style", "fill: none; stroke: none;");
1338
+ child.removeAttribute("opacity");
1339
+ child.removeAttribute("fill-opacity");
1340
+ child.removeAttribute("stroke-opacity");
1341
+ }
1342
+ layer.appendChild(clone);
1343
+ cloned++;
1344
+ }
1345
+ if (cloned > 0) {
1346
+ svg.appendChild(layer);
1347
+ console.log(`[Vector PDF][selectable-layer] appended ${cloned} invisible text clone(s)`);
1348
+ }
1355
1349
  }
1356
1350
  async function logTextMeasurementDiagnostic(svg) {
1357
1351
  var _a, _b, _c, _d, _e;
@@ -1881,7 +1875,7 @@ async function collectInlinedFontFaceCss() {
1881
1875
  return cachedInlinedFontFaceCss;
1882
1876
  }
1883
1877
  async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey, options) {
1884
- var _a;
1878
+ var _a, _b;
1885
1879
  try {
1886
1880
  const parser = new DOMParser();
1887
1881
  const processedSvg = inlineNestedSvgImageDataUris(rawSvg, parser);
@@ -1918,12 +1912,17 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
1918
1912
  } catch (e) {
1919
1913
  console.warn("[Vector PDF] anchor-bake pass failed (continuing):", e);
1920
1914
  }
1915
+ appendInvisibleSelectableTextLayer(svgToDraw);
1921
1916
  await rasterizeShadowMarkers(svgToDraw);
1922
- promoteFabricLineAnchorsToSelectableText(svgToDraw);
1923
1917
  await convertTextDecorationsToLines(svgToDraw);
1918
+ const outlined = await convertAllTextToPath(new XMLSerializer().serializeToString(svgToDraw), void 0, { mode: "all" });
1919
+ const outlinedDoc = parser.parseFromString(outlined, "image/svg+xml");
1920
+ if (!outlinedDoc.querySelector("parsererror") && ((_a = outlinedDoc.documentElement) == null ? void 0 : _a.tagName.toLowerCase()) === "svg") {
1921
+ svgToDraw = outlinedDoc.documentElement;
1922
+ }
1924
1923
  const rewritten = rewriteSvgFontsForJsPDFWithSourceMeta(new XMLSerializer().serializeToString(svgToDraw));
1925
1924
  const rewrittenDoc = parser.parseFromString(rewritten, "image/svg+xml");
1926
- if (!rewrittenDoc.querySelector("parsererror") && ((_a = rewrittenDoc.documentElement) == null ? void 0 : _a.tagName.toLowerCase()) === "svg") {
1925
+ if (!rewrittenDoc.querySelector("parsererror") && ((_b = rewrittenDoc.documentElement) == null ? void 0 : _b.tagName.toLowerCase()) === "svg") {
1927
1926
  return rewrittenDoc.documentElement;
1928
1927
  }
1929
1928
  return svgToDraw;
@@ -2505,7 +2504,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
2505
2504
  async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
2506
2505
  if (!colorMap || Object.keys(colorMap).length === 0) return null;
2507
2506
  try {
2508
- const { getNormalizedSvgUrl } = await import("./index-BQA8_wgq.js").then((n) => n.$);
2507
+ const { getNormalizedSvgUrl } = await import("./index-xn-L7QHB.js").then((n) => n.$);
2509
2508
  return await getNormalizedSvgUrl(imageUrl, colorMap);
2510
2509
  } catch {
2511
2510
  return null;
@@ -3286,7 +3285,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
3286
3285
  }
3287
3286
  let fetchUrl = imageUrl;
3288
3287
  if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
3289
- const { isPrivateUrl } = await import("./index-BQA8_wgq.js").then((n) => n.$);
3288
+ const { isPrivateUrl } = await import("./index-xn-L7QHB.js").then((n) => n.$);
3290
3289
  if (isPrivateUrl(imageUrl)) return null;
3291
3290
  const proxyUrl = new URL(`${API_URL}/image-proxy`);
3292
3291
  proxyUrl.searchParams.set("url", imageUrl);
@@ -5260,6 +5259,7 @@ async function exportMultiPagePdf(pages, options) {
5260
5259
  pdf.save(filename);
5261
5260
  }
5262
5261
  export {
5262
+ appendInvisibleSelectableTextLayer,
5263
5263
  bakeTextAnchorPositionsFromLiveSvg,
5264
5264
  convertSvgTextDecorationsToLinesString,
5265
5265
  drawPreparedLiveCanvasSvgPageToPdf,
@@ -5268,7 +5268,6 @@ export {
5268
5268
  exportMultiPagePdf,
5269
5269
  logTextMeasurementDiagnostic,
5270
5270
  preparePagesForExport,
5271
- promoteFabricLineAnchorsToSelectableText,
5272
5271
  rewriteSvgFontsForJsPDFWithSourceMeta
5273
5272
  };
5274
- //# sourceMappingURL=vectorPdfExport-vCax992V.js.map
5273
+ //# sourceMappingURL=vectorPdfExport-CZyyQbwm.js.map