@pixldocs/canvas-renderer 0.5.77 → 0.5.79
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 +256 -219
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +256 -219
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -11664,6 +11664,232 @@ function applyContentBoundsPagination(config) {
|
|
|
11664
11664
|
if (!mutated) return config;
|
|
11665
11665
|
return { ...config, pages: resultPages };
|
|
11666
11666
|
}
|
|
11667
|
+
function normalizeFontFamily(fontStack) {
|
|
11668
|
+
const first = fontStack.split(",")[0].trim();
|
|
11669
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
11670
|
+
}
|
|
11671
|
+
const loadedFonts = /* @__PURE__ */ new Set();
|
|
11672
|
+
const loadingPromises = /* @__PURE__ */ new Map();
|
|
11673
|
+
function withTimeout(promise, timeoutMs = 4e3) {
|
|
11674
|
+
let timeoutId;
|
|
11675
|
+
return Promise.race([
|
|
11676
|
+
promise,
|
|
11677
|
+
new Promise((resolve) => {
|
|
11678
|
+
timeoutId = setTimeout(resolve, timeoutMs);
|
|
11679
|
+
})
|
|
11680
|
+
]).finally(() => {
|
|
11681
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
11682
|
+
});
|
|
11683
|
+
}
|
|
11684
|
+
async function loadGoogleFontCSS(rawFontFamily) {
|
|
11685
|
+
if (!rawFontFamily || typeof document === "undefined") return;
|
|
11686
|
+
const fontFamily = normalizeFontFamily(rawFontFamily);
|
|
11687
|
+
if (!fontFamily) return;
|
|
11688
|
+
if (loadedFonts.has(fontFamily)) return;
|
|
11689
|
+
const existing = loadingPromises.get(fontFamily);
|
|
11690
|
+
if (existing) return existing;
|
|
11691
|
+
const promise = (async () => {
|
|
11692
|
+
try {
|
|
11693
|
+
const encoded = encodeURIComponent(fontFamily);
|
|
11694
|
+
const url = `https://fonts.googleapis.com/css?family=${encoded}:300,400,500,600,700&display=swap`;
|
|
11695
|
+
const link = document.createElement("link");
|
|
11696
|
+
link.rel = "stylesheet";
|
|
11697
|
+
link.href = url;
|
|
11698
|
+
link.crossOrigin = "anonymous";
|
|
11699
|
+
await new Promise((resolve, reject) => {
|
|
11700
|
+
link.onload = () => resolve();
|
|
11701
|
+
link.onerror = () => reject(new Error(`Failed to load font: ${fontFamily}`));
|
|
11702
|
+
document.head.appendChild(link);
|
|
11703
|
+
});
|
|
11704
|
+
loadedFonts.add(fontFamily);
|
|
11705
|
+
} catch (e) {
|
|
11706
|
+
console.warn(`[@pixldocs/canvas-renderer] Font load failed: ${fontFamily}`, e);
|
|
11707
|
+
}
|
|
11708
|
+
})();
|
|
11709
|
+
loadingPromises.set(fontFamily, promise);
|
|
11710
|
+
await promise;
|
|
11711
|
+
loadingPromises.delete(fontFamily);
|
|
11712
|
+
}
|
|
11713
|
+
function collectFontsFromConfig(config) {
|
|
11714
|
+
var _a;
|
|
11715
|
+
const fonts = /* @__PURE__ */ new Set();
|
|
11716
|
+
fonts.add("Open Sans");
|
|
11717
|
+
fonts.add("Hind");
|
|
11718
|
+
function walk(nodes) {
|
|
11719
|
+
var _a2;
|
|
11720
|
+
if (!nodes) return;
|
|
11721
|
+
for (const node of nodes) {
|
|
11722
|
+
if (node.fontFamily) fonts.add(normalizeFontFamily(node.fontFamily));
|
|
11723
|
+
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) fonts.add(normalizeFontFamily(node.smartProps.fontFamily));
|
|
11724
|
+
if (node.styles && Array.isArray(node.styles)) {
|
|
11725
|
+
for (const lineStyle of node.styles) {
|
|
11726
|
+
if (lineStyle && typeof lineStyle === "object") {
|
|
11727
|
+
for (const charStyle of Object.values(lineStyle)) {
|
|
11728
|
+
if (charStyle == null ? void 0 : charStyle.fontFamily) fonts.add(normalizeFontFamily(charStyle.fontFamily));
|
|
11729
|
+
}
|
|
11730
|
+
}
|
|
11731
|
+
}
|
|
11732
|
+
}
|
|
11733
|
+
if (node.children) walk(node.children);
|
|
11734
|
+
}
|
|
11735
|
+
}
|
|
11736
|
+
for (const page of config.pages || []) {
|
|
11737
|
+
walk(page.children || []);
|
|
11738
|
+
}
|
|
11739
|
+
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
11740
|
+
for (const def of Object.values(config.themeConfig.variables)) {
|
|
11741
|
+
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
11742
|
+
if (def.label && /font/i.test(def.label)) {
|
|
11743
|
+
fonts.add(normalizeFontFamily(def.value));
|
|
11744
|
+
}
|
|
11745
|
+
}
|
|
11746
|
+
}
|
|
11747
|
+
}
|
|
11748
|
+
return fonts;
|
|
11749
|
+
}
|
|
11750
|
+
function collectFontDescriptorsFromConfig(config) {
|
|
11751
|
+
var _a;
|
|
11752
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11753
|
+
const descriptors = [];
|
|
11754
|
+
function add(family, weight, style) {
|
|
11755
|
+
const f = normalizeFontFamily(family);
|
|
11756
|
+
if (!f) return;
|
|
11757
|
+
const w = weight ?? 400;
|
|
11758
|
+
const s = style ?? "normal";
|
|
11759
|
+
const key = `${f}|${w}|${s}`;
|
|
11760
|
+
if (seen.has(key)) return;
|
|
11761
|
+
seen.add(key);
|
|
11762
|
+
descriptors.push({ family: f, weight: w, style: s });
|
|
11763
|
+
}
|
|
11764
|
+
function walk(nodes) {
|
|
11765
|
+
var _a2;
|
|
11766
|
+
if (!nodes) return;
|
|
11767
|
+
for (const node of nodes) {
|
|
11768
|
+
if (node.fontFamily) {
|
|
11769
|
+
add(node.fontFamily, node.fontWeight, node.fontStyle);
|
|
11770
|
+
if (node.type === "text") {
|
|
11771
|
+
for (const w of [300, 400, 500, 600, 700]) {
|
|
11772
|
+
add(node.fontFamily, w, node.fontStyle);
|
|
11773
|
+
}
|
|
11774
|
+
}
|
|
11775
|
+
}
|
|
11776
|
+
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) {
|
|
11777
|
+
add(node.smartProps.fontFamily, node.smartProps.fontWeight, node.smartProps.fontStyle);
|
|
11778
|
+
}
|
|
11779
|
+
if (node.styles) {
|
|
11780
|
+
const styleEntries = Array.isArray(node.styles) ? node.styles : Object.values(node.styles);
|
|
11781
|
+
for (const lineStyle of styleEntries) {
|
|
11782
|
+
if (lineStyle && typeof lineStyle === "object") {
|
|
11783
|
+
for (const charStyle of Object.values(lineStyle)) {
|
|
11784
|
+
if (charStyle == null ? void 0 : charStyle.fontFamily) {
|
|
11785
|
+
add(charStyle.fontFamily, charStyle.fontWeight, charStyle.fontStyle);
|
|
11786
|
+
}
|
|
11787
|
+
}
|
|
11788
|
+
}
|
|
11789
|
+
}
|
|
11790
|
+
}
|
|
11791
|
+
if (node.children) walk(node.children);
|
|
11792
|
+
}
|
|
11793
|
+
}
|
|
11794
|
+
add("Open Sans", 400, "normal");
|
|
11795
|
+
add("Hind", 400, "normal");
|
|
11796
|
+
add("Hind", 700, "normal");
|
|
11797
|
+
for (const page of config.pages || []) {
|
|
11798
|
+
walk(page.children || []);
|
|
11799
|
+
}
|
|
11800
|
+
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
11801
|
+
for (const def of Object.values(config.themeConfig.variables)) {
|
|
11802
|
+
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
11803
|
+
if (def.label && /font/i.test(def.label)) {
|
|
11804
|
+
add(def.value);
|
|
11805
|
+
}
|
|
11806
|
+
}
|
|
11807
|
+
}
|
|
11808
|
+
}
|
|
11809
|
+
return descriptors;
|
|
11810
|
+
}
|
|
11811
|
+
async function ensureFontsForResolvedConfig(config) {
|
|
11812
|
+
if (typeof document === "undefined") return;
|
|
11813
|
+
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
11814
|
+
const families = new Set(descriptors.map((d) => d.family));
|
|
11815
|
+
await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 3500);
|
|
11816
|
+
if (document.fonts) {
|
|
11817
|
+
descriptors.forEach((d) => {
|
|
11818
|
+
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
11819
|
+
const weightStr = String(d.weight);
|
|
11820
|
+
const spec = `${stylePrefix}${weightStr} 16px "${d.family}"`;
|
|
11821
|
+
document.fonts.load(spec).catch(() => {
|
|
11822
|
+
});
|
|
11823
|
+
});
|
|
11824
|
+
}
|
|
11825
|
+
}
|
|
11826
|
+
function configHasAutoShrinkText$1(config) {
|
|
11827
|
+
var _a;
|
|
11828
|
+
if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return false;
|
|
11829
|
+
const walk = (nodes) => {
|
|
11830
|
+
for (const node of nodes || []) {
|
|
11831
|
+
if (!node) continue;
|
|
11832
|
+
if (node.type === "text" && node.overflowPolicy === "auto-shrink") return true;
|
|
11833
|
+
if (Array.isArray(node.children) && node.children.length && walk(node.children)) return true;
|
|
11834
|
+
}
|
|
11835
|
+
return false;
|
|
11836
|
+
};
|
|
11837
|
+
for (const page of config.pages) {
|
|
11838
|
+
if (walk(page.children || [])) return true;
|
|
11839
|
+
}
|
|
11840
|
+
return false;
|
|
11841
|
+
}
|
|
11842
|
+
async function awaitFontsForConfig(config, maxWaitMs) {
|
|
11843
|
+
if (typeof document === "undefined" || !document.fonts) return;
|
|
11844
|
+
await ensureFontsForResolvedConfig(config);
|
|
11845
|
+
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
11846
|
+
if (descriptors.length === 0) return;
|
|
11847
|
+
const loads = Promise.all(
|
|
11848
|
+
descriptors.map((d) => {
|
|
11849
|
+
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
11850
|
+
const spec = `${stylePrefix}${d.weight} 16px "${d.family}"`;
|
|
11851
|
+
return document.fonts.load(spec).catch(() => []);
|
|
11852
|
+
})
|
|
11853
|
+
).then(() => void 0);
|
|
11854
|
+
await Promise.race([
|
|
11855
|
+
loads,
|
|
11856
|
+
new Promise((resolve) => setTimeout(resolve, maxWaitMs))
|
|
11857
|
+
]);
|
|
11858
|
+
await Promise.race([
|
|
11859
|
+
document.fonts.ready.catch(() => void 0).then(() => void 0),
|
|
11860
|
+
new Promise((r) => setTimeout(r, Math.min(500, maxWaitMs)))
|
|
11861
|
+
]);
|
|
11862
|
+
const checkSpecs = [];
|
|
11863
|
+
for (const d of descriptors) {
|
|
11864
|
+
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
11865
|
+
checkSpecs.push(`${stylePrefix}${d.weight} 16px "${d.family}"`);
|
|
11866
|
+
}
|
|
11867
|
+
const startedAt = Date.now();
|
|
11868
|
+
const pollBudget = Math.min(maxWaitMs, 2500);
|
|
11869
|
+
const allReady = () => {
|
|
11870
|
+
for (const spec of checkSpecs) {
|
|
11871
|
+
try {
|
|
11872
|
+
if (!document.fonts.check(spec)) return false;
|
|
11873
|
+
} catch {
|
|
11874
|
+
}
|
|
11875
|
+
}
|
|
11876
|
+
return true;
|
|
11877
|
+
};
|
|
11878
|
+
while (!allReady() && Date.now() - startedAt < pollBudget) {
|
|
11879
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
11880
|
+
}
|
|
11881
|
+
await new Promise(
|
|
11882
|
+
(resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
|
|
11883
|
+
);
|
|
11884
|
+
}
|
|
11885
|
+
async function awaitFontsBeforeTextReflow(config) {
|
|
11886
|
+
if (typeof document === "undefined" || !configHasAutoShrinkText$1(config)) return;
|
|
11887
|
+
try {
|
|
11888
|
+
await awaitFontsForConfig(config, 4e3);
|
|
11889
|
+
} catch (error) {
|
|
11890
|
+
console.warn("[@pixldocs/canvas-renderer] Font wait before text reflow failed:", error);
|
|
11891
|
+
}
|
|
11892
|
+
}
|
|
11667
11893
|
function repeatablePageToSection(page) {
|
|
11668
11894
|
return {
|
|
11669
11895
|
id: page.id,
|
|
@@ -11857,6 +12083,7 @@ async function resolveTemplateData(options) {
|
|
|
11857
12083
|
}
|
|
11858
12084
|
}
|
|
11859
12085
|
const repeatablePagesInput = deriveRepeatablePagesFromTemplate(config, inlineFormSchema, mergedFormData);
|
|
12086
|
+
await awaitFontsBeforeTextReflow(config);
|
|
11860
12087
|
const resolvedConfig = applyFormDataToConfig(
|
|
11861
12088
|
config,
|
|
11862
12089
|
mappings,
|
|
@@ -12001,6 +12228,7 @@ async function resolveFromForm(options) {
|
|
|
12001
12228
|
};
|
|
12002
12229
|
collectFormats(formConfig.sections);
|
|
12003
12230
|
}
|
|
12231
|
+
await awaitFontsBeforeTextReflow(templateConfig);
|
|
12004
12232
|
let resolvedConfig = applyFormDataToConfig(
|
|
12005
12233
|
templateConfig,
|
|
12006
12234
|
mappings,
|
|
@@ -12179,224 +12407,6 @@ function paintRepeatableSections(config, repeatableSections) {
|
|
|
12179
12407
|
}
|
|
12180
12408
|
}
|
|
12181
12409
|
}
|
|
12182
|
-
function normalizeFontFamily(fontStack) {
|
|
12183
|
-
const first = fontStack.split(",")[0].trim();
|
|
12184
|
-
return first.replace(/^['"]|['"]$/g, "");
|
|
12185
|
-
}
|
|
12186
|
-
const loadedFonts = /* @__PURE__ */ new Set();
|
|
12187
|
-
const loadingPromises = /* @__PURE__ */ new Map();
|
|
12188
|
-
function withTimeout(promise, timeoutMs = 4e3) {
|
|
12189
|
-
let timeoutId;
|
|
12190
|
-
return Promise.race([
|
|
12191
|
-
promise,
|
|
12192
|
-
new Promise((resolve) => {
|
|
12193
|
-
timeoutId = setTimeout(resolve, timeoutMs);
|
|
12194
|
-
})
|
|
12195
|
-
]).finally(() => {
|
|
12196
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
12197
|
-
});
|
|
12198
|
-
}
|
|
12199
|
-
async function loadGoogleFontCSS(rawFontFamily) {
|
|
12200
|
-
if (!rawFontFamily || typeof document === "undefined") return;
|
|
12201
|
-
const fontFamily = normalizeFontFamily(rawFontFamily);
|
|
12202
|
-
if (!fontFamily) return;
|
|
12203
|
-
if (loadedFonts.has(fontFamily)) return;
|
|
12204
|
-
const existing = loadingPromises.get(fontFamily);
|
|
12205
|
-
if (existing) return existing;
|
|
12206
|
-
const promise = (async () => {
|
|
12207
|
-
try {
|
|
12208
|
-
const encoded = encodeURIComponent(fontFamily);
|
|
12209
|
-
const url = `https://fonts.googleapis.com/css?family=${encoded}:300,400,500,600,700&display=swap`;
|
|
12210
|
-
const link = document.createElement("link");
|
|
12211
|
-
link.rel = "stylesheet";
|
|
12212
|
-
link.href = url;
|
|
12213
|
-
link.crossOrigin = "anonymous";
|
|
12214
|
-
await new Promise((resolve, reject) => {
|
|
12215
|
-
link.onload = () => resolve();
|
|
12216
|
-
link.onerror = () => reject(new Error(`Failed to load font: ${fontFamily}`));
|
|
12217
|
-
document.head.appendChild(link);
|
|
12218
|
-
});
|
|
12219
|
-
loadedFonts.add(fontFamily);
|
|
12220
|
-
} catch (e) {
|
|
12221
|
-
console.warn(`[@pixldocs/canvas-renderer] Font load failed: ${fontFamily}`, e);
|
|
12222
|
-
}
|
|
12223
|
-
})();
|
|
12224
|
-
loadingPromises.set(fontFamily, promise);
|
|
12225
|
-
await promise;
|
|
12226
|
-
loadingPromises.delete(fontFamily);
|
|
12227
|
-
}
|
|
12228
|
-
function collectFontsFromConfig(config) {
|
|
12229
|
-
var _a;
|
|
12230
|
-
const fonts = /* @__PURE__ */ new Set();
|
|
12231
|
-
fonts.add("Open Sans");
|
|
12232
|
-
fonts.add("Hind");
|
|
12233
|
-
function walk(nodes) {
|
|
12234
|
-
var _a2;
|
|
12235
|
-
if (!nodes) return;
|
|
12236
|
-
for (const node of nodes) {
|
|
12237
|
-
if (node.fontFamily) fonts.add(normalizeFontFamily(node.fontFamily));
|
|
12238
|
-
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) fonts.add(normalizeFontFamily(node.smartProps.fontFamily));
|
|
12239
|
-
if (node.styles && Array.isArray(node.styles)) {
|
|
12240
|
-
for (const lineStyle of node.styles) {
|
|
12241
|
-
if (lineStyle && typeof lineStyle === "object") {
|
|
12242
|
-
for (const charStyle of Object.values(lineStyle)) {
|
|
12243
|
-
if (charStyle == null ? void 0 : charStyle.fontFamily) fonts.add(normalizeFontFamily(charStyle.fontFamily));
|
|
12244
|
-
}
|
|
12245
|
-
}
|
|
12246
|
-
}
|
|
12247
|
-
}
|
|
12248
|
-
if (node.children) walk(node.children);
|
|
12249
|
-
}
|
|
12250
|
-
}
|
|
12251
|
-
for (const page of config.pages || []) {
|
|
12252
|
-
walk(page.children || []);
|
|
12253
|
-
}
|
|
12254
|
-
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
12255
|
-
for (const def of Object.values(config.themeConfig.variables)) {
|
|
12256
|
-
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
12257
|
-
if (def.label && /font/i.test(def.label)) {
|
|
12258
|
-
fonts.add(normalizeFontFamily(def.value));
|
|
12259
|
-
}
|
|
12260
|
-
}
|
|
12261
|
-
}
|
|
12262
|
-
}
|
|
12263
|
-
return fonts;
|
|
12264
|
-
}
|
|
12265
|
-
function collectFontDescriptorsFromConfig(config) {
|
|
12266
|
-
var _a;
|
|
12267
|
-
const seen = /* @__PURE__ */ new Set();
|
|
12268
|
-
const descriptors = [];
|
|
12269
|
-
function add(family, weight, style) {
|
|
12270
|
-
const f = normalizeFontFamily(family);
|
|
12271
|
-
if (!f) return;
|
|
12272
|
-
const w = weight ?? 400;
|
|
12273
|
-
const s = style ?? "normal";
|
|
12274
|
-
const key = `${f}|${w}|${s}`;
|
|
12275
|
-
if (seen.has(key)) return;
|
|
12276
|
-
seen.add(key);
|
|
12277
|
-
descriptors.push({ family: f, weight: w, style: s });
|
|
12278
|
-
}
|
|
12279
|
-
function walk(nodes) {
|
|
12280
|
-
var _a2;
|
|
12281
|
-
if (!nodes) return;
|
|
12282
|
-
for (const node of nodes) {
|
|
12283
|
-
if (node.fontFamily) {
|
|
12284
|
-
add(node.fontFamily, node.fontWeight, node.fontStyle);
|
|
12285
|
-
if (node.type === "text") {
|
|
12286
|
-
for (const w of [300, 400, 500, 600, 700]) {
|
|
12287
|
-
add(node.fontFamily, w, node.fontStyle);
|
|
12288
|
-
}
|
|
12289
|
-
}
|
|
12290
|
-
}
|
|
12291
|
-
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) {
|
|
12292
|
-
add(node.smartProps.fontFamily, node.smartProps.fontWeight, node.smartProps.fontStyle);
|
|
12293
|
-
}
|
|
12294
|
-
if (node.styles) {
|
|
12295
|
-
const styleEntries = Array.isArray(node.styles) ? node.styles : Object.values(node.styles);
|
|
12296
|
-
for (const lineStyle of styleEntries) {
|
|
12297
|
-
if (lineStyle && typeof lineStyle === "object") {
|
|
12298
|
-
for (const charStyle of Object.values(lineStyle)) {
|
|
12299
|
-
if (charStyle == null ? void 0 : charStyle.fontFamily) {
|
|
12300
|
-
add(charStyle.fontFamily, charStyle.fontWeight, charStyle.fontStyle);
|
|
12301
|
-
}
|
|
12302
|
-
}
|
|
12303
|
-
}
|
|
12304
|
-
}
|
|
12305
|
-
}
|
|
12306
|
-
if (node.children) walk(node.children);
|
|
12307
|
-
}
|
|
12308
|
-
}
|
|
12309
|
-
add("Open Sans", 400, "normal");
|
|
12310
|
-
add("Hind", 400, "normal");
|
|
12311
|
-
add("Hind", 700, "normal");
|
|
12312
|
-
for (const page of config.pages || []) {
|
|
12313
|
-
walk(page.children || []);
|
|
12314
|
-
}
|
|
12315
|
-
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
12316
|
-
for (const def of Object.values(config.themeConfig.variables)) {
|
|
12317
|
-
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
12318
|
-
if (def.label && /font/i.test(def.label)) {
|
|
12319
|
-
add(def.value);
|
|
12320
|
-
}
|
|
12321
|
-
}
|
|
12322
|
-
}
|
|
12323
|
-
}
|
|
12324
|
-
return descriptors;
|
|
12325
|
-
}
|
|
12326
|
-
async function ensureFontsForResolvedConfig(config) {
|
|
12327
|
-
if (typeof document === "undefined") return;
|
|
12328
|
-
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
12329
|
-
const families = new Set(descriptors.map((d) => d.family));
|
|
12330
|
-
await withTimeout(Promise.all([...families].map((f) => loadGoogleFontCSS(f))), 3500);
|
|
12331
|
-
if (document.fonts) {
|
|
12332
|
-
descriptors.forEach((d) => {
|
|
12333
|
-
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
12334
|
-
const weightStr = String(d.weight);
|
|
12335
|
-
const spec = `${stylePrefix}${weightStr} 16px "${d.family}"`;
|
|
12336
|
-
document.fonts.load(spec).catch(() => {
|
|
12337
|
-
});
|
|
12338
|
-
});
|
|
12339
|
-
}
|
|
12340
|
-
}
|
|
12341
|
-
function configHasAutoShrinkText$1(config) {
|
|
12342
|
-
var _a;
|
|
12343
|
-
if (!((_a = config == null ? void 0 : config.pages) == null ? void 0 : _a.length)) return false;
|
|
12344
|
-
const walk = (nodes) => {
|
|
12345
|
-
for (const node of nodes || []) {
|
|
12346
|
-
if (!node) continue;
|
|
12347
|
-
if (node.type === "text" && node.overflowPolicy === "auto-shrink") return true;
|
|
12348
|
-
if (Array.isArray(node.children) && node.children.length && walk(node.children)) return true;
|
|
12349
|
-
}
|
|
12350
|
-
return false;
|
|
12351
|
-
};
|
|
12352
|
-
for (const page of config.pages) {
|
|
12353
|
-
if (walk(page.children || [])) return true;
|
|
12354
|
-
}
|
|
12355
|
-
return false;
|
|
12356
|
-
}
|
|
12357
|
-
async function awaitFontsForConfig(config, maxWaitMs) {
|
|
12358
|
-
if (typeof document === "undefined" || !document.fonts) return;
|
|
12359
|
-
await ensureFontsForResolvedConfig(config);
|
|
12360
|
-
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
12361
|
-
if (descriptors.length === 0) return;
|
|
12362
|
-
const loads = Promise.all(
|
|
12363
|
-
descriptors.map((d) => {
|
|
12364
|
-
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
12365
|
-
const spec = `${stylePrefix}${d.weight} 16px "${d.family}"`;
|
|
12366
|
-
return document.fonts.load(spec).catch(() => []);
|
|
12367
|
-
})
|
|
12368
|
-
).then(() => void 0);
|
|
12369
|
-
await Promise.race([
|
|
12370
|
-
loads,
|
|
12371
|
-
new Promise((resolve) => setTimeout(resolve, maxWaitMs))
|
|
12372
|
-
]);
|
|
12373
|
-
await Promise.race([
|
|
12374
|
-
document.fonts.ready.catch(() => void 0).then(() => void 0),
|
|
12375
|
-
new Promise((r) => setTimeout(r, Math.min(500, maxWaitMs)))
|
|
12376
|
-
]);
|
|
12377
|
-
const checkSpecs = [];
|
|
12378
|
-
for (const d of descriptors) {
|
|
12379
|
-
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
12380
|
-
checkSpecs.push(`${stylePrefix}${d.weight} 16px "${d.family}"`);
|
|
12381
|
-
}
|
|
12382
|
-
const startedAt = Date.now();
|
|
12383
|
-
const pollBudget = Math.min(maxWaitMs, 2500);
|
|
12384
|
-
const allReady = () => {
|
|
12385
|
-
for (const spec of checkSpecs) {
|
|
12386
|
-
try {
|
|
12387
|
-
if (!document.fonts.check(spec)) return false;
|
|
12388
|
-
} catch {
|
|
12389
|
-
}
|
|
12390
|
-
}
|
|
12391
|
-
return true;
|
|
12392
|
-
};
|
|
12393
|
-
while (!allReady() && Date.now() - startedAt < pollBudget) {
|
|
12394
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
12395
|
-
}
|
|
12396
|
-
await new Promise(
|
|
12397
|
-
(resolve) => requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
|
|
12398
|
-
);
|
|
12399
|
-
}
|
|
12400
12410
|
const PREVIEW_DEBUG_PREFIX = "[canvas-renderer][preview-debug]";
|
|
12401
12411
|
function countUnderlinedNodes(config) {
|
|
12402
12412
|
var _a;
|
|
@@ -12587,7 +12597,7 @@ function PixldocsPreview(props) {
|
|
|
12587
12597
|
!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..." }) })
|
|
12588
12598
|
] });
|
|
12589
12599
|
}
|
|
12590
|
-
const PACKAGE_VERSION = "0.5.
|
|
12600
|
+
const PACKAGE_VERSION = "0.5.79";
|
|
12591
12601
|
const roundParityValue = (value) => {
|
|
12592
12602
|
if (typeof value !== "number") return value;
|
|
12593
12603
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -15497,6 +15507,25 @@ async function convertTextDecorationsToLines(svg) {
|
|
|
15497
15507
|
}
|
|
15498
15508
|
}
|
|
15499
15509
|
}
|
|
15510
|
+
async function convertSvgTextDecorationsToLinesString(svgStr) {
|
|
15511
|
+
if (typeof DOMParser === "undefined" || typeof XMLSerializer === "undefined") {
|
|
15512
|
+
return svgStr;
|
|
15513
|
+
}
|
|
15514
|
+
if (!/text-decoration/i.test(svgStr) && !/underline/i.test(svgStr)) {
|
|
15515
|
+
return svgStr;
|
|
15516
|
+
}
|
|
15517
|
+
try {
|
|
15518
|
+
const parser = new DOMParser();
|
|
15519
|
+
const docEl = parser.parseFromString(svgStr, "image/svg+xml");
|
|
15520
|
+
const rootSvg = docEl.documentElement;
|
|
15521
|
+
if (!rootSvg) return svgStr;
|
|
15522
|
+
await convertTextDecorationsToLines(rootSvg);
|
|
15523
|
+
const serializer = new XMLSerializer();
|
|
15524
|
+
return serializer.serializeToString(rootSvg);
|
|
15525
|
+
} catch {
|
|
15526
|
+
return svgStr;
|
|
15527
|
+
}
|
|
15528
|
+
}
|
|
15500
15529
|
async function rasterizeShadowMarkers(svg) {
|
|
15501
15530
|
var _a, _b, _c, _d, _e;
|
|
15502
15531
|
if (typeof window === "undefined" || typeof document === "undefined") return;
|
|
@@ -15765,6 +15794,14 @@ async function assemblePdfFromSvgs(svgResults, options = {}) {
|
|
|
15765
15794
|
const shouldStripBg = stripPageBackground ?? hasGradient;
|
|
15766
15795
|
const shouldOutlineText = options.outlineText !== false;
|
|
15767
15796
|
let pageSvg = page.svg;
|
|
15797
|
+
try {
|
|
15798
|
+
pageSvg = await convertSvgTextDecorationsToLinesString(pageSvg);
|
|
15799
|
+
} catch (underlineErr) {
|
|
15800
|
+
console.warn(
|
|
15801
|
+
"[canvas-renderer][pdf] underline-to-line conversion failed (raw stage):",
|
|
15802
|
+
underlineErr
|
|
15803
|
+
);
|
|
15804
|
+
}
|
|
15768
15805
|
if (shouldOutlineText) {
|
|
15769
15806
|
try {
|
|
15770
15807
|
const { convertAllTextToPath } = await Promise.resolve().then(() => require("./svgTextToPath-BTHnqJpM.cjs"));
|