@pixldocs/canvas-renderer 0.5.200 → 0.5.201

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.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jspdf = require("jspdf");
4
4
  const svg2pdf_js = require("svg2pdf.js");
5
5
  const fabric = require("fabric");
6
- const index = require("./index-B0b3u83I.cjs");
6
+ const index = require("./index-RcI43b-V.cjs");
7
7
  const pdfFonts = require("./pdfFonts-BTj2f465.cjs");
8
8
  function _interopNamespaceDefault(e) {
9
9
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -486,6 +486,129 @@ async function svg2pdfWithDomMount(svg, pdf, opts, options) {
486
486
  function getSvgImageHref(image) {
487
487
  return image.getAttribute("href") || image.getAttribute("xlink:href") || "";
488
488
  }
489
+ function isSafariLikeForInlineJpegSvgPdf() {
490
+ try {
491
+ if (typeof navigator === "undefined") return false;
492
+ const ua = navigator.userAgent || "";
493
+ const vendor = navigator.vendor || "";
494
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || /Macintosh/.test(ua) && Number(navigator.maxTouchPoints || 0) > 1;
495
+ const isSafariDesktop = /Safari/.test(ua) && /Apple/.test(vendor) && !/Chrome|CriOS|Chromium|Edg|FxiOS/.test(ua);
496
+ return isIOS || isSafariDesktop;
497
+ } catch {
498
+ return false;
499
+ }
500
+ }
501
+ function estimateDataUrlBytesForPdf(dataUrl) {
502
+ const comma = dataUrl.indexOf(",");
503
+ const payload = comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl;
504
+ return Math.floor(payload.length * 0.75);
505
+ }
506
+ function parseSvgNumber(value) {
507
+ if (!value) return null;
508
+ const match = value.trim().match(/^-?\d+(?:\.\d+)?/);
509
+ if (!match) return null;
510
+ const n = Number(match[0]);
511
+ return Number.isFinite(n) && n > 0 ? n : null;
512
+ }
513
+ function getApproxSvgTransformScale(image) {
514
+ let sx = 1;
515
+ let sy = 1;
516
+ let cur = image;
517
+ while (cur && cur.tagName.toLowerCase() !== "svg") {
518
+ const transform = cur.getAttribute("transform") || "";
519
+ const matrix = transform.match(/matrix\(([^)]+)\)/i);
520
+ if (matrix) {
521
+ const parts = matrix[1].split(/[\s,]+/).map(Number).filter(Number.isFinite);
522
+ if (parts.length >= 4) {
523
+ sx *= Math.hypot(parts[0], parts[1]) || 1;
524
+ sy *= Math.hypot(parts[2], parts[3]) || 1;
525
+ }
526
+ }
527
+ const scale = transform.match(/scale\(([^)]+)\)/i);
528
+ if (scale) {
529
+ const parts = scale[1].split(/[\s,]+/).map(Number).filter(Number.isFinite);
530
+ if (parts.length >= 1) {
531
+ sx *= parts[0] || 1;
532
+ sy *= (parts.length >= 2 ? parts[1] : parts[0]) || 1;
533
+ }
534
+ }
535
+ cur = cur.parentElement;
536
+ }
537
+ return { x: Math.max(0.01, Math.abs(sx)), y: Math.max(0.01, Math.abs(sy)) };
538
+ }
539
+ async function rewriteSafariInlineJpegImagesToPng(svg) {
540
+ if (!isSafariLikeForInlineJpegSvgPdf() || typeof document === "undefined") return;
541
+ const jpegImages = Array.from(svg.querySelectorAll("image")).filter((image) => /^data:image\/jpe?g[;,]/i.test(getSvgImageHref(image)));
542
+ if (jpegImages.length === 0) return;
543
+ let rewritten = 0;
544
+ for (const image of jpegImages) {
545
+ const href = getSvgImageHref(image);
546
+ const decodeImage = (src) => new Promise((resolve) => {
547
+ const img = new Image();
548
+ img.onload = async () => {
549
+ try {
550
+ if (typeof img.decode === "function") await img.decode();
551
+ } catch {
552
+ }
553
+ resolve(img.naturalWidth > 0 && img.naturalHeight > 0 ? img : null);
554
+ };
555
+ img.onerror = () => resolve(null);
556
+ try {
557
+ img.src = src;
558
+ } catch {
559
+ resolve(null);
560
+ }
561
+ });
562
+ let loaded = await decodeImage(href);
563
+ let blobUrl = null;
564
+ if (!loaded) {
565
+ try {
566
+ const blob = await (await fetch(href)).blob();
567
+ blobUrl = URL.createObjectURL(blob);
568
+ loaded = await decodeImage(blobUrl);
569
+ } catch {
570
+ }
571
+ }
572
+ if (!loaded) {
573
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
574
+ continue;
575
+ }
576
+ const attrW = parseSvgNumber(image.getAttribute("width")) || loaded.naturalWidth || loaded.width;
577
+ const attrH = parseSvgNumber(image.getAttribute("height")) || loaded.naturalHeight || loaded.height;
578
+ const transformScale = getApproxSvgTransformScale(image);
579
+ const renderedW = attrW * transformScale.x;
580
+ const renderedH = attrH * transformScale.y;
581
+ const density = 2;
582
+ const maxEdge = 1800;
583
+ let targetW = Math.max(1, Math.round(Math.min(attrW, renderedW * density || attrW)));
584
+ let targetH = Math.max(1, Math.round(Math.min(attrH, renderedH * density || attrH)));
585
+ const longest = Math.max(targetW, targetH);
586
+ if (longest > maxEdge) {
587
+ const scale = maxEdge / longest;
588
+ targetW = Math.max(1, Math.round(targetW * scale));
589
+ targetH = Math.max(1, Math.round(targetH * scale));
590
+ }
591
+ let pngDataUrl = null;
592
+ for (const shrink of [1, 0.82, 0.68, 0.55]) {
593
+ const canvas = document.createElement("canvas");
594
+ canvas.width = Math.max(1, Math.round(targetW * shrink));
595
+ canvas.height = Math.max(1, Math.round(targetH * shrink));
596
+ const ctx = canvas.getContext("2d");
597
+ if (!ctx) break;
598
+ ctx.fillStyle = "#ffffff";
599
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
600
+ ctx.drawImage(loaded, 0, 0, canvas.width, canvas.height);
601
+ pngDataUrl = canvas.toDataURL("image/png");
602
+ if (estimateDataUrlBytesForPdf(pngDataUrl) <= 4e6 || shrink === 0.55) break;
603
+ }
604
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
605
+ if (!pngDataUrl) continue;
606
+ image.setAttribute("href", pngDataUrl);
607
+ if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", pngDataUrl);
608
+ rewritten++;
609
+ }
610
+ if (rewritten > 0) console.log(`[client-pdf-export] Safari-safe inline JPEG rewrite: ${rewritten} image(s) converted to PNG inside live SVG`);
611
+ }
489
612
  async function preloadSvgImagesForPdf(svg, options) {
490
613
  const images = Array.from(svg.querySelectorAll("image"));
491
614
  if (!images.length) return;
@@ -1950,6 +2073,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
1950
2073
  stripRootPageBackgroundFromSvg(svgToDraw);
1951
2074
  }
1952
2075
  sanitizeSvgTreeForPdf(svgToDraw);
2076
+ await rewriteSafariInlineJpegImagesToPng(svgToDraw);
1953
2077
  try {
1954
2078
  await logTextMeasurementDiagnostic(svgToDraw);
1955
2079
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
@@ -2573,7 +2697,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
2573
2697
  async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
2574
2698
  if (!colorMap || Object.keys(colorMap).length === 0) return null;
2575
2699
  try {
2576
- const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-B0b3u83I.cjs")).then((n) => n.canvasImageLoader);
2700
+ const { getNormalizedSvgUrl } = await Promise.resolve().then(() => require("./index-RcI43b-V.cjs")).then((n) => n.canvasImageLoader);
2577
2701
  return await getNormalizedSvgUrl(imageUrl, colorMap);
2578
2702
  } catch {
2579
2703
  return null;
@@ -3364,7 +3488,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
3364
3488
  }
3365
3489
  let fetchUrl = imageUrl;
3366
3490
  if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
3367
- const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-B0b3u83I.cjs")).then((n) => n.canvasImageLoader);
3491
+ const { isPrivateUrl } = await Promise.resolve().then(() => require("./index-RcI43b-V.cjs")).then((n) => n.canvasImageLoader);
3368
3492
  if (isPrivateUrl(imageUrl)) return null;
3369
3493
  const proxyUrl = new URL(`${index.API_URL}/image-proxy`);
3370
3494
  proxyUrl.searchParams.set("url", imageUrl);
@@ -5371,4 +5495,4 @@ exports.exportMultiPagePdf = exportMultiPagePdf;
5371
5495
  exports.logTextMeasurementDiagnostic = logTextMeasurementDiagnostic;
5372
5496
  exports.preparePagesForExport = preparePagesForExport;
5373
5497
  exports.rewriteSvgFontsForJsPDFWithSourceMeta = rewriteSvgFontsForJsPDFWithSourceMeta;
5374
- //# sourceMappingURL=vectorPdfExport-CV6GxECJ.cjs.map
5498
+ //# sourceMappingURL=vectorPdfExport-DQjvPb1v.cjs.map