@pixldocs/canvas-renderer 0.5.64 → 0.5.66

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
@@ -12561,7 +12561,7 @@ function PixldocsPreview(props) {
12561
12561
  !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..." }) })
12562
12562
  ] });
12563
12563
  }
12564
- const PACKAGE_VERSION = "0.5.64";
12564
+ const PACKAGE_VERSION = "0.5.66";
12565
12565
  let __underlineFixInstalled = false;
12566
12566
  function installUnderlineFix(fab) {
12567
12567
  var _a;
@@ -13277,6 +13277,7 @@ class PixldocsRenderer {
13277
13277
  captureSvgViaPreviewCanvas(config, pageIndex, canvasWidth, canvasHeight) {
13278
13278
  return new Promise(async (resolve, reject) => {
13279
13279
  const { PreviewCanvas: PreviewCanvas2 } = await Promise.resolve().then(() => PreviewCanvas$1);
13280
+ const hasAutoShrink = configHasAutoShrinkText(config);
13280
13281
  const container = document.createElement("div");
13281
13282
  container.style.cssText = `
13282
13283
  position: fixed; left: -99999px; top: -99999px;
@@ -13289,6 +13290,8 @@ class PixldocsRenderer {
13289
13290
  reject(new Error("SVG render timeout (30s)"));
13290
13291
  }, 3e4);
13291
13292
  let root = null;
13293
+ let mountKey = 0;
13294
+ let didPreviewParityRemount = false;
13292
13295
  const cleanup = () => {
13293
13296
  clearTimeout(timeout);
13294
13297
  try {
@@ -13297,6 +13300,48 @@ class PixldocsRenderer {
13297
13300
  }
13298
13301
  container.remove();
13299
13302
  };
13303
+ const mountPreview = (readyHandler) => {
13304
+ root = client.createRoot(container);
13305
+ root.render(
13306
+ react.createElement(PreviewCanvas2, {
13307
+ key: `svg-capture-${mountKey}`,
13308
+ config,
13309
+ pageIndex,
13310
+ zoom: 1,
13311
+ absoluteZoom: true,
13312
+ skipFontReadyWait: false,
13313
+ onReady: readyHandler
13314
+ })
13315
+ );
13316
+ };
13317
+ const remountForPreviewParity = async () => {
13318
+ if (didPreviewParityRemount) return;
13319
+ didPreviewParityRemount = true;
13320
+ mountKey += 1;
13321
+ try {
13322
+ clearMeasurementCache();
13323
+ } catch {
13324
+ }
13325
+ try {
13326
+ clearFabricCharCache();
13327
+ } catch {
13328
+ }
13329
+ try {
13330
+ root == null ? void 0 : root.unmount();
13331
+ } catch {
13332
+ }
13333
+ await new Promise((settle) => {
13334
+ mountPreview(() => {
13335
+ this.waitForCanvasScene(container, config, pageIndex).then(async () => {
13336
+ const expectedImageCount = this.getExpectedImageCount(config, pageIndex);
13337
+ await this.waitForCanvasImages(container, expectedImageCount);
13338
+ await this.waitForStableTextMetrics(container, config);
13339
+ await this.waitForCanvasScene(container, config, pageIndex);
13340
+ settle();
13341
+ }).catch(() => settle());
13342
+ });
13343
+ });
13344
+ };
13300
13345
  const onReady = () => {
13301
13346
  this.waitForCanvasScene(container, config, pageIndex).then(async () => {
13302
13347
  var _a, _b;
@@ -13305,6 +13350,10 @@ class PixldocsRenderer {
13305
13350
  await this.waitForCanvasImages(container, expectedImageCount);
13306
13351
  await this.waitForStableTextMetrics(container, config);
13307
13352
  await this.waitForCanvasScene(container, config, pageIndex);
13353
+ if (hasAutoShrink && !didPreviewParityRemount) {
13354
+ console.log("[canvas-renderer][svg-parity] remounting once to match PixldocsPreview auto-shrink stabilization");
13355
+ await remountForPreviewParity();
13356
+ }
13308
13357
  const fabricInstance = this.getFabricCanvasFromContainer(container);
13309
13358
  if (!fabricInstance) {
13310
13359
  cleanup();
@@ -13353,18 +13402,7 @@ class PixldocsRenderer {
13353
13402
  }
13354
13403
  });
13355
13404
  };
13356
- root = client.createRoot(container);
13357
- root.render(
13358
- react.createElement(PreviewCanvas2, {
13359
- config,
13360
- pageIndex,
13361
- zoom: 1,
13362
- // 1:1 — no UI scaling for SVG capture
13363
- absoluteZoom: true,
13364
- skipFontReadyWait: false,
13365
- onReady
13366
- })
13367
- );
13405
+ mountPreview(onReady);
13368
13406
  });
13369
13407
  }
13370
13408
  /**
@@ -15179,6 +15217,14 @@ async function svg2pdfWithDomMount(svg, pdf, opts) {
15179
15217
  async function convertTextDecorationsToLines(svg) {
15180
15218
  const doc = svg.ownerDocument;
15181
15219
  if (!doc) return;
15220
+ const stripTextDecoration = (el) => {
15221
+ el.removeAttribute("text-decoration");
15222
+ const style = el.getAttribute("style") || "";
15223
+ if (!style) return;
15224
+ const kept = style.split(";").map((part) => part.trim()).filter(Boolean).filter((part) => !/^text-decoration\s*:/i.test(part));
15225
+ if (kept.length > 0) el.setAttribute("style", kept.join("; "));
15226
+ else el.removeAttribute("style");
15227
+ };
15182
15228
  const resolveInheritedSvgValue = (el, attr, styleProp = attr) => {
15183
15229
  var _a, _b;
15184
15230
  let current = el;
@@ -15329,6 +15375,8 @@ async function convertTextDecorationsToLines(svg) {
15329
15375
  if (textEl.parentElement) {
15330
15376
  textEl.parentElement.insertBefore(line, textEl.nextSibling);
15331
15377
  }
15378
+ stripTextDecoration(tspan);
15379
+ if (textHasUnderline) stripTextDecoration(textEl);
15332
15380
  }
15333
15381
  }
15334
15382
  if (tempContainer) {
@@ -15567,7 +15615,7 @@ function drawPageBackground(pdf, pageIndex, pageWidth, pageHeight, backgroundCol
15567
15615
  }
15568
15616
  }
15569
15617
  async function assemblePdfFromSvgs(svgResults, options = {}) {
15570
- var _a, _b;
15618
+ var _a, _b, _c;
15571
15619
  if (svgResults.length === 0) throw new Error("No pages to export");
15572
15620
  const { title, stripPageBackground } = options;
15573
15621
  const firstPage = svgResults[0];
@@ -15595,17 +15643,33 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15595
15643
  const hasGradient = !!((_b = (_a = page.backgroundGradient) == null ? void 0 : _a.stops) == null ? void 0 : _b.length);
15596
15644
  drawPageBackground(pdf, i, page.width, page.height, page.backgroundColor, page.backgroundGradient);
15597
15645
  const shouldStripBg = stripPageBackground ?? hasGradient;
15646
+ const shouldOutlineText = options.outlineText ?? true;
15598
15647
  const pageSvg = page.svg;
15599
15648
  let processedSvg = await prepareLiveCanvasSvgForPdf(pageSvg, page.width, page.height, `page-${i + 1}`, {
15600
15649
  stripPageBackground: shouldStripBg
15601
15650
  });
15602
15651
  if (processedSvg) {
15603
- const svgStr = new XMLSerializer().serializeToString(processedSvg);
15604
- const rewrittenSvg = rewriteSvgFontsForJsPDF(svgStr);
15652
+ await convertTextDecorationsToLines(processedSvg);
15653
+ if (shouldOutlineText) {
15654
+ try {
15655
+ const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-BTHnqJpM.cjs"));
15656
+ const outlinedSvg = await convertAllTextToPath(
15657
+ new XMLSerializer().serializeToString(processedSvg),
15658
+ fontBaseUrl
15659
+ );
15660
+ const outlineDoc = new DOMParser().parseFromString(outlinedSvg, "image/svg+xml");
15661
+ const outlinedRoot = outlineDoc.documentElement;
15662
+ if (outlinedRoot && ((_c = outlinedRoot.tagName) == null ? void 0 : _c.toLowerCase()) === "svg" && !outlineDoc.querySelector("parsererror")) {
15663
+ processedSvg = outlinedRoot;
15664
+ }
15665
+ } catch (outlineErr) {
15666
+ console.warn("[canvas-renderer][pdf] text outlining unavailable, falling back to embedded SVG text:", outlineErr);
15667
+ }
15668
+ }
15669
+ const rewrittenSvg = rewriteSvgFontsForJsPDF(new XMLSerializer().serializeToString(processedSvg));
15605
15670
  const reParser = new DOMParser();
15606
15671
  const reDoc = reParser.parseFromString(rewrittenSvg, "image/svg+xml");
15607
15672
  processedSvg = reDoc.documentElement;
15608
- await convertTextDecorationsToLines(processedSvg);
15609
15673
  }
15610
15674
  if (processedSvg) {
15611
15675
  pdf.setFillColor(0, 0, 0);