@pixldocs/canvas-renderer 0.3.12 → 0.3.14
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 +179 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +31 -0
- package/dist/index.js +179 -74
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -10388,6 +10388,165 @@ function paintRepeatableSections(config, repeatableSections) {
|
|
|
10388
10388
|
}
|
|
10389
10389
|
}
|
|
10390
10390
|
}
|
|
10391
|
+
function normalizeFontFamily(fontStack) {
|
|
10392
|
+
const first = fontStack.split(",")[0].trim();
|
|
10393
|
+
return first.replace(/^['"]|['"]$/g, "");
|
|
10394
|
+
}
|
|
10395
|
+
const loadedFonts = /* @__PURE__ */ new Set();
|
|
10396
|
+
const loadingPromises = /* @__PURE__ */ new Map();
|
|
10397
|
+
async function loadGoogleFontCSS(rawFontFamily) {
|
|
10398
|
+
if (!rawFontFamily || typeof document === "undefined") return;
|
|
10399
|
+
const fontFamily = normalizeFontFamily(rawFontFamily);
|
|
10400
|
+
if (!fontFamily) return;
|
|
10401
|
+
if (loadedFonts.has(fontFamily)) return;
|
|
10402
|
+
const existing = loadingPromises.get(fontFamily);
|
|
10403
|
+
if (existing) return existing;
|
|
10404
|
+
const promise = (async () => {
|
|
10405
|
+
var _a;
|
|
10406
|
+
try {
|
|
10407
|
+
if ((_a = document.fonts) == null ? void 0 : _a.check(`16px "${fontFamily}"`)) {
|
|
10408
|
+
loadedFonts.add(fontFamily);
|
|
10409
|
+
return;
|
|
10410
|
+
}
|
|
10411
|
+
const encoded = encodeURIComponent(fontFamily);
|
|
10412
|
+
const url = `https://fonts.googleapis.com/css?family=${encoded}:300,400,500,600,700&display=swap`;
|
|
10413
|
+
const link = document.createElement("link");
|
|
10414
|
+
link.rel = "stylesheet";
|
|
10415
|
+
link.href = url;
|
|
10416
|
+
link.crossOrigin = "anonymous";
|
|
10417
|
+
await new Promise((resolve, reject) => {
|
|
10418
|
+
link.onload = () => resolve();
|
|
10419
|
+
link.onerror = () => reject(new Error(`Failed to load font: ${fontFamily}`));
|
|
10420
|
+
document.head.appendChild(link);
|
|
10421
|
+
});
|
|
10422
|
+
if (document.fonts) {
|
|
10423
|
+
await document.fonts.load(`16px "${fontFamily}"`);
|
|
10424
|
+
await document.fonts.ready;
|
|
10425
|
+
}
|
|
10426
|
+
loadedFonts.add(fontFamily);
|
|
10427
|
+
} catch (e) {
|
|
10428
|
+
console.warn(`[@pixldocs/canvas-renderer] Font load failed: ${fontFamily}`, e);
|
|
10429
|
+
}
|
|
10430
|
+
})();
|
|
10431
|
+
loadingPromises.set(fontFamily, promise);
|
|
10432
|
+
await promise;
|
|
10433
|
+
loadingPromises.delete(fontFamily);
|
|
10434
|
+
}
|
|
10435
|
+
function collectFontsFromConfig(config) {
|
|
10436
|
+
var _a;
|
|
10437
|
+
const fonts = /* @__PURE__ */ new Set();
|
|
10438
|
+
fonts.add("Open Sans");
|
|
10439
|
+
fonts.add("Hind");
|
|
10440
|
+
function walk(nodes) {
|
|
10441
|
+
var _a2;
|
|
10442
|
+
if (!nodes) return;
|
|
10443
|
+
for (const node of nodes) {
|
|
10444
|
+
if (node.fontFamily) fonts.add(normalizeFontFamily(node.fontFamily));
|
|
10445
|
+
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) fonts.add(normalizeFontFamily(node.smartProps.fontFamily));
|
|
10446
|
+
if (node.styles && Array.isArray(node.styles)) {
|
|
10447
|
+
for (const lineStyle of node.styles) {
|
|
10448
|
+
if (lineStyle && typeof lineStyle === "object") {
|
|
10449
|
+
for (const charStyle of Object.values(lineStyle)) {
|
|
10450
|
+
if (charStyle == null ? void 0 : charStyle.fontFamily) fonts.add(normalizeFontFamily(charStyle.fontFamily));
|
|
10451
|
+
}
|
|
10452
|
+
}
|
|
10453
|
+
}
|
|
10454
|
+
}
|
|
10455
|
+
if (node.children) walk(node.children);
|
|
10456
|
+
}
|
|
10457
|
+
}
|
|
10458
|
+
for (const page of config.pages || []) {
|
|
10459
|
+
walk(page.children || []);
|
|
10460
|
+
}
|
|
10461
|
+
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
10462
|
+
for (const def of Object.values(config.themeConfig.variables)) {
|
|
10463
|
+
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
10464
|
+
if (def.label && /font/i.test(def.label)) {
|
|
10465
|
+
fonts.add(normalizeFontFamily(def.value));
|
|
10466
|
+
}
|
|
10467
|
+
}
|
|
10468
|
+
}
|
|
10469
|
+
}
|
|
10470
|
+
return fonts;
|
|
10471
|
+
}
|
|
10472
|
+
function collectFontDescriptorsFromConfig(config) {
|
|
10473
|
+
var _a;
|
|
10474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10475
|
+
const descriptors = [];
|
|
10476
|
+
function add(family, weight, style) {
|
|
10477
|
+
const f = normalizeFontFamily(family);
|
|
10478
|
+
if (!f) return;
|
|
10479
|
+
const w = weight ?? 400;
|
|
10480
|
+
const s = style ?? "normal";
|
|
10481
|
+
const key = `${f}|${w}|${s}`;
|
|
10482
|
+
if (seen.has(key)) return;
|
|
10483
|
+
seen.add(key);
|
|
10484
|
+
descriptors.push({ family: f, weight: w, style: s });
|
|
10485
|
+
}
|
|
10486
|
+
function walk(nodes) {
|
|
10487
|
+
var _a2;
|
|
10488
|
+
if (!nodes) return;
|
|
10489
|
+
for (const node of nodes) {
|
|
10490
|
+
if (node.fontFamily) {
|
|
10491
|
+
add(node.fontFamily, node.fontWeight, node.fontStyle);
|
|
10492
|
+
if (node.type === "text") {
|
|
10493
|
+
for (const w of [300, 400, 500, 600, 700]) {
|
|
10494
|
+
add(node.fontFamily, w, node.fontStyle);
|
|
10495
|
+
}
|
|
10496
|
+
}
|
|
10497
|
+
}
|
|
10498
|
+
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) {
|
|
10499
|
+
add(node.smartProps.fontFamily, node.smartProps.fontWeight, node.smartProps.fontStyle);
|
|
10500
|
+
}
|
|
10501
|
+
if (node.styles) {
|
|
10502
|
+
const styleEntries = Array.isArray(node.styles) ? node.styles : Object.values(node.styles);
|
|
10503
|
+
for (const lineStyle of styleEntries) {
|
|
10504
|
+
if (lineStyle && typeof lineStyle === "object") {
|
|
10505
|
+
for (const charStyle of Object.values(lineStyle)) {
|
|
10506
|
+
if (charStyle == null ? void 0 : charStyle.fontFamily) {
|
|
10507
|
+
add(charStyle.fontFamily, charStyle.fontWeight, charStyle.fontStyle);
|
|
10508
|
+
}
|
|
10509
|
+
}
|
|
10510
|
+
}
|
|
10511
|
+
}
|
|
10512
|
+
}
|
|
10513
|
+
if (node.children) walk(node.children);
|
|
10514
|
+
}
|
|
10515
|
+
}
|
|
10516
|
+
add("Open Sans", 400, "normal");
|
|
10517
|
+
add("Hind", 400, "normal");
|
|
10518
|
+
add("Hind", 700, "normal");
|
|
10519
|
+
for (const page of config.pages || []) {
|
|
10520
|
+
walk(page.children || []);
|
|
10521
|
+
}
|
|
10522
|
+
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
10523
|
+
for (const def of Object.values(config.themeConfig.variables)) {
|
|
10524
|
+
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
10525
|
+
if (def.label && /font/i.test(def.label)) {
|
|
10526
|
+
add(def.value);
|
|
10527
|
+
}
|
|
10528
|
+
}
|
|
10529
|
+
}
|
|
10530
|
+
}
|
|
10531
|
+
return descriptors;
|
|
10532
|
+
}
|
|
10533
|
+
async function ensureFontsForResolvedConfig(config) {
|
|
10534
|
+
if (typeof document === "undefined") return;
|
|
10535
|
+
const descriptors = collectFontDescriptorsFromConfig(config);
|
|
10536
|
+
const families = new Set(descriptors.map((d) => d.family));
|
|
10537
|
+
await Promise.all([...families].map((f) => loadGoogleFontCSS(f)));
|
|
10538
|
+
if (document.fonts) {
|
|
10539
|
+
const loadPromises = descriptors.map((d) => {
|
|
10540
|
+
const stylePrefix = d.style === "italic" ? "italic " : "";
|
|
10541
|
+
const weightStr = String(d.weight);
|
|
10542
|
+
const spec = `${stylePrefix}${weightStr} 16px "${d.family}"`;
|
|
10543
|
+
return document.fonts.load(spec).catch(() => {
|
|
10544
|
+
});
|
|
10545
|
+
});
|
|
10546
|
+
await Promise.all(loadPromises);
|
|
10547
|
+
await document.fonts.ready;
|
|
10548
|
+
}
|
|
10549
|
+
}
|
|
10391
10550
|
function PixldocsPreview(props) {
|
|
10392
10551
|
const {
|
|
10393
10552
|
pageIndex = 0,
|
|
@@ -10405,6 +10564,7 @@ function PixldocsPreview(props) {
|
|
|
10405
10564
|
}, [imageProxyUrl]);
|
|
10406
10565
|
const [resolvedConfig, setResolvedConfig] = react.useState(null);
|
|
10407
10566
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
10567
|
+
const [fontsReady, setFontsReady] = react.useState(false);
|
|
10408
10568
|
const isResolveMode = !("config" in props && props.config);
|
|
10409
10569
|
react.useEffect(() => {
|
|
10410
10570
|
if (!isResolveMode) {
|
|
@@ -10425,7 +10585,17 @@ function PixldocsPreview(props) {
|
|
|
10425
10585
|
}).then((resolved) => {
|
|
10426
10586
|
if (!cancelled) {
|
|
10427
10587
|
setResolvedConfig(resolved.config);
|
|
10428
|
-
|
|
10588
|
+
ensureFontsForResolvedConfig(resolved.config).then(() => {
|
|
10589
|
+
if (!cancelled) {
|
|
10590
|
+
setFontsReady(true);
|
|
10591
|
+
setIsLoading(false);
|
|
10592
|
+
}
|
|
10593
|
+
}).catch(() => {
|
|
10594
|
+
if (!cancelled) {
|
|
10595
|
+
setFontsReady(true);
|
|
10596
|
+
setIsLoading(false);
|
|
10597
|
+
}
|
|
10598
|
+
});
|
|
10429
10599
|
}
|
|
10430
10600
|
}).catch((err) => {
|
|
10431
10601
|
if (!cancelled) {
|
|
@@ -10445,6 +10615,11 @@ function PixldocsPreview(props) {
|
|
|
10445
10615
|
isResolveMode ? props.themeId : void 0
|
|
10446
10616
|
]);
|
|
10447
10617
|
const config = isResolveMode ? resolvedConfig : props.config;
|
|
10618
|
+
react.useEffect(() => {
|
|
10619
|
+
if (isResolveMode || !config) return;
|
|
10620
|
+
setFontsReady(false);
|
|
10621
|
+
ensureFontsForResolvedConfig(config).then(() => setFontsReady(true)).catch(() => setFontsReady(true));
|
|
10622
|
+
}, [isResolveMode, config]);
|
|
10448
10623
|
if (isLoading) {
|
|
10449
10624
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style: { ...style, display: "flex", alignItems: "center", justifyContent: "center", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 14 }, children: "Loading preview..." }) });
|
|
10450
10625
|
}
|
|
@@ -10461,77 +10636,6 @@ function PixldocsPreview(props) {
|
|
|
10461
10636
|
}
|
|
10462
10637
|
) });
|
|
10463
10638
|
}
|
|
10464
|
-
function normalizeFontFamily(fontStack) {
|
|
10465
|
-
const first = fontStack.split(",")[0].trim();
|
|
10466
|
-
return first.replace(/^['"]|['"]$/g, "");
|
|
10467
|
-
}
|
|
10468
|
-
const loadedFonts = /* @__PURE__ */ new Set();
|
|
10469
|
-
const loadingPromises = /* @__PURE__ */ new Map();
|
|
10470
|
-
async function loadGoogleFontCSS(rawFontFamily) {
|
|
10471
|
-
if (!rawFontFamily || typeof document === "undefined") return;
|
|
10472
|
-
const fontFamily = normalizeFontFamily(rawFontFamily);
|
|
10473
|
-
if (!fontFamily) return;
|
|
10474
|
-
if (loadedFonts.has(fontFamily)) return;
|
|
10475
|
-
const existing = loadingPromises.get(fontFamily);
|
|
10476
|
-
if (existing) return existing;
|
|
10477
|
-
const promise = (async () => {
|
|
10478
|
-
var _a;
|
|
10479
|
-
try {
|
|
10480
|
-
if ((_a = document.fonts) == null ? void 0 : _a.check(`16px "${fontFamily}"`)) {
|
|
10481
|
-
loadedFonts.add(fontFamily);
|
|
10482
|
-
return;
|
|
10483
|
-
}
|
|
10484
|
-
const encoded = encodeURIComponent(fontFamily);
|
|
10485
|
-
const url = `https://fonts.googleapis.com/css?family=${encoded}:300,400,500,600,700&display=swap`;
|
|
10486
|
-
const link = document.createElement("link");
|
|
10487
|
-
link.rel = "stylesheet";
|
|
10488
|
-
link.href = url;
|
|
10489
|
-
link.crossOrigin = "anonymous";
|
|
10490
|
-
await new Promise((resolve, reject) => {
|
|
10491
|
-
link.onload = () => resolve();
|
|
10492
|
-
link.onerror = () => reject(new Error(`Failed to load font: ${fontFamily}`));
|
|
10493
|
-
document.head.appendChild(link);
|
|
10494
|
-
});
|
|
10495
|
-
if (document.fonts) {
|
|
10496
|
-
await document.fonts.load(`16px "${fontFamily}"`);
|
|
10497
|
-
await document.fonts.ready;
|
|
10498
|
-
}
|
|
10499
|
-
loadedFonts.add(fontFamily);
|
|
10500
|
-
} catch (e) {
|
|
10501
|
-
console.warn(`[@pixldocs/canvas-renderer] Font load failed: ${fontFamily}`, e);
|
|
10502
|
-
}
|
|
10503
|
-
})();
|
|
10504
|
-
loadingPromises.set(fontFamily, promise);
|
|
10505
|
-
await promise;
|
|
10506
|
-
loadingPromises.delete(fontFamily);
|
|
10507
|
-
}
|
|
10508
|
-
function collectFontsFromConfig(config) {
|
|
10509
|
-
var _a;
|
|
10510
|
-
const fonts = /* @__PURE__ */ new Set();
|
|
10511
|
-
fonts.add("Open Sans");
|
|
10512
|
-
function walk(nodes) {
|
|
10513
|
-
var _a2;
|
|
10514
|
-
if (!nodes) return;
|
|
10515
|
-
for (const node of nodes) {
|
|
10516
|
-
if (node.fontFamily) fonts.add(normalizeFontFamily(node.fontFamily));
|
|
10517
|
-
if ((_a2 = node.smartProps) == null ? void 0 : _a2.fontFamily) fonts.add(normalizeFontFamily(node.smartProps.fontFamily));
|
|
10518
|
-
if (node.children) walk(node.children);
|
|
10519
|
-
}
|
|
10520
|
-
}
|
|
10521
|
-
for (const page of config.pages || []) {
|
|
10522
|
-
walk(page.children || []);
|
|
10523
|
-
}
|
|
10524
|
-
if ((_a = config.themeConfig) == null ? void 0 : _a.variables) {
|
|
10525
|
-
for (const def of Object.values(config.themeConfig.variables)) {
|
|
10526
|
-
if (def.value && typeof def.value === "string" && !def.value.startsWith("#") && !def.value.startsWith("rgb")) {
|
|
10527
|
-
if (def.label && /font/i.test(def.label)) {
|
|
10528
|
-
fonts.add(normalizeFontFamily(def.value));
|
|
10529
|
-
}
|
|
10530
|
-
}
|
|
10531
|
-
}
|
|
10532
|
-
}
|
|
10533
|
-
return fonts;
|
|
10534
|
-
}
|
|
10535
10639
|
class PixldocsRenderer {
|
|
10536
10640
|
constructor(config) {
|
|
10537
10641
|
__publicField(this, "config");
|
|
@@ -10552,8 +10656,7 @@ class PixldocsRenderer {
|
|
|
10552
10656
|
if (!page) {
|
|
10553
10657
|
throw new Error(`Page index ${pageIndex} not found (template has ${templateConfig.pages.length} pages)`);
|
|
10554
10658
|
}
|
|
10555
|
-
|
|
10556
|
-
await Promise.all([...fonts].map((f) => loadGoogleFontCSS(f)));
|
|
10659
|
+
await ensureFontsForResolvedConfig(templateConfig);
|
|
10557
10660
|
const { setPackageApiUrl: setPackageApiUrl2 } = await Promise.resolve().then(() => appApi);
|
|
10558
10661
|
setPackageApiUrl2(this.config.imageProxyUrl);
|
|
10559
10662
|
const dataUrl = await this.renderPageViaPreviewCanvas(
|
|
@@ -10780,7 +10883,9 @@ class PixldocsRenderer {
|
|
|
10780
10883
|
exports.PixldocsPreview = PixldocsPreview;
|
|
10781
10884
|
exports.PixldocsRenderer = PixldocsRenderer;
|
|
10782
10885
|
exports.applyThemeToConfig = applyThemeToConfig;
|
|
10886
|
+
exports.collectFontDescriptorsFromConfig = collectFontDescriptorsFromConfig;
|
|
10783
10887
|
exports.collectFontsFromConfig = collectFontsFromConfig;
|
|
10888
|
+
exports.ensureFontsForResolvedConfig = ensureFontsForResolvedConfig;
|
|
10784
10889
|
exports.loadGoogleFontCSS = loadGoogleFontCSS;
|
|
10785
10890
|
exports.normalizeFontFamily = normalizeFontFamily;
|
|
10786
10891
|
exports.resolveFromForm = resolveFromForm;
|