@pixldocs/canvas-renderer 0.5.160 → 0.5.161

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.
@@ -5711,7 +5711,6 @@ function applyTextBackground(obj, cfg) {
5711
5711
  const bgPath = hasBg ? `<path d="${bgD}" fill="${escapeXmlAttr(bgFill)}"${bgOpacityAttr} />` : "";
5712
5712
  svg = svg.replace(/style="[^"]*filter:\s*url\([^)]+\)[^"]*"/i, "");
5713
5713
  svg = svg.replace(/<filter[\s\S]*?<\/filter>/gi, "");
5714
- svg = bakeTextSvgToFabricLineStarts(svg, this, w);
5715
5714
  let bgShadowMarker = "";
5716
5715
  let textShadowMarker = "";
5717
5716
  if (hasShadow) {
@@ -5761,104 +5760,6 @@ function applyTextBackground(obj, cfg) {
5761
5760
  function recolorSvgFills(svg, color) {
5762
5761
  return _recolorSvgFills(svg, color);
5763
5762
  }
5764
- function bakeTextSvgToFabricLineStarts(svg, obj, w) {
5765
- var _a, _b, _c, _d;
5766
- try {
5767
- const lines = (obj == null ? void 0 : obj._textLines) ?? [];
5768
- if (!Array.isArray(lines) || lines.length === 0) return svg;
5769
- const rawAlign = String((obj == null ? void 0 : obj.textAlign) || "left").toLowerCase();
5770
- const alignmentAnchor = /right|end/.test(rawAlign) ? "end" : /center/.test(rawAlign) ? "middle" : "start";
5771
- const hasStyledChars = (() => {
5772
- const styles = obj == null ? void 0 : obj.styles;
5773
- if (!styles || typeof styles !== "object") return false;
5774
- return Object.values(styles).some((line) => line && typeof line === "object" && Object.keys(line).length > 0);
5775
- })();
5776
- const canUseAlignmentAnchor = alignmentAnchor !== "start" && !hasStyledChars && !(obj == null ? void 0 : obj.path) && !Number((obj == null ? void 0 : obj.charSpacing) ?? 0);
5777
- const halfW = w / 2;
5778
- const lineAnchors = [];
5779
- for (let i = 0; i < lines.length; i++) {
5780
- let lineLeft = 0;
5781
- let lineW = 0;
5782
- let firstGlyphAdjust = 0;
5783
- try {
5784
- lineLeft = ((_a = obj._getLineLeftOffset) == null ? void 0 : _a.call(obj, i)) ?? 0;
5785
- } catch {
5786
- lineLeft = 0;
5787
- }
5788
- try {
5789
- lineW = ((_b = obj.getLineWidth) == null ? void 0 : _b.call(obj, i)) ?? 0;
5790
- } catch {
5791
- lineW = 0;
5792
- }
5793
- try {
5794
- const firstBox = (_d = (_c = obj.__charBounds) == null ? void 0 : _c[i]) == null ? void 0 : _d[0];
5795
- const kerned = Number(firstBox == null ? void 0 : firstBox.kernedWidth);
5796
- const glyphW = Number(firstBox == null ? void 0 : firstBox.width);
5797
- if (Number.isFinite(kerned) && Number.isFinite(glyphW)) {
5798
- firstGlyphAdjust = kerned - glyphW;
5799
- }
5800
- } catch {
5801
- firstGlyphAdjust = 0;
5802
- }
5803
- const baseStart = -halfW + (Number.isFinite(lineLeft) ? lineLeft : 0);
5804
- if (canUseAlignmentAnchor && Number.isFinite(lineW) && lineW > 0) {
5805
- lineAnchors.push({
5806
- x: alignmentAnchor === "end" ? baseStart + lineW : baseStart + lineW / 2,
5807
- anchor: alignmentAnchor,
5808
- lineWidth: lineW,
5809
- lineStart: baseStart
5810
- });
5811
- } else {
5812
- lineAnchors.push({
5813
- x: baseStart + (Number.isFinite(firstGlyphAdjust) ? firstGlyphAdjust : 0),
5814
- anchor: "start",
5815
- lineWidth: Number.isFinite(lineW) ? lineW : 0,
5816
- lineStart: baseStart
5817
- });
5818
- }
5819
- }
5820
- const textOpenRe = /<text\b([^>]*)>/i;
5821
- const textOpenMatch = svg.match(textOpenRe);
5822
- if (!textOpenMatch) return svg;
5823
- let textAttrs = textOpenMatch[1];
5824
- if (/\stext-anchor\s*=\s*"[^"]*"/i.test(textAttrs)) {
5825
- textAttrs = textAttrs.replace(/\stext-anchor\s*=\s*"[^"]*"/i, ' text-anchor="start"');
5826
- } else {
5827
- textAttrs = ` text-anchor="start"${textAttrs}`;
5828
- }
5829
- textAttrs = textAttrs.replace(
5830
- /(\sstyle=")([^"]*)(")/i,
5831
- (_m, pre, val, post) => pre + val.replace(/text-align\s*:\s*[^;"']+;?/gi, "").trim() + post
5832
- );
5833
- const newTextOpen = `<text${textAttrs}>`;
5834
- const stripAnchorAttrs = (attrs) => attrs.replace(/\s+text-anchor\s*=\s*"[^"]*"/gi, "").replace(
5835
- /(\sstyle=")([^"]*)(")/i,
5836
- (_m, pre, val, post) => pre + val.replace(/text-anchor\s*:\s*[^;"']+;?/gi, "").trim() + post
5837
- );
5838
- let lineIdx = 0;
5839
- let lastY = "";
5840
- const newSvg = svg.replace(textOpenMatch[0], newTextOpen).replace(
5841
- /<tspan\b([^>]*?)\sx="([^"]*)"([^>]*)>/gi,
5842
- (_m, pre, _oldX, post) => {
5843
- const attrs = `${pre} ${post}`;
5844
- const yMatch = attrs.match(/\sy\s*=\s*"([^"]*)"/i);
5845
- const y = (yMatch == null ? void 0 : yMatch[1]) ?? "";
5846
- const isLineStart = y !== "" ? y !== lastY : lineIdx < lineAnchors.length;
5847
- if (!isLineStart) return _m;
5848
- if (y !== "") lastY = y;
5849
- const lineAnchor = lineAnchors[lineIdx];
5850
- lineIdx += 1;
5851
- if (!lineAnchor || typeof lineAnchor.x !== "number" || !Number.isFinite(lineAnchor.x)) return _m;
5852
- const cleanPre = stripAnchorAttrs(pre);
5853
- const cleanPost = stripAnchorAttrs(post);
5854
- return `<tspan${cleanPre} x="${lineAnchor.x.toFixed(3)}" text-anchor="${lineAnchor.anchor}" data-pd-line-anchor="1" data-pd-line-width="${lineAnchor.lineWidth.toFixed(3)}" data-pd-line-start="${lineAnchor.lineStart.toFixed(3)}"${cleanPost}>`;
5855
- }
5856
- );
5857
- return newSvg;
5858
- } catch {
5859
- return svg;
5860
- }
5861
- }
5862
5763
  function _recolorSvgFills(svg, color) {
5863
5764
  const safe = escapeXmlAttr(color);
5864
5765
  let out = svg.replace(
@@ -15959,121 +15860,6 @@ function PixldocsPreview(props) {
15959
15860
  !canvasSettled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
15960
15861
  ] });
15961
15862
  }
15962
- function isFabricTextLike(obj) {
15963
- return !!obj && (obj.type === "textbox" || obj.type === "i-text" || obj.type === "text" || Array.isArray(obj._textLines) && typeof obj.getLineWidth === "function");
15964
- }
15965
- function bakeSelectableTextSvgToFabricLineAnchors(svg, obj) {
15966
- try {
15967
- if (/\bdata-pd-line-anchor\s*=\s*"1"/i.test(svg)) return svg;
15968
- const rawAlign = String((obj == null ? void 0 : obj.textAlign) || "left").toLowerCase();
15969
- if (!/center|right|end/.test(rawAlign)) return svg;
15970
- const lines = (obj == null ? void 0 : obj._textLines) ?? [];
15971
- const width = Number((obj == null ? void 0 : obj.width) ?? 0);
15972
- if (!Array.isArray(lines) || lines.length === 0 || !Number.isFinite(width) || width <= 0) return svg;
15973
- const alignmentAnchor = /right|end/.test(rawAlign) ? "end" : "middle";
15974
- const hasStyledChars = (() => {
15975
- const styles = obj == null ? void 0 : obj.styles;
15976
- if (!styles || typeof styles !== "object") return false;
15977
- return Object.values(styles).some((line2) => line2 && typeof line2 === "object" && Object.keys(line2).length > 0);
15978
- })();
15979
- const canUseLineAnchor = !hasStyledChars && !(obj == null ? void 0 : obj.path) && !Number((obj == null ? void 0 : obj.charSpacing) ?? 0);
15980
- const halfW = width / 2;
15981
- const lineAnchors = lines.map((_line, i) => {
15982
- var _a, _b, _c, _d;
15983
- let lineLeft = 0;
15984
- let lineW = 0;
15985
- let firstGlyphAdjust = 0;
15986
- try {
15987
- lineLeft = Number(((_a = obj._getLineLeftOffset) == null ? void 0 : _a.call(obj, i)) ?? 0);
15988
- } catch {
15989
- lineLeft = 0;
15990
- }
15991
- try {
15992
- lineW = Number(((_b = obj.getLineWidth) == null ? void 0 : _b.call(obj, i)) ?? 0);
15993
- } catch {
15994
- lineW = 0;
15995
- }
15996
- try {
15997
- const firstBox = (_d = (_c = obj.__charBounds) == null ? void 0 : _c[i]) == null ? void 0 : _d[0];
15998
- const kerned = Number(firstBox == null ? void 0 : firstBox.kernedWidth);
15999
- const glyphW = Number(firstBox == null ? void 0 : firstBox.width);
16000
- if (Number.isFinite(kerned) && Number.isFinite(glyphW)) firstGlyphAdjust = kerned - glyphW;
16001
- } catch {
16002
- firstGlyphAdjust = 0;
16003
- }
16004
- const baseStart = -halfW + (Number.isFinite(lineLeft) ? lineLeft : 0);
16005
- if (canUseLineAnchor && Number.isFinite(lineW) && lineW > 0) {
16006
- return {
16007
- x: alignmentAnchor === "end" ? baseStart + lineW : baseStart + lineW / 2,
16008
- anchor: alignmentAnchor,
16009
- lineWidth: lineW,
16010
- lineStart: baseStart
16011
- };
16012
- }
16013
- return {
16014
- x: baseStart + (Number.isFinite(firstGlyphAdjust) ? firstGlyphAdjust : 0),
16015
- anchor: "start",
16016
- lineWidth: Number.isFinite(lineW) ? lineW : 0,
16017
- lineStart: baseStart
16018
- };
16019
- });
16020
- const stripAnchorAttrs = (attrs) => attrs.replace(/\s+text-anchor\s*=\s*"[^"]*"/gi, "").replace(/\s+data-pd-line-anchor\s*=\s*"[^"]*"/gi, "").replace(/(\sstyle=")([^"]*)(")/i, (_m, pre, val, post) => {
16021
- const cleaned = val.replace(/text-anchor\s*:\s*[^;"']+;?/gi, "").replace(/text-align\s*:\s*[^;"']+;?/gi, "").trim();
16022
- return cleaned ? `${pre}${cleaned}${post}` : "";
16023
- });
16024
- const textOpenMatch = svg.match(/<text\b([^>]*)>/i);
16025
- if (!textOpenMatch) return svg;
16026
- const textAttrs = stripAnchorAttrs(textOpenMatch[1]);
16027
- let lineIdx = 0;
16028
- let lastY = "";
16029
- let replacedLine = false;
16030
- const patched = svg.replace(textOpenMatch[0], `<text text-anchor="start"${textAttrs}>`).replace(
16031
- /<tspan\b([^>]*?)\sx="([^"]*)"([^>]*)>/gi,
16032
- (match, pre, _oldX, post) => {
16033
- const attrs = `${pre} ${post}`;
16034
- const yMatch = attrs.match(/\sy\s*=\s*"([^"]*)"/i);
16035
- const y = (yMatch == null ? void 0 : yMatch[1]) ?? "";
16036
- const isLineStart = y !== "" ? y !== lastY : lineIdx < lineAnchors.length;
16037
- if (!isLineStart) return match;
16038
- if (y !== "") lastY = y;
16039
- const line2 = lineAnchors[lineIdx++];
16040
- if (!line2 || !Number.isFinite(line2.x)) return match;
16041
- replacedLine = true;
16042
- return `<tspan${stripAnchorAttrs(pre)} x="${line2.x.toFixed(3)}" text-anchor="${line2.anchor}" data-pd-line-anchor="1" data-pd-line-width="${line2.lineWidth.toFixed(3)}" data-pd-line-start="${line2.lineStart.toFixed(3)}"${stripAnchorAttrs(post)}>`;
16043
- }
16044
- );
16045
- if (replacedLine) return patched;
16046
- const line = lineAnchors[0];
16047
- if (!line || !Number.isFinite(line.x)) return patched;
16048
- return patched.replace(/<text\b([^>]*)>/i, (_m, attrs) => {
16049
- const clean = stripAnchorAttrs(attrs).replace(/\s+x\s*=\s*"[^"]*"/i, "");
16050
- return `<text x="${line.x.toFixed(3)}" text-anchor="${line.anchor}" data-pd-line-anchor="1" data-pd-line-width="${line.lineWidth.toFixed(3)}" data-pd-line-start="${line.lineStart.toFixed(3)}"${clean}>`;
16051
- });
16052
- } catch {
16053
- return svg;
16054
- }
16055
- }
16056
- function patchTextObjectsForSelectableSvg(fabricInstance) {
16057
- var _a;
16058
- const records = [];
16059
- const visit = (obj) => {
16060
- if (!obj || typeof obj !== "object") return;
16061
- if (isFabricTextLike(obj) && typeof obj.toSVG === "function") {
16062
- const original = obj.toSVG;
16063
- obj.toSVG = function patchedSelectableTextToSVG(reviver) {
16064
- return bakeSelectableTextSvgToFabricLineAnchors(original.call(this, reviver), this);
16065
- };
16066
- records.push({ obj, toSVG: original });
16067
- }
16068
- const children = typeof obj.getObjects === "function" ? obj.getObjects() : obj._objects;
16069
- if (Array.isArray(children)) children.forEach(visit);
16070
- };
16071
- try {
16072
- (_a = fabricInstance == null ? void 0 : fabricInstance.getObjects) == null ? void 0 : _a.call(fabricInstance).forEach(visit);
16073
- } catch {
16074
- }
16075
- return records;
16076
- }
16077
15863
  function normalizeSvgDimensions(svg, targetWidth, targetHeight) {
16078
15864
  let normalized = svg;
16079
15865
  if (/\bwidth="[^"]*"/i.test(normalized)) {
@@ -16127,7 +15913,6 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16127
15913
  } catch {
16128
15914
  }
16129
15915
  const fadeBakeRecords = [];
16130
- const textSvgPatchRecords = patchTextObjectsForSelectableSvg(fabricInstance);
16131
15916
  try {
16132
15917
  const objs = fabricInstance.getObjects().slice();
16133
15918
  for (const obj of objs) {
@@ -16176,12 +15961,6 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16176
15961
  const raw = fabricInstance.toSVG();
16177
15962
  svgString = normalizeSvgDimensions(raw, canvasWidth, canvasHeight);
16178
15963
  } finally {
16179
- for (const rec of textSvgPatchRecords) {
16180
- try {
16181
- rec.obj.toSVG = rec.toSVG;
16182
- } catch {
16183
- }
16184
- }
16185
15964
  for (const rec of fadeBakeRecords) {
16186
15965
  try {
16187
15966
  fabricInstance.remove(rec.replacement);
@@ -16202,9 +15981,9 @@ function captureFabricCanvasSvgForPdf(fabricInstance, canvasWidth, canvasHeight)
16202
15981
  }
16203
15982
  return svgString;
16204
15983
  }
16205
- const resolvedPackageVersion = "0.5.160";
15984
+ const resolvedPackageVersion = "0.5.161";
16206
15985
  const PACKAGE_VERSION = resolvedPackageVersion;
16207
- const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.160";
15986
+ const DEPLOYMENT_VERSION_MARKER = "__PIXLDOCS_CANVAS_RENDERER_VERSION__:0.5.161";
16208
15987
  const roundParityValue = (value) => {
16209
15988
  if (typeof value !== "number") return value;
16210
15989
  return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
@@ -16639,7 +16418,7 @@ class PixldocsRenderer {
16639
16418
  await this.waitForCanvasScene(container, cloned, i);
16640
16419
  }
16641
16420
  console.log(`[canvas-renderer][pdf-unified] mounted ${cloned.pages.length} page(s), handing off to client exportMultiPagePdf`);
16642
- const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-DEMJeh_t.cjs"));
16421
+ const { exportMultiPagePdf, preparePagesForExport } = await Promise.resolve().then(() => require("./vectorPdfExport-CqdQi3YK.cjs"));
16643
16422
  const prepared = preparePagesForExport(
16644
16423
  cloned.pages,
16645
16424
  canvasWidth,
@@ -18741,7 +18520,7 @@ async function prepareLiveCanvasSvgForPdf(rawSvg, pageWidth, pageHeight, pageKey
18741
18520
  if (options == null ? void 0 : options.stripPageBackground) stripRootPageBackgroundFromSvg(svgToDraw);
18742
18521
  sanitizeSvgTreeForPdf(svgToDraw);
18743
18522
  try {
18744
- const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-DEMJeh_t.cjs"));
18523
+ const { bakeTextAnchorPositionsFromLiveSvg, logTextMeasurementDiagnostic } = await Promise.resolve().then(() => require("./vectorPdfExport-CqdQi3YK.cjs"));
18745
18524
  try {
18746
18525
  await logTextMeasurementDiagnostic(svgToDraw);
18747
18526
  } catch {
@@ -19088,4 +18867,4 @@ exports.setAutoShrinkDebug = setAutoShrinkDebug;
19088
18867
  exports.setBundledAssetPrefixes = setBundledAssetPrefixes;
19089
18868
  exports.warmResolvedTemplateForPreview = warmResolvedTemplateForPreview;
19090
18869
  exports.warmTemplateFromForm = warmTemplateFromForm;
19091
- //# sourceMappingURL=index-CtUEIsYl.cjs.map
18870
+ //# sourceMappingURL=index-OWSb_i03.cjs.map