@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.d.ts CHANGED
@@ -87,6 +87,8 @@ export declare function collectImageUrls(config: TemplateConfig): string[];
87
87
  */
88
88
  export declare function configHasAutoShrinkText(config: TemplateConfig | null | undefined): boolean;
89
89
 
90
+ export declare function dumpSvgTextDiagnostics(svgStr: string, pageIndex: number, tag: string, stage: string, maxItems?: number): void;
91
+
90
92
  export declare interface DynamicField {
91
93
  id: string;
92
94
  label: string;
@@ -254,7 +256,7 @@ export declare function normalizeFontFamily(fontStack: string): string;
254
256
  * Package version banner. Bump alongside package.json so we can confirm
255
257
  * (via browser:log) that the deployed bundle matches the expected build.
256
258
  */
257
- export declare const PACKAGE_VERSION = "0.5.68";
259
+ export declare const PACKAGE_VERSION = "0.5.70";
258
260
 
259
261
  export declare interface PageSettings {
260
262
  backgroundColor?: string;
package/dist/index.js CHANGED
@@ -12982,6 +12982,19 @@ function injectLocalFontFaces(rawFontFamily) {
12982
12982
  document.head.appendChild(style);
12983
12983
  return true;
12984
12984
  }
12985
+ async function awaitLocalFontFace(rawFontFamily, timeoutMs = 1600) {
12986
+ if (typeof document === "undefined" || !document.fonts) return false;
12987
+ const fontFamily = normalizeFontFamily(rawFontFamily);
12988
+ if (!injectLocalFontFaces(fontFamily)) return false;
12989
+ const weights = [400, 700];
12990
+ const loads = Promise.all(
12991
+ weights.map((weight) => document.fonts.load(`${weight} 16px "${fontFamily}"`))
12992
+ ).then(() => document.fonts.check(`400 16px "${fontFamily}"`));
12993
+ return await Promise.race([
12994
+ loads.catch(() => false),
12995
+ new Promise((resolve) => setTimeout(() => resolve(false), timeoutMs))
12996
+ ]);
12997
+ }
12985
12998
  function withTimeout(promise, timeoutMs = 4e3) {
12986
12999
  let timeoutId;
12987
13000
  return Promise.race([
@@ -13002,7 +13015,7 @@ async function loadGoogleFontCSS(rawFontFamily) {
13002
13015
  if (existing) return existing;
13003
13016
  const promise = (async () => {
13004
13017
  try {
13005
- if (injectLocalFontFaces(fontFamily)) {
13018
+ if (await awaitLocalFontFace(fontFamily)) {
13006
13019
  loadedFonts.add(fontFamily);
13007
13020
  return;
13008
13021
  }
@@ -13128,7 +13141,7 @@ async function ensureFontsForResolvedConfig(config) {
13128
13141
  if (typeof document === "undefined") return;
13129
13142
  const descriptors = collectFontDescriptorsFromConfig(config);
13130
13143
  const families = new Set(descriptors.map((d) => d.family));
13131
- void withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 2500);
13144
+ await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 3500);
13132
13145
  if (document.fonts) {
13133
13146
  descriptors.forEach((d) => {
13134
13147
  const stylePrefix = d.style === "italic" ? "italic " : "";
@@ -13157,7 +13170,7 @@ function configHasAutoShrinkText$1(config) {
13157
13170
  }
13158
13171
  async function awaitFontsForConfig(config, maxWaitMs) {
13159
13172
  if (typeof document === "undefined" || !document.fonts) return;
13160
- void ensureFontsForResolvedConfig(config);
13173
+ await ensureFontsForResolvedConfig(config);
13161
13174
  const descriptors = collectFontDescriptorsFromConfig(config);
13162
13175
  if (descriptors.length === 0) return;
13163
13176
  const loads = Promise.all(
@@ -13399,7 +13412,7 @@ function PixldocsPreview(props) {
13399
13412
  !canvasSettled && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) })
13400
13413
  ] });
13401
13414
  }
13402
- const PACKAGE_VERSION = "0.5.68";
13415
+ const PACKAGE_VERSION = "0.5.70";
13403
13416
  let __underlineFixInstalled = false;
13404
13417
  function installUnderlineFix(fab) {
13405
13418
  var _a;
@@ -13889,7 +13902,7 @@ class PixldocsRenderer {
13889
13902
  */
13890
13903
  async awaitFontsForConfig(config, maxWaitMs) {
13891
13904
  if (typeof document === "undefined" || !document.fonts) return;
13892
- void ensureFontsForResolvedConfig(config);
13905
+ await ensureFontsForResolvedConfig(config);
13893
13906
  await this.waitForRelevantFonts(config, maxWaitMs);
13894
13907
  await Promise.race([
13895
13908
  document.fonts.ready.catch(() => void 0).then(() => void 0),
@@ -14345,6 +14358,65 @@ class PixldocsRenderer {
14345
14358
  await waitForPaint();
14346
14359
  }
14347
14360
  }
14361
+ function dumpSvgTextDiagnostics(svgStr, pageIndex, tag, stage, maxItems = 30) {
14362
+ try {
14363
+ if (typeof DOMParser === "undefined") return;
14364
+ const doc = new DOMParser().parseFromString(svgStr, "image/svg+xml");
14365
+ if (doc.querySelector("parsererror")) {
14366
+ console.warn(`${tag} page=${pageIndex} stage=${stage} parse-error`);
14367
+ return;
14368
+ }
14369
+ const root = doc.documentElement;
14370
+ const svgWidth = root == null ? void 0 : root.getAttribute("width");
14371
+ const svgHeight = root == null ? void 0 : root.getAttribute("height");
14372
+ const svgViewBox = root == null ? void 0 : root.getAttribute("viewBox");
14373
+ const texts = Array.from(doc.querySelectorAll("text"));
14374
+ const summary = {
14375
+ page: pageIndex,
14376
+ stage,
14377
+ svgLen: svgStr.length,
14378
+ svgWidth,
14379
+ svgHeight,
14380
+ svgViewBox,
14381
+ textCount: texts.length
14382
+ };
14383
+ console.log(`${tag} ${stage} page=${pageIndex} summary`, summary);
14384
+ const sample = texts.slice(0, maxItems).map((t, idx) => {
14385
+ var _a, _b;
14386
+ const tspans = Array.from(t.querySelectorAll("tspan"));
14387
+ const tspanInfo = tspans.slice(0, 4).map((s) => ({
14388
+ x: s.getAttribute("x"),
14389
+ y: s.getAttribute("y"),
14390
+ text: (s.textContent || "").slice(0, 40)
14391
+ }));
14392
+ let containerWidth = null;
14393
+ let cursor = t.parentElement;
14394
+ while (cursor && !containerWidth) {
14395
+ containerWidth = (_a = cursor.getAttribute) == null ? void 0 : _a.call(cursor, "width");
14396
+ cursor = cursor.parentElement;
14397
+ if (cursor && ((_b = cursor.tagName) == null ? void 0 : _b.toLowerCase()) === "svg") break;
14398
+ }
14399
+ return {
14400
+ idx,
14401
+ x: t.getAttribute("x"),
14402
+ y: t.getAttribute("y"),
14403
+ fontSize: t.getAttribute("font-size"),
14404
+ fontFamily: t.getAttribute("font-family"),
14405
+ fontWeight: t.getAttribute("font-weight"),
14406
+ textAnchor: t.getAttribute("text-anchor"),
14407
+ transform: t.getAttribute("transform"),
14408
+ style: (t.getAttribute("style") || "").slice(0, 120),
14409
+ ancestorWidth: containerWidth,
14410
+ textContent: (t.textContent || "").slice(0, 60),
14411
+ tspanCount: tspans.length,
14412
+ tspanSample: tspanInfo
14413
+ };
14414
+ });
14415
+ console.log(`${tag} ${stage} page=${pageIndex} text-sample (first ${sample.length}/${texts.length})`, sample);
14416
+ } catch (err) {
14417
+ console.warn(`${tag} ${stage} page=${pageIndex} dump threw`, err);
14418
+ }
14419
+ }
14348
14420
  const SVG_DRAWABLE_TAGS = /* @__PURE__ */ new Set([
14349
14421
  "path",
14350
14422
  "rect",
@@ -15640,6 +15712,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15640
15712
  const { title, stripPageBackground } = options;
15641
15713
  const firstPage = svgResults[0];
15642
15714
  const orientation = firstPage.width > firstPage.height ? "landscape" : "portrait";
15715
+ const PARITY_TAG = "[canvas-renderer][parity-diag][pkg-pdf]";
15716
+ console.log(`${PARITY_TAG} pkg-version=0.5.70 pages=${svgResults.length}`);
15717
+ try {
15718
+ for (let pi = 0; pi < svgResults.length; pi++) {
15719
+ dumpSvgTextDiagnostics(svgResults[pi].svg, pi, PARITY_TAG, "STAGE-1-raw-toSVG");
15720
+ }
15721
+ } catch (e) {
15722
+ console.warn(`${PARITY_TAG} dump failed`, e);
15723
+ }
15643
15724
  const pdf = new jsPDF({
15644
15725
  orientation,
15645
15726
  unit: "px",
@@ -15669,6 +15750,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15669
15750
  stripPageBackground: shouldStripBg
15670
15751
  });
15671
15752
  if (processedSvg) {
15753
+ try {
15754
+ dumpSvgTextDiagnostics(
15755
+ new XMLSerializer().serializeToString(processedSvg),
15756
+ i,
15757
+ PARITY_TAG,
15758
+ "STAGE-2-after-prepareLiveCanvasSvgForPdf"
15759
+ );
15760
+ } catch {
15761
+ }
15672
15762
  await convertTextDecorationsToLines(processedSvg);
15673
15763
  if (shouldOutlineText) {
15674
15764
  try {
@@ -15690,6 +15780,15 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15690
15780
  const reParser = new DOMParser();
15691
15781
  const reDoc = reParser.parseFromString(rewrittenSvg, "image/svg+xml");
15692
15782
  processedSvg = reDoc.documentElement;
15783
+ try {
15784
+ dumpSvgTextDiagnostics(
15785
+ rewrittenSvg,
15786
+ i,
15787
+ PARITY_TAG,
15788
+ "STAGE-3-after-rewriteSvgFontsForJsPDF"
15789
+ );
15790
+ } catch {
15791
+ }
15693
15792
  }
15694
15793
  if (processedSvg) {
15695
15794
  pdf.setFillColor(0, 0, 0);
@@ -15713,7 +15812,8 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
15713
15812
  }
15714
15813
  const pdfExport = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
15715
15814
  __proto__: null,
15716
- assemblePdfFromSvgs
15815
+ assemblePdfFromSvgs,
15816
+ dumpSvgTextDiagnostics
15717
15817
  }, Symbol.toStringTag, { value: "Module" }));
15718
15818
  function collectImageUrls(config) {
15719
15819
  const urls = [];
@@ -15817,6 +15917,7 @@ export {
15817
15917
  collectFontsFromConfig,
15818
15918
  collectImageUrls,
15819
15919
  configHasAutoShrinkText$1 as configHasAutoShrinkText,
15920
+ dumpSvgTextDiagnostics,
15820
15921
  embedFont,
15821
15922
  embedFontsForConfig,
15822
15923
  embedFontsInPdf,