@pixldocs/canvas-renderer 0.5.96 → 0.5.98
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 +173 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +173 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -13103,7 +13103,7 @@ function PixldocsPreview(props) {
|
|
|
13103
13103
|
!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..." }) })
|
|
13104
13104
|
] });
|
|
13105
13105
|
}
|
|
13106
|
-
const PACKAGE_VERSION = "0.5.
|
|
13106
|
+
const PACKAGE_VERSION = "0.5.98";
|
|
13107
13107
|
const roundParityValue = (value) => {
|
|
13108
13108
|
if (typeof value !== "number") return value;
|
|
13109
13109
|
return Number.isFinite(value) ? Number(value.toFixed(3)) : value;
|
|
@@ -14064,6 +14064,7 @@ class PixldocsRenderer {
|
|
|
14064
14064
|
this.logFabricTextParitySnapshot("after-stable-text-metrics", fabricInstance);
|
|
14065
14065
|
}
|
|
14066
14066
|
}
|
|
14067
|
+
const __vite_import_meta_env__ = {};
|
|
14067
14068
|
const FONT_WEIGHT_LABELS = {
|
|
14068
14069
|
300: "Light",
|
|
14069
14070
|
400: "Regular",
|
|
@@ -14600,6 +14601,10 @@ function getEmbeddedJsPDFFontName(fontName, weight, isItalic = false) {
|
|
|
14600
14601
|
function isFontAvailable(fontName) {
|
|
14601
14602
|
return fontName in FONT_FILES;
|
|
14602
14603
|
}
|
|
14604
|
+
const registeredFamilies = /* @__PURE__ */ new Set();
|
|
14605
|
+
function isFamilyEmbedded(family) {
|
|
14606
|
+
return registeredFamilies.has(family);
|
|
14607
|
+
}
|
|
14603
14608
|
const ttfCache = /* @__PURE__ */ new Map();
|
|
14604
14609
|
async function fetchTTFAsBase64(url) {
|
|
14605
14610
|
const cached = ttfCache.get(url);
|
|
@@ -14672,12 +14677,165 @@ async function embedFont(pdf, fontName, weight, fontBaseUrl, isItalic = false) {
|
|
|
14672
14677
|
} catch {
|
|
14673
14678
|
}
|
|
14674
14679
|
}
|
|
14680
|
+
registeredFamilies.add(fontName);
|
|
14675
14681
|
return true;
|
|
14676
14682
|
} catch (e) {
|
|
14677
14683
|
console.warn(`[pdf-fonts] Failed to embed ${fontName} w${weight}:`, e);
|
|
14678
14684
|
return false;
|
|
14679
14685
|
}
|
|
14680
14686
|
}
|
|
14687
|
+
const googleFontNotFound = /* @__PURE__ */ new Set();
|
|
14688
|
+
const fontshareNotFound = /* @__PURE__ */ new Set();
|
|
14689
|
+
function bytesToBase64(bytes) {
|
|
14690
|
+
let binary = "";
|
|
14691
|
+
for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
|
14692
|
+
return btoa(binary);
|
|
14693
|
+
}
|
|
14694
|
+
function getFontProxyUrl() {
|
|
14695
|
+
var _a;
|
|
14696
|
+
const viteUrl = (__vite_import_meta_env__ == null ? void 0 : __vite_import_meta_env__.VITE_SUPABASE_URL) || "";
|
|
14697
|
+
const runtimeUrl = typeof globalThis !== "undefined" ? ((_a = globalThis.__CONFIG__) == null ? void 0 : _a.supabaseUrl) || globalThis.__PIXLDOCS_SUPABASE_URL || "" : "";
|
|
14698
|
+
const baseUrl = (viteUrl || runtimeUrl || "").replace(/\/$/, "");
|
|
14699
|
+
return baseUrl ? `${baseUrl}/functions/v1/font-proxy` : null;
|
|
14700
|
+
}
|
|
14701
|
+
async function fetchTtfViaProxy(family, weight, isItalic, source) {
|
|
14702
|
+
const proxyUrl = getFontProxyUrl();
|
|
14703
|
+
if (!proxyUrl) return null;
|
|
14704
|
+
try {
|
|
14705
|
+
const url = `${proxyUrl}?family=${encodeURIComponent(family)}&weight=${weight}&italic=${isItalic ? 1 : 0}&source=${source}`;
|
|
14706
|
+
const res = await fetch(url);
|
|
14707
|
+
if (!res.ok) return null;
|
|
14708
|
+
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
14709
|
+
return isJsPdfEmbeddableTrueType(bytes) ? bytes : null;
|
|
14710
|
+
} catch {
|
|
14711
|
+
return null;
|
|
14712
|
+
}
|
|
14713
|
+
}
|
|
14714
|
+
async function fetchGoogleFontTTF(fontFamily, weight, isItalic = false) {
|
|
14715
|
+
const cacheKey = `gf:${fontFamily}:${weight}:${isItalic ? "i" : "n"}`;
|
|
14716
|
+
if (ttfCache.has(cacheKey)) return ttfCache.get(cacheKey);
|
|
14717
|
+
if (googleFontNotFound.has(fontFamily)) return null;
|
|
14718
|
+
const proxyBytes = await fetchTtfViaProxy(fontFamily, weight, isItalic, "google");
|
|
14719
|
+
if (proxyBytes) {
|
|
14720
|
+
const b64 = bytesToBase64(proxyBytes);
|
|
14721
|
+
ttfCache.set(cacheKey, b64);
|
|
14722
|
+
return b64;
|
|
14723
|
+
}
|
|
14724
|
+
try {
|
|
14725
|
+
const ital = isItalic ? "1" : "0";
|
|
14726
|
+
const cssUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(
|
|
14727
|
+
fontFamily
|
|
14728
|
+
)}:ital,wght@${ital},${weight}&display=swap`;
|
|
14729
|
+
const cssRes = await fetch(cssUrl, {
|
|
14730
|
+
headers: {
|
|
14731
|
+
"User-Agent": "Mozilla/5.0 (Linux; U; Android 2.2; en-us) AppleWebKit/533.1 (KHTML, like Gecko)"
|
|
14732
|
+
}
|
|
14733
|
+
});
|
|
14734
|
+
if (!cssRes.ok) {
|
|
14735
|
+
if (cssRes.status === 400 || cssRes.status === 404) googleFontNotFound.add(fontFamily);
|
|
14736
|
+
return null;
|
|
14737
|
+
}
|
|
14738
|
+
const css = await cssRes.text();
|
|
14739
|
+
const urlMatch = css.match(/url\(([^)]+)\)\s+format\(['"]?truetype['"]?\)/i) || css.match(/url\(([^)]+)\)/);
|
|
14740
|
+
if (!urlMatch) return null;
|
|
14741
|
+
const ttfUrl = urlMatch[1].replace(/['"]/g, "");
|
|
14742
|
+
const ttfRes = await fetch(ttfUrl);
|
|
14743
|
+
if (!ttfRes.ok) return null;
|
|
14744
|
+
const buf = await ttfRes.arrayBuffer();
|
|
14745
|
+
const bytes = new Uint8Array(buf);
|
|
14746
|
+
if (!isJsPdfEmbeddableTrueType(bytes)) {
|
|
14747
|
+
console.warn(`[pdf-fonts] Google Fonts returned a non-TTF for ${fontFamily} (${weight}); skipping`);
|
|
14748
|
+
return null;
|
|
14749
|
+
}
|
|
14750
|
+
const b64 = bytesToBase64(bytes);
|
|
14751
|
+
ttfCache.set(cacheKey, b64);
|
|
14752
|
+
return b64;
|
|
14753
|
+
} catch (err) {
|
|
14754
|
+
console.warn(`[pdf-fonts] fetchGoogleFontTTF failed for ${fontFamily} (${weight}):`, err);
|
|
14755
|
+
return null;
|
|
14756
|
+
}
|
|
14757
|
+
}
|
|
14758
|
+
async function fetchFontshareTTF(fontFamily, weight, isItalic = false) {
|
|
14759
|
+
const cacheKey = `fs:${fontFamily}:${weight}:${isItalic ? "i" : "n"}`;
|
|
14760
|
+
if (ttfCache.has(cacheKey)) return ttfCache.get(cacheKey);
|
|
14761
|
+
if (fontshareNotFound.has(fontFamily)) return null;
|
|
14762
|
+
const slug = fontFamily.trim().toLowerCase().replace(/\s+/g, "-");
|
|
14763
|
+
const proxyBytes = await fetchTtfViaProxy(fontFamily, weight, isItalic, "fontshare");
|
|
14764
|
+
if (proxyBytes) {
|
|
14765
|
+
const b64 = bytesToBase64(proxyBytes);
|
|
14766
|
+
ttfCache.set(cacheKey, b64);
|
|
14767
|
+
return b64;
|
|
14768
|
+
}
|
|
14769
|
+
try {
|
|
14770
|
+
const styleSuffix = isItalic ? "i" : "";
|
|
14771
|
+
const cssUrl = `https://api.fontshare.com/v2/css?f[]=${slug}@${weight}${styleSuffix}&display=swap`;
|
|
14772
|
+
const cssRes = await fetch(cssUrl);
|
|
14773
|
+
if (!cssRes.ok) {
|
|
14774
|
+
if (cssRes.status === 400 || cssRes.status === 404) fontshareNotFound.add(fontFamily);
|
|
14775
|
+
return null;
|
|
14776
|
+
}
|
|
14777
|
+
const css = await cssRes.text();
|
|
14778
|
+
const ttMatch = css.match(/url\(([^)]+)\)\s+format\(['"]?truetype['"]?\)/i);
|
|
14779
|
+
if (!ttMatch) {
|
|
14780
|
+
fontshareNotFound.add(fontFamily);
|
|
14781
|
+
return null;
|
|
14782
|
+
}
|
|
14783
|
+
let ttfUrl = ttMatch[1].replace(/['"]/g, "").trim();
|
|
14784
|
+
if (ttfUrl.startsWith("//")) ttfUrl = `https:${ttfUrl}`;
|
|
14785
|
+
const ttfRes = await fetch(ttfUrl);
|
|
14786
|
+
if (!ttfRes.ok) return null;
|
|
14787
|
+
const buf = await ttfRes.arrayBuffer();
|
|
14788
|
+
const bytes = new Uint8Array(buf);
|
|
14789
|
+
if (!isJsPdfEmbeddableTrueType(bytes)) return null;
|
|
14790
|
+
const b64 = bytesToBase64(bytes);
|
|
14791
|
+
ttfCache.set(cacheKey, b64);
|
|
14792
|
+
return b64;
|
|
14793
|
+
} catch (err) {
|
|
14794
|
+
console.warn(`[pdf-fonts] fetchFontshareTTF failed for ${fontFamily} (${weight}):`, err);
|
|
14795
|
+
return null;
|
|
14796
|
+
}
|
|
14797
|
+
}
|
|
14798
|
+
function registerJsPdfFont(pdf, fontName, resolvedWeight, isItalic, base64) {
|
|
14799
|
+
const label = FONT_WEIGHT_LABELS[resolvedWeight];
|
|
14800
|
+
const italicSuffix = isItalic ? "Italic" : "";
|
|
14801
|
+
const jsPdfFontName = getEmbeddedJsPDFFontName(fontName, resolvedWeight, isItalic);
|
|
14802
|
+
const fileName = `${getJsPDFFontName(fontName)}-${label}${italicSuffix}.ttf`;
|
|
14803
|
+
try {
|
|
14804
|
+
pdf.addFileToVFS(fileName, base64);
|
|
14805
|
+
pdf.addFont(fileName, jsPdfFontName, "normal");
|
|
14806
|
+
if (fontName !== jsPdfFontName) {
|
|
14807
|
+
try {
|
|
14808
|
+
pdf.addFont(fileName, fontName, "normal");
|
|
14809
|
+
} catch {
|
|
14810
|
+
}
|
|
14811
|
+
}
|
|
14812
|
+
registeredFamilies.add(fontName);
|
|
14813
|
+
return true;
|
|
14814
|
+
} catch (err) {
|
|
14815
|
+
console.warn(`[pdf-fonts] registerJsPdfFont failed for ${fontName}:`, err);
|
|
14816
|
+
return false;
|
|
14817
|
+
}
|
|
14818
|
+
}
|
|
14819
|
+
async function embedFontWithGoogleFallback(pdf, fontName, weight = 400, fontBaseUrl, isItalic = false) {
|
|
14820
|
+
if (FONT_FILES[fontName]) {
|
|
14821
|
+
const ok = await embedFont(pdf, fontName, weight, fontBaseUrl, isItalic);
|
|
14822
|
+
if (ok) return true;
|
|
14823
|
+
}
|
|
14824
|
+
const resolved = resolveFontWeight(weight);
|
|
14825
|
+
const fsB64 = await fetchFontshareTTF(fontName, resolved, isItalic);
|
|
14826
|
+
if (fsB64) return registerJsPdfFont(pdf, fontName, resolved, isItalic, fsB64);
|
|
14827
|
+
if (isItalic) {
|
|
14828
|
+
const fsUpright = await fetchFontshareTTF(fontName, resolved, false);
|
|
14829
|
+
if (fsUpright) return registerJsPdfFont(pdf, fontName, resolved, isItalic, fsUpright);
|
|
14830
|
+
}
|
|
14831
|
+
const b64 = await fetchGoogleFontTTF(fontName, resolved, isItalic);
|
|
14832
|
+
if (b64) return registerJsPdfFont(pdf, fontName, resolved, isItalic, b64);
|
|
14833
|
+
if (isItalic) {
|
|
14834
|
+
const uprightB64 = await fetchGoogleFontTTF(fontName, resolved, false);
|
|
14835
|
+
if (uprightB64) return registerJsPdfFont(pdf, fontName, resolved, isItalic, uprightB64);
|
|
14836
|
+
}
|
|
14837
|
+
return false;
|
|
14838
|
+
}
|
|
14681
14839
|
async function embedFontsForConfig(pdf, config, fontBaseUrl) {
|
|
14682
14840
|
const fontKeys = /* @__PURE__ */ new Set();
|
|
14683
14841
|
const SEP = "";
|
|
@@ -14836,7 +14994,7 @@ function rewriteSvgFontsForJsPDF(svgStr) {
|
|
|
14836
14994
|
const rawFf = resolveInheritedValue(el, "font-family");
|
|
14837
14995
|
if (!rawFf) continue;
|
|
14838
14996
|
const clean = (_a = rawFf.split(",")[0]) == null ? void 0 : _a.replace(/['"]/g, "").trim();
|
|
14839
|
-
if (!isFontAvailable(clean)) continue;
|
|
14997
|
+
if (!isFontAvailable(clean) && !isFamilyEmbedded(clean)) continue;
|
|
14840
14998
|
const weightRaw = resolveInheritedValue(el, "font-weight") || "400";
|
|
14841
14999
|
const styleRaw = resolveInheritedValue(el, "font-style") || "normal";
|
|
14842
15000
|
const weight = resolveWeightNum(weightRaw);
|
|
@@ -14919,14 +15077,19 @@ async function embedFontsInPdf(pdf, fontFamilies, fontBaseUrl) {
|
|
|
14919
15077
|
fontFamilies.add(FONT_FALLBACK_SYMBOLS);
|
|
14920
15078
|
fontFamilies.add(FONT_FALLBACK_DEVANAGARI);
|
|
14921
15079
|
for (const family of fontFamilies) {
|
|
14922
|
-
if (
|
|
14923
|
-
|
|
14924
|
-
|
|
14925
|
-
|
|
14926
|
-
|
|
15080
|
+
if (isFontAvailable(family)) {
|
|
15081
|
+
for (const w of weights) {
|
|
15082
|
+
tasks.push(
|
|
15083
|
+
embedFont(pdf, family, w, fontBaseUrl).then((ok) => {
|
|
15084
|
+
if (ok) embedded.add(`${family}${w}`);
|
|
15085
|
+
})
|
|
15086
|
+
);
|
|
15087
|
+
}
|
|
15088
|
+
} else {
|
|
14927
15089
|
tasks.push(
|
|
14928
|
-
|
|
14929
|
-
if (ok) embedded.add(`${family}
|
|
15090
|
+
embedFontWithGoogleFallback(pdf, family, 400, fontBaseUrl, false).then((ok) => {
|
|
15091
|
+
if (ok) embedded.add(`${family}400`);
|
|
15092
|
+
else console.warn(`[pdf-fonts] No TTF (local/Google/Fontshare) for "${family}" — will use Helvetica fallback`);
|
|
14930
15093
|
})
|
|
14931
15094
|
);
|
|
14932
15095
|
}
|
|
@@ -14942,6 +15105,7 @@ const pdfFonts = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProp
|
|
|
14942
15105
|
FONT_FILES,
|
|
14943
15106
|
FONT_WEIGHT_LABELS,
|
|
14944
15107
|
embedFont,
|
|
15108
|
+
embedFontWithGoogleFallback,
|
|
14945
15109
|
embedFontsForConfig,
|
|
14946
15110
|
embedFontsInPdf,
|
|
14947
15111
|
extractFontFamiliesFromSvgs,
|