@pixldocs/canvas-renderer 0.5.14 → 0.5.16
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 +39 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +39 -29
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -91,8 +91,7 @@ export declare function embedFontsForConfig(pdf: jsPDF, config: any, fontBaseUrl
|
|
|
91
91
|
export declare function embedFontsInPdf(pdf: jsPDF, fontFamilies: Set<string>, fontBaseUrl: string): Promise<Set<string>>;
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
95
|
-
* and available to Fabric/Canvas before rendering.
|
|
94
|
+
* Start loading all fonts required by a fully-resolved TemplateConfig.
|
|
96
95
|
*
|
|
97
96
|
* This is the **single API** consumers (and the renderer internally) should
|
|
98
97
|
* call to guarantee font parity with EC2 `/render-from-form`.
|
|
@@ -101,8 +100,8 @@ export declare function embedFontsInPdf(pdf: jsPDF, fontFamilies: Set<string>, f
|
|
|
101
100
|
* 1. Walks ALL text nodes (including clones/repeatables) collecting
|
|
102
101
|
* fontFamily + fontWeight + fontStyle.
|
|
103
102
|
* 2. Loads each unique family via Google Fonts CSS v1 (idempotent).
|
|
104
|
-
* 3.
|
|
105
|
-
*
|
|
103
|
+
* 3. Kicks off each weight+style combo via `document.fonts.load()` without
|
|
104
|
+
* blocking render completion; late font load reflow handles final metrics.
|
|
106
105
|
*
|
|
107
106
|
* Idempotent — safe to call multiple times for the same config.
|
|
108
107
|
*/
|
package/dist/index.js
CHANGED
|
@@ -2637,6 +2637,19 @@ const FONTS_TO_PRELOAD = [
|
|
|
2637
2637
|
];
|
|
2638
2638
|
let fontsLoaded = false;
|
|
2639
2639
|
let fontsLoadingPromise = null;
|
|
2640
|
+
const withFontTimeout = async (promise, timeoutMs = 4e3) => {
|
|
2641
|
+
let timeoutId;
|
|
2642
|
+
try {
|
|
2643
|
+
return await Promise.race([
|
|
2644
|
+
promise,
|
|
2645
|
+
new Promise((resolve) => {
|
|
2646
|
+
timeoutId = setTimeout(resolve, timeoutMs);
|
|
2647
|
+
})
|
|
2648
|
+
]);
|
|
2649
|
+
} finally {
|
|
2650
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
2651
|
+
}
|
|
2652
|
+
};
|
|
2640
2653
|
const preloadFont = async (fontFamily) => {
|
|
2641
2654
|
try {
|
|
2642
2655
|
if (document.fonts) {
|
|
@@ -2657,11 +2670,11 @@ const preloadAllFonts = async () => {
|
|
|
2657
2670
|
}
|
|
2658
2671
|
fontsLoadingPromise = (async () => {
|
|
2659
2672
|
if (document.fonts) {
|
|
2660
|
-
await document.fonts.ready;
|
|
2673
|
+
await withFontTimeout(document.fonts.ready, 2500);
|
|
2661
2674
|
}
|
|
2662
|
-
await Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font)));
|
|
2675
|
+
await withFontTimeout(Promise.all(FONTS_TO_PRELOAD.map((font) => preloadFont(font))).then(() => void 0), 5e3);
|
|
2663
2676
|
if (document.fonts) {
|
|
2664
|
-
await document.fonts.ready;
|
|
2677
|
+
await withFontTimeout(document.fonts.ready, 2500);
|
|
2665
2678
|
}
|
|
2666
2679
|
fontsLoaded = true;
|
|
2667
2680
|
})();
|
|
@@ -2669,14 +2682,12 @@ const preloadAllFonts = async () => {
|
|
|
2669
2682
|
};
|
|
2670
2683
|
const waitForFontsReady = async () => {
|
|
2671
2684
|
if (!document.fonts) return;
|
|
2672
|
-
await document.fonts.ready;
|
|
2685
|
+
await withFontTimeout(document.fonts.ready, 2500);
|
|
2673
2686
|
};
|
|
2674
|
-
const DEFAULT_FONT_CHECK_TIMEOUT_MS = 3500;
|
|
2675
|
-
const FONT_CHECK_POLL_MS = 60;
|
|
2676
2687
|
const waitUntilFontsAvailable = async (fontFamilies, options) => {
|
|
2677
2688
|
if (!document.fonts || fontFamilies.length === 0) return;
|
|
2678
|
-
const timeoutMs =
|
|
2679
|
-
const pollMs =
|
|
2689
|
+
const timeoutMs = options == null ? void 0 : options.timeoutMs;
|
|
2690
|
+
const pollMs = options == null ? void 0 : options.pollIntervalMs;
|
|
2680
2691
|
const deadline = Date.now() + timeoutMs;
|
|
2681
2692
|
const check = () => fontFamilies.every(
|
|
2682
2693
|
(f) => document.fonts.check(`16px "${f}"`) && document.fonts.check(`bold 16px "${f}"`)
|
|
@@ -11675,6 +11686,17 @@ function normalizeFontFamily(fontStack) {
|
|
|
11675
11686
|
}
|
|
11676
11687
|
const loadedFonts = /* @__PURE__ */ new Set();
|
|
11677
11688
|
const loadingPromises = /* @__PURE__ */ new Map();
|
|
11689
|
+
function withTimeout(promise, timeoutMs = 4e3) {
|
|
11690
|
+
let timeoutId;
|
|
11691
|
+
return Promise.race([
|
|
11692
|
+
promise,
|
|
11693
|
+
new Promise((resolve) => {
|
|
11694
|
+
timeoutId = setTimeout(resolve, timeoutMs);
|
|
11695
|
+
})
|
|
11696
|
+
]).finally(() => {
|
|
11697
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
11698
|
+
});
|
|
11699
|
+
}
|
|
11678
11700
|
async function loadGoogleFontCSS(rawFontFamily) {
|
|
11679
11701
|
if (!rawFontFamily || typeof document === "undefined") return;
|
|
11680
11702
|
const fontFamily = normalizeFontFamily(rawFontFamily);
|
|
@@ -11695,10 +11717,6 @@ async function loadGoogleFontCSS(rawFontFamily) {
|
|
|
11695
11717
|
link.onerror = () => reject(new Error(`Failed to load font: ${fontFamily}`));
|
|
11696
11718
|
document.head.appendChild(link);
|
|
11697
11719
|
});
|
|
11698
|
-
if (document.fonts) {
|
|
11699
|
-
await document.fonts.load(`16px "${fontFamily}"`);
|
|
11700
|
-
await document.fonts.ready;
|
|
11701
|
-
}
|
|
11702
11720
|
loadedFonts.add(fontFamily);
|
|
11703
11721
|
} catch (e) {
|
|
11704
11722
|
console.warn(`[@pixldocs/canvas-renderer] Font load failed: ${fontFamily}`, e);
|
|
@@ -11810,17 +11828,15 @@ async function ensureFontsForResolvedConfig(config) {
|
|
|
11810
11828
|
if (typeof document === "undefined") return;
|
|
11811
11829
|
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
11812
11830
|
const families = new Set(descriptors.map((d) => d.family));
|
|
11813
|
-
|
|
11831
|
+
void withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 2500);
|
|
11814
11832
|
if (document.fonts) {
|
|
11815
|
-
|
|
11833
|
+
descriptors.forEach((d) => {
|
|
11816
11834
|
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
11817
11835
|
const weightStr = String(d.weight);
|
|
11818
11836
|
const spec = `${stylePrefix}${weightStr} 16px "${d.family}"`;
|
|
11819
|
-
|
|
11837
|
+
document.fonts.load(spec).catch(() => {
|
|
11820
11838
|
});
|
|
11821
11839
|
});
|
|
11822
|
-
await Promise.all(loadPromises);
|
|
11823
|
-
await document.fonts.ready;
|
|
11824
11840
|
}
|
|
11825
11841
|
}
|
|
11826
11842
|
function PixldocsPreview(props) {
|
|
@@ -12604,14 +12620,8 @@ class PixldocsRenderer {
|
|
|
12604
12620
|
return null;
|
|
12605
12621
|
}
|
|
12606
12622
|
async waitForStableTextMetrics(container, config) {
|
|
12607
|
-
var _a;
|
|
12608
12623
|
if (typeof document !== "undefined") {
|
|
12609
12624
|
await ensureFontsForResolvedConfig(config);
|
|
12610
|
-
await ((_a = document.fonts) == null ? void 0 : _a.ready);
|
|
12611
|
-
const fontFamilies = [...collectFontsFromConfig(config)].filter(Boolean);
|
|
12612
|
-
if (fontFamilies.length > 0) {
|
|
12613
|
-
await waitUntilFontsAvailable(fontFamilies, { timeoutMs: 4e3, pollIntervalMs: 50 });
|
|
12614
|
-
}
|
|
12615
12625
|
}
|
|
12616
12626
|
const fabricInstance = this.getFabricCanvasFromContainer(container);
|
|
12617
12627
|
if (!(fabricInstance == null ? void 0 : fabricInstance.getObjects)) return;
|
|
@@ -12621,9 +12631,9 @@ class PixldocsRenderer {
|
|
|
12621
12631
|
clearMeasurementCache();
|
|
12622
12632
|
};
|
|
12623
12633
|
const reflowTextboxes = () => {
|
|
12624
|
-
var
|
|
12634
|
+
var _a, _b, _c;
|
|
12625
12635
|
const walk = (obj) => {
|
|
12626
|
-
var
|
|
12636
|
+
var _a2, _b2, _c2, _d;
|
|
12627
12637
|
if (!obj) return;
|
|
12628
12638
|
const children = Array.isArray(obj._objects) ? obj._objects : Array.isArray(obj.objects) ? obj.objects : [];
|
|
12629
12639
|
if (children.length) children.forEach(walk);
|
|
@@ -12635,8 +12645,8 @@ class PixldocsRenderer {
|
|
|
12635
12645
|
scaleY: obj.scaleY
|
|
12636
12646
|
};
|
|
12637
12647
|
const resetTextboxLayoutInternals = () => {
|
|
12638
|
-
var
|
|
12639
|
-
(
|
|
12648
|
+
var _a3;
|
|
12649
|
+
(_a3 = obj._clearCache) == null ? void 0 : _a3.call(obj);
|
|
12640
12650
|
obj.__charBounds = [];
|
|
12641
12651
|
obj.__lineWidths = [];
|
|
12642
12652
|
obj.__lineHeights = [];
|
|
@@ -12650,7 +12660,7 @@ class PixldocsRenderer {
|
|
|
12650
12660
|
resetTextboxLayoutInternals();
|
|
12651
12661
|
obj.initDimensions();
|
|
12652
12662
|
if (saved.width != null) {
|
|
12653
|
-
(
|
|
12663
|
+
(_a2 = obj.set) == null ? void 0 : _a2.call(obj, {
|
|
12654
12664
|
width: saved.width,
|
|
12655
12665
|
scaleX: saved.scaleX,
|
|
12656
12666
|
scaleY: saved.scaleY
|
|
@@ -12669,7 +12679,7 @@ class PixldocsRenderer {
|
|
|
12669
12679
|
}
|
|
12670
12680
|
};
|
|
12671
12681
|
fabricInstance.getObjects().forEach(walk);
|
|
12672
|
-
(
|
|
12682
|
+
(_a = fabricInstance.calcOffset) == null ? void 0 : _a.call(fabricInstance);
|
|
12673
12683
|
(_b = fabricInstance.renderAll) == null ? void 0 : _b.call(fabricInstance);
|
|
12674
12684
|
(_c = fabricInstance.requestRenderAll) == null ? void 0 : _c.call(fabricInstance);
|
|
12675
12685
|
};
|