@pixldocs/canvas-renderer 0.5.150 → 0.5.151

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.
@@ -5693,6 +5693,7 @@ function applyTextBackground(obj, cfg) {
5693
5693
  const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}"${bgOpacityAttr} />` : "";
5694
5694
  svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
5695
5695
  svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
5696
+ svg = bakeTextSvgToFabricLineStarts(svg, this, w);
5696
5697
  let bgShadowMarker = "";
5697
5698
  let textShadowMarker = "";
5698
5699
  if (hasShadow) {
@@ -5725,17 +5726,69 @@ function applyTextBackground(obj, cfg) {
5725
5726
  const openTagMatch = svg.match(/^\s*<g\b[^>]*>/);
5726
5727
  const inserted = bgShadowMarker + bgPath + textShadowMarker;
5727
5728
  const shadowBlur = hasShadow ? Math.max(0, Number(shadow.blur ?? 0)) : 0;
5728
- const needsOutlineTag = shadowBlur > 0 ? ' data-pd-shadow-blur="1"' : "";
5729
+ const decorationTags = [
5730
+ shadowBlur > 0 ? 'data-pd-shadow-blur="1"' : "",
5731
+ hasBg ? 'data-pd-text-bg="1"' : ""
5732
+ ].filter(Boolean).join(" ");
5733
+ const decorationAttr = decorationTags ? ` ${decorationTags}` : "";
5729
5734
  if (openTagMatch) {
5730
5735
  const openTag = openTagMatch[0];
5731
- const taggedOpenTag = needsOutlineTag && !/data-pd-shadow-blur=/i.test(openTag) ? openTag.replace(/^<g\b/, `<g${needsOutlineTag}`) : openTag;
5736
+ const taggedOpenTag = decorationAttr ? openTag.replace(/^<g\b/, `<g${decorationAttr}`).replace(/\s(data-pd-shadow-blur="1")(?=[^>]*\s\1)/i, "").replace(/\s(data-pd-text-bg="1")(?=[^>]*\s\1)/i, "") : openTag;
5732
5737
  return svg.replace(openTag, taggedOpenTag + inserted);
5733
5738
  }
5734
- return `<g${needsOutlineTag}>${inserted}${svg}</g>`;
5739
+ return `<g${decorationAttr}>${inserted}${svg}</g>`;
5735
5740
  };
5736
5741
  }
5737
5742
  }
5738
5743
  function recolorSvgFills(svg, color) {
5744
+ return _recolorSvgFills(svg, color);
5745
+ }
5746
+ function bakeTextSvgToFabricLineStarts(svg, obj, w) {
5747
+ var _a;
5748
+ try {
5749
+ const lines = (obj == null ? void 0 : obj._textLines) ?? [];
5750
+ if (!Array.isArray(lines) || lines.length === 0) return svg;
5751
+ const halfW = w / 2;
5752
+ const lineXs = [];
5753
+ for (let i = 0; i < lines.length; i++) {
5754
+ let lineLeft = 0;
5755
+ try {
5756
+ lineLeft = ((_a = obj._getLineLeftOffset) == null ? void 0 : _a.call(obj, i)) ?? 0;
5757
+ } catch {
5758
+ lineLeft = 0;
5759
+ }
5760
+ lineXs.push(-halfW + (Number.isFinite(lineLeft) ? lineLeft : 0));
5761
+ }
5762
+ const textOpenRe = /<text\b([^>]*)>/i;
5763
+ const textOpenMatch = svg.match(textOpenRe);
5764
+ if (!textOpenMatch) return svg;
5765
+ let textAttrs = textOpenMatch[1];
5766
+ if (/\stext-anchor\s*=\s*"[^"]*"/i.test(textAttrs)) {
5767
+ textAttrs = textAttrs.replace(/\stext-anchor\s*=\s*"[^"]*"/i, ' text-anchor="start"');
5768
+ } else {
5769
+ textAttrs = ` text-anchor="start"${textAttrs}`;
5770
+ }
5771
+ textAttrs = textAttrs.replace(
5772
+ /(\sstyle=")([^"]*)(")/i,
5773
+ (_m, pre, val, post) => pre + val.replace(/text-align\s*:\s*[^;"']+;?/gi, "").trim() + post
5774
+ );
5775
+ const newTextOpen = `<text${textAttrs}>`;
5776
+ let lineIdx = 0;
5777
+ const newSvg = svg.replace(textOpenMatch[0], newTextOpen).replace(
5778
+ /<tspan\b([^>]*?)\sx="([^"]*)"([^>]*)>/gi,
5779
+ (_m, pre, _oldX, post) => {
5780
+ const x = lineXs[lineIdx];
5781
+ lineIdx += 1;
5782
+ if (typeof x !== "number" || !Number.isFinite(x)) return _m;
5783
+ return `<tspan${pre} x="${x.toFixed(3)}"${post}>`;
5784
+ }
5785
+ );
5786
+ return newSvg;
5787
+ } catch {
5788
+ return svg;
5789
+ }
5790
+ }
5791
+ function _recolorSvgFills(svg, color) {
5739
5792
  const safe = escapeXmlAttr(color);
5740
5793
  let out = svg.replace(
5741
5794
  /(<(?:text|tspan|path|rect)\b[^>]*?\sfill=")([^"]*)("[^>]*>)/gi,
@@ -15956,9 +16009,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
15956
16009
  }
15957
16010
  return svgString;
15958
16011
  }
15959
- const resolvedPackageVersion = "0.5.150";
16012
+ const resolvedPackageVersion = "0.5.151";
15960
16013
  const PACKAGE_VERSION = resolvedPackageVersion;
15961
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.150";
16014
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.151";
15962
16015
  const roundParityValue = (value) => {
15963
16016
  if (typeof value !== "number") return value;
15964
16017
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16393,7 +16446,7 @@ class PixldocsRenderer {
16393
16446
  await this.waitForCanvasScene(container, cloned, i);
16394
16447
  }
16395
16448
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16396
- const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-CDnEStQk.js");
16449
+ const { exportMultiPagePdf, preparePagesForExport } = await import("./vectorPdfExport-TF3IGImZ.js");
16397
16450
  const prepared = preparePagesForExport(
16398
16451
  cloned.pages,
16399
16452
  canvasWidth,
@@ -18495,7 +18548,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18495
18548
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18496
18549
  sanitizeSvgTreeForPdf(svgToDraw);
18497
18550
  try {
18498
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-CDnEStQk.js");
18551
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await import("./vectorPdfExport-TF3IGImZ.js");
18499
18552
  try {
18500
18553
  await logTextMeasurementDiagnostic(svgToDraw);
18501
18554
  } catch {
@@ -18630,7 +18683,7 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
18630
18683
  }
18631
18684
  if (shouldOutlineText) {
18632
18685
  try {
18633
- const { convertAllTextToPath } = await import("./svgTextToPath-ws6Fh3rx.js");
18686
+ const { convertAllTextToPath } = await import("./svgTextToPath-BE8TxgiO.js");
18634
18687
  pageSvg = await convertAllTextToPath(pageSvg, fontBaseUrl, { mode: outlineSubMode });
18635
18688
  try {
18636
18689
  dumpSvgTextDiagnostics(pageSvg, i, PARITY_TAG, "STAGE-1b-after-text-to-path-raw");
@@ -18845,4 +18898,4 @@ export {
18845
18898
  collectFontDescriptorsFromConfig as y,
18846
18899
  collectFontsFromConfig as z
18847
18900
  };
18848
- //# sourceMappingURL=index-khnxviCH.js.map
18901
+ //# sourceMappingURL=index-Dp8yJxTW.js.map