@pixldocs/canvas-renderer 0.5.68 → 0.5.70

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
@@ -13001,6 +13001,19 @@ function injectLocalFontFaces(rawFontFamily) {
13001
13001
  document.head.appendChild(style);
13002
13002
  return true;
13003
13003
  }
13004
+ async function awaitLocalFontFace(rawFontFamily, timeoutMs = 1600) {
13005
+ if (typeof document === "undefined" || !document.fonts) return false;
13006
+ const fontFamily = normalizeFontFamily(rawFontFamily);
13007
+ if (!injectLocalFontFaces(fontFamily)) return false;
13008
+ const weights = [400, 700];
13009
+ const loads = Promise.all(
13010
+ weights.map((weight) => document.fonts.load(`${weight} 16px "${fontFamily}"`))
13011
+ ).then(() => document.fonts.check(`400 16px "${fontFamily}"`));
13012
+ return await Promise.race([
13013
+ loads.catch(() => false),
13014
+ new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs))
13015
+ ]);
13016
+ }
13004
13017
  function withTimeout(promise, timeoutMs = 4e3) {
13005
13018
  let timeoutId;
13006
13019
  return Promise.race([
@@ -13021,7 +13034,7 @@ async function loadGoogleFontCSS(rawFontFamily) {
13021
13034
  if (existing) return existing;
13022
13035
  const promise = (async () => {
13023
13036
  try {
13024
- if (injectLocalFontFaces(fontFamily)) {
13037
+ if (await awaitLocalFontFace(fontFamily)) {
13025
13038
  loadedFonts.add(fontFamily);
13026
13039
  return;
13027
13040
  }
@@ -13147,7 +13160,7 @@ async function ensureFontsForResolvedConfig(config) {
13147
13160
  if (typeof document === "undefined") return;
13148
13161
  const descriptors = collectFontDescriptorsFromConfig(config);
13149
13162
  const families = new Set(descriptors.map((d) => d.family));
13150
- void withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 2500);
13163
+ await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 3500);
13151
13164
  if (document.fonts) {
13152
13165
  descriptors.forEach((d) => {
13153
13166
  const stylePrefix = d.style === "italic" ? "italic " : "";
@@ -13176,7 +13189,7 @@ function configHasAutoShrinkText$1(config) {
13176
13189
  }
13177
13190
  async function awaitFontsForConfig(config, maxWaitMs) {
13178
13191
  if (typeof document === "undefined" || !document.fonts) return;
13179
- void ensureFontsForResolvedConfig(config);
13192
+ await ensureFontsForResolvedConfig(config);
13180
13193
  const descriptors = collectFontDescriptorsFromConfig(config);
13181
13194
  if (descriptors.length === 0) return;
13182
13195
  const loads = Promise.all(
@@ -13418,7 +13431,7 @@ function PixldocsPreview(props) {
13418
13431
  !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..." }) })
13419
13432
  ] });
13420
13433
  }
13421
- const PACKAGE_VERSION = "0.5.68";
13434
+ const PACKAGE_VERSION = "0.5.70";
13422
13435
  let __underlineFixInstalled = false;
13423
13436
  function installUnderlineFix(fab) {
13424
13437
  var _a;
@@ -13908,7 +13921,7 @@ class PixldocsRenderer {
13908
13921
  */
13909
13922
  async awaitFontsForConfig(config, maxWaitMs) {
13910
13923
  if (typeof document === "undefined" || !document.fonts) return;
13911
- void ensureFontsForResolvedConfig(config);
13924
+ await ensureFontsForResolvedConfig(config);
13912
13925
  await this.waitForRelevantFonts(config, maxWaitMs);
13913
13926
  await Promise.race([
13914
13927
  document.fonts.ready.catch(() => void 0).then(() => void 0),
@@ -14364,6 +14377,65 @@ class PixldocsRenderer {
14364
14377
  await waitForPaint();
14365
14378
  }
14366
14379
  }
14380
+ function dumpSvgTextDiagnostics(svgStr, pageIndex, tag, stage, maxItems = 30) {
14381
+ try {
14382
+ if (typeof DOMParser === "undefined") return;
14383
+ const doc = new DOMParser().parseFromString(svgStr, "image/svg+xml");
14384
+ if (doc.querySelector("parsererror")) {
14385
+ console.warn(`${tag} page=${pageIndex} stage=${stage} parse-error`);
14386
+ return;
14387
+ }
14388
+ const root = doc.documentElement;
14389
+ const svgWidth = root == null ? void 0 : root.getAttribute("width");
14390
+ const svgHeight = root == null ? void 0 : root.getAttribute("height");
14391
+ const svgViewBox = root == null ? void 0 : root.getAttribute("viewBox");
14392
+ const texts = Array.from(doc.querySelectorAll("text"));
14393
+ const summary = {
14394
+ page: pageIndex,
14395
+ stage,
14396
+ svgLen: svgStr.length,
14397
+ svgWidth,
14398
+ svgHeight,
14399
+ svgViewBox,
14400
+ textCount: texts.length
14401
+ };
14402
+ console.log(`${tag} ${stage} page=${pageIndex} summary`, summary);
14403
+ const sample = texts.slice(0, maxItems).map((t, idx) => {
14404
+ var _a, _b;
14405
+ const tspans = Array.from(t.querySelectorAll("tspan"));
14406
+ const tspanInfo = tspans.slice(0, 4).map((s) => ({
14407
+ x: s.getAttribute("x"),
14408
+ y: s.getAttribute("y"),
14409
+ text: (s.textContent || "").slice(0, 40)
14410
+ }));
14411
+ let containerWidth = null;
14412
+ let cursor = t.parentElement;
14413
+ while (cursor && !containerWidth) {
14414
+ containerWidth = (_a = cursor.getAttribute) == null ? void 0 : _a.call(cursor, "width");
14415
+ cursor = cursor.parentElement;
14416
+ if (cursor && ((_b = cursor.tagName) == null ? void 0 : _b.toLowerCase()) === "svg") break;
14417
+ }
14418
+ return {
14419
+ idx,
14420
+ x: t.getAttribute("x"),
14421
+ y: t.getAttribute("y"),
14422
+ fontSize: t.getAttribute("font-size"),
14423
+ fontFamily: t.getAttribute("font-family"),
14424
+ fontWeight: t.getAttribute("font-weight"),
14425
+ textAnchor: t.getAttribute("text-anchor"),
14426
+ transform: t.getAttribute("transform"),
14427
+ style: (t.getAttribute("style") || "").slice(0, 120),
14428
+ ancestorWidth: containerWidth,
14429
+ textContent: (t.textContent || "").slice(0, 60),
14430
+ tspanCount: tspans.length,
14431
+ tspanSample: tspanInfo
14432
+ };
14433
+ });
14434
+ console.log(`${tag} ${stage} page=${pageIndex} text-sample (first ${sample.length}/${texts.length})`, sample);
14435
+ } catch (err) {
14436
+ console.warn(`${tag} ${stage} page=${pageIndex} dump threw`, err);
14437
+ }
14438
+ }
14367
14439
  const SVG_DRAWABLE_TAGS = /* @__PURE__ */ new Set([
14368
14440
  "path",
14369
14441
  "rect",
@@ -15659,6 +15731,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15659
15731
  const { title, stripPageBackground } = options;
15660
15732
  const firstPage = svgResults[0];
15661
15733
  const orientation = firstPage.width > firstPage.height ? "landscape" : "portrait";
15734
+ const PARITY_TAG = "[canvas-renderer][parity-diag][pkg-pdf]";
15735
+ console.log(`${PARITY_TAG} pkg-version=0.5.70 pages=${svgResults.length}`);
15736
+ try {
15737
+ for (let pi = 0; pi < svgResults.length; pi++) {
15738
+ dumpSvgTextDiagnostics(svgResults[pi].svg, pi, PARITY_TAG, "STAGE-1-raw-toSVG");
15739
+ }
15740
+ } catch (e) {
15741
+ console.warn(`${PARITY_TAG} dump failed`, e);
15742
+ }
15662
15743
  const pdf = new jspdf.jsPDF({
15663
15744
  orientation,
15664
15745
  unit: "px",
@@ -15688,6 +15769,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15688
15769
  stripPageBackground: shouldStripBg
15689
15770
  });
15690
15771
  if (processedSvg) {
15772
+ try {
15773
+ dumpSvgTextDiagnostics(
15774
+ new XMLSerializer().serializeToString(processedSvg),
15775
+ i,
15776
+ PARITY_TAG,
15777
+ "STAGE-2-after-prepareLiveCanvasSvgForPdf"
15778
+ );
15779
+ } catch {
15780
+ }
15691
15781
  await convertTextDecorationsToLines(processedSvg);
15692
15782
  if (shouldOutlineText) {
15693
15783
  try {
@@ -15709,6 +15799,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15709
15799
  const reParser = new DOMParser();
15710
15800
  const reDoc = reParser.parseFromString(rewrittenSvg, "image/svg+xml");
15711
15801
  processedSvg = reDoc.documentElement;
15802
+ try {
15803
+ dumpSvgTextDiagnostics(
15804
+ rewrittenSvg,
15805
+ i,
15806
+ PARITY_TAG,
15807
+ "STAGE-3-after-rewriteSvgFontsForJsPDF"
15808
+ );
15809
+ } catch {
15810
+ }
15712
15811
  }
15713
15812
  if (processedSvg) {
15714
15813
  pdf.setFillColor(0, 0, 0);
@@ -15732,7 +15831,8 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15732
15831
  }
15733
15832
  const pdfExport = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
15734
15833
  __proto__: null,
15735
- assemblePdfFromSvgs
15834
+ assemblePdfFromSvgs,
15835
+ dumpSvgTextDiagnostics
15736
15836
  }, Symbol.toStringTag, { value: "Module" }));
15737
15837
  function collectImageUrls(config) {
15738
15838
  const urls = [];
@@ -15835,6 +15935,7 @@ exports.collectFontDescriptorsFromConfig = collectFontDescriptorsFromConfig;
15835
15935
  exports.collectFontsFromConfig = collectFontsFromConfig;
15836
15936
  exports.collectImageUrls = collectImageUrls;
15837
15937
  exports.configHasAutoShrinkText = configHasAutoShrinkText$1;
15938
+ exports.dumpSvgTextDiagnostics = dumpSvgTextDiagnostics;
15838
15939
  exports.embedFont = embedFont;
15839
15940
  exports.embedFontsForConfig = embedFontsForConfig;
15840
15941
  exports.embedFontsInPdf = embedFontsInPdf;