@pixldocs/canvas-renderer 0.5.199 → 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.
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("./index-CEUoSPy-.cjs");
3
+ const index = require("./index-RcI43b-V.cjs");
4
4
  exports.DEPLOYMENT_VERSION_MARKER = index.DEPLOYMENT_VERSION_MARKER;
5
5
  exports.FONT_FALLBACK_DEVANAGARI = index.FONT_FALLBACK_DEVANAGARI;
6
6
  exports.FONT_FALLBACK_MATH = index.FONT_FALLBACK_MATH;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, F, o, q, s, P, t, u, v, w, x, y, z, B, C, E, G, H, I, J, K, L, M, b, N, O, Q, R, S, U, V, W, X, Y, Z, _, $, a0, a1, a2, a3, a4, a5 } from "./index-CyCjpD2N.js";
1
+ import { D, F, o, q, s, P, t, u, v, w, x, y, z, B, C, E, G, H, I, J, K, L, M, b, N, O, Q, R, S, U, V, W, X, Y, Z, _, $, a0, a1, a2, a3, a4, a5 } from "./index-CABGgEg5.js";
2
2
  export {
3
3
  D as DEPLOYMENT_VERSION_MARKER,
4
4
  F as FONT_FALLBACK_DEVANAGARI,
@@ -1,7 +1,7 @@
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-CyCjpD2N.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-CABGgEg5.js";
5
5
  import { resetPdfFontRegistry, FONT_FALLBACK_SYMBOLS, FONT_FALLBACK_MATH, FONT_FALLBACK_DEVANAGARI, embedFontWithGoogleFallback, getEmbeddedVariantsList, isFontAvailable, isFamilyEmbedded, resolveBestRegisteredVariant, getEmbeddedJsPDFFontName, resolveFontWeight, doesVariantSupportChar } from "./pdfFonts-DhEaMTZl.js";
6
6
  async function embedFontsForSvg(pdf, svgStr) {
7
7
  var _a;
@@ -467,6 +467,129 @@ async function svg2pdfWithDomMount(svg, pdf, opts, options) {
467
467
  function getSvgImageHref(image) {
468
468
  return image.getAttribute("href") || image.getAttribute("xlink:href") || "";
469
469
  }
470
+ function isSafariLikeForInlineJpegSvgPdf() {
471
+ try {
472
+ if (typeof navigator === "undefined") return false;
473
+ const ua = navigator.userAgent || "";
474
+ const vendor = navigator.vendor || "";
475
+ const isIOS = /iPad|iPhone|iPod/.test(ua) || /Macintosh/.test(ua) && Number(navigator.maxTouchPoints || 0) > 1;
476
+ const isSafariDesktop = /Safari/.test(ua) && /Apple/.test(vendor) && !/Chrome|CriOS|Chromium|Edg|FxiOS/.test(ua);
477
+ return isIOS || isSafariDesktop;
478
+ } catch {
479
+ return false;
480
+ }
481
+ }
482
+ function estimateDataUrlBytesForPdf(dataUrl) {
483
+ const comma = dataUrl.indexOf(",");
484
+ const payload = comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl;
485
+ return Math.floor(payload.length * 0.75);
486
+ }
487
+ function parseSvgNumber(value) {
488
+ if (!value) return null;
489
+ const match = value.trim().match(/^-?\d+(?:\.\d+)?/);
490
+ if (!match) return null;
491
+ const n = Number(match[0]);
492
+ return Number.isFinite(n) && n > 0 ? n : null;
493
+ }
494
+ function getApproxSvgTransformScale(image) {
495
+ let sx = 1;
496
+ let sy = 1;
497
+ let cur = image;
498
+ while (cur && cur.tagName.toLowerCase() !== "svg") {
499
+ const transform = cur.getAttribute("transform") || "";
500
+ const matrix = transform.match(/matrix\(([^)]+)\)/i);
501
+ if (matrix) {
502
+ const parts = matrix[1].split(/[\s,]+/).map(Number).filter(Number.isFinite);
503
+ if (parts.length >= 4) {
504
+ sx *= Math.hypot(parts[0], parts[1]) || 1;
505
+ sy *= Math.hypot(parts[2], parts[3]) || 1;
506
+ }
507
+ }
508
+ const scale = transform.match(/scale\(([^)]+)\)/i);
509
+ if (scale) {
510
+ const parts = scale[1].split(/[\s,]+/).map(Number).filter(Number.isFinite);
511
+ if (parts.length >= 1) {
512
+ sx *= parts[0] || 1;
513
+ sy *= (parts.length >= 2 ? parts[1] : parts[0]) || 1;
514
+ }
515
+ }
516
+ cur = cur.parentElement;
517
+ }
518
+ return { x: Math.max(0.01, Math.abs(sx)), y: Math.max(0.01, Math.abs(sy)) };
519
+ }
520
+ async function rewriteSafariInlineJpegImagesToPng(svg) {
521
+ if (!isSafariLikeForInlineJpegSvgPdf() || typeof document === "undefined") return;
522
+ const jpegImages = Array.from(svg.querySelectorAll("image")).filter((image) => /^data:image\/jpe?g[;,]/i.test(getSvgImageHref(image)));
523
+ if (jpegImages.length === 0) return;
524
+ let rewritten = 0;
525
+ for (const image of jpegImages) {
526
+ const href = getSvgImageHref(image);
527
+ const decodeImage = (src) => new Promise((resolve) => {
528
+ const img = new Image();
529
+ img.onload = async () => {
530
+ try {
531
+ if (typeof img.decode === "function") await img.decode();
532
+ } catch {
533
+ }
534
+ resolve(img.naturalWidth > 0 && img.naturalHeight > 0 ? img : null);
535
+ };
536
+ img.onerror = () => resolve(null);
537
+ try {
538
+ img.src = src;
539
+ } catch {
540
+ resolve(null);
541
+ }
542
+ });
543
+ let loaded = await decodeImage(href);
544
+ let blobUrl = null;
545
+ if (!loaded) {
546
+ try {
547
+ const blob = await (await fetch(href)).blob();
548
+ blobUrl = URL.createObjectURL(blob);
549
+ loaded = await decodeImage(blobUrl);
550
+ } catch {
551
+ }
552
+ }
553
+ if (!loaded) {
554
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
555
+ continue;
556
+ }
557
+ const attrW = parseSvgNumber(image.getAttribute("width")) || loaded.naturalWidth || loaded.width;
558
+ const attrH = parseSvgNumber(image.getAttribute("height")) || loaded.naturalHeight || loaded.height;
559
+ const transformScale = getApproxSvgTransformScale(image);
560
+ const renderedW = attrW * transformScale.x;
561
+ const renderedH = attrH * transformScale.y;
562
+ const density = 2;
563
+ const maxEdge = 1800;
564
+ let targetW = Math.max(1, Math.round(Math.min(attrW, renderedW * density || attrW)));
565
+ let targetH = Math.max(1, Math.round(Math.min(attrH, renderedH * density || attrH)));
566
+ const longest = Math.max(targetW, targetH);
567
+ if (longest > maxEdge) {
568
+ const scale = maxEdge / longest;
569
+ targetW = Math.max(1, Math.round(targetW * scale));
570
+ targetH = Math.max(1, Math.round(targetH * scale));
571
+ }
572
+ let pngDataUrl = null;
573
+ for (const shrink of [1, 0.82, 0.68, 0.55]) {
574
+ const canvas = document.createElement("canvas");
575
+ canvas.width = Math.max(1, Math.round(targetW * shrink));
576
+ canvas.height = Math.max(1, Math.round(targetH * shrink));
577
+ const ctx = canvas.getContext("2d");
578
+ if (!ctx) break;
579
+ ctx.fillStyle = "#ffffff";
580
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
581
+ ctx.drawImage(loaded, 0, 0, canvas.width, canvas.height);
582
+ pngDataUrl = canvas.toDataURL("image/png");
583
+ if (estimateDataUrlBytesForPdf(pngDataUrl) <= 4e6 || shrink === 0.55) break;
584
+ }
585
+ if (blobUrl) URL.revokeObjectURL(blobUrl);
586
+ if (!pngDataUrl) continue;
587
+ image.setAttribute("href", pngDataUrl);
588
+ if (image.hasAttribute("xlink:href")) image.setAttribute("xlink:href", pngDataUrl);
589
+ rewritten++;
590
+ }
591
+ if (rewritten > 0) console.log(`[client-pdf-export] Safari-safe inline JPEG rewrite: ${rewritten} image(s) converted to PNG inside live SVG`);
592
+ }
470
593
  async function preloadSvgImagesForPdf(svg, options) {
471
594
  const images = Array.from(svg.querySelectorAll("image"));
472
595
  if (!images.length) return;
@@ -1931,6 +2054,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
1931
2054
  stripRootPageBackgroundFromSvg(svgToDraw);
1932
2055
  }
1933
2056
  sanitizeSvgTreeForPdf(svgToDraw);
2057
+ await rewriteSafariInlineJpegImagesToPng(svgToDraw);
1934
2058
  try {
1935
2059
  await logTextMeasurementDiagnostic(svgToDraw);
1936
2060
  await bakeTextAnchorPositionsFromLiveSvg(svgToDraw);
@@ -2554,7 +2678,7 @@ async function fetchSvgAsElement(imageUrl, colorMap) {
2554
2678
  async function getRecoloredSvgDataUrl(imageUrl, colorMap) {
2555
2679
  if (!colorMap || Object.keys(colorMap).length === 0) return null;
2556
2680
  try {
2557
- const { getNormalizedSvgUrl } = await import("./index-CyCjpD2N.js").then((n) => n.a6);
2681
+ const { getNormalizedSvgUrl } = await import("./index-CABGgEg5.js").then((n) => n.a6);
2558
2682
  return await getNormalizedSvgUrl(imageUrl, colorMap);
2559
2683
  } catch {
2560
2684
  return null;
@@ -3345,7 +3469,7 @@ async function fetchImageAsBase64(imageUrl, opts = {}) {
3345
3469
  }
3346
3470
  let fetchUrl = imageUrl;
3347
3471
  if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
3348
- const { isPrivateUrl } = await import("./index-CyCjpD2N.js").then((n) => n.a6);
3472
+ const { isPrivateUrl } = await import("./index-CABGgEg5.js").then((n) => n.a6);
3349
3473
  if (isPrivateUrl(imageUrl)) return null;
3350
3474
  const proxyUrl = new URL(`${API_URL}/image-proxy`);
3351
3475
  proxyUrl.searchParams.set("url", imageUrl);
@@ -5354,4 +5478,4 @@ export {
5354
5478
  preparePagesForExport,
5355
5479
  rewriteSvgFontsForJsPDFWithSourceMeta
5356
5480
  };
5357
- //# sourceMappingURL=vectorPdfExport-D57BlzeZ.js.map
5481
+ //# sourceMappingURL=vectorPdfExport-CVpaZO9N.js.map