@quartz-community/og-image 0.1.1 → 0.1.2
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/CHANGELOG.md +6 -0
- package/dist/index.js +171 -17
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- ab7b8e9: Fix build crash when Google Fonts is unreachable (fetch failed). Added error handling to font fetching, system font fallback for macOS/Linux/Windows, and graceful skip when no fonts are available.
|
|
8
|
+
|
|
3
9
|
All notable changes to this project will be documented in this file.
|
|
4
10
|
|
|
5
11
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
package/dist/index.js
CHANGED
|
@@ -23924,7 +23924,50 @@ async function getSatoriFonts(headerFont, bodyFont) {
|
|
|
23924
23924
|
...headerFonts.filter((font) => font !== null),
|
|
23925
23925
|
...bodyFonts.filter((font) => font !== null)
|
|
23926
23926
|
];
|
|
23927
|
-
|
|
23927
|
+
if (fonts.length > 0) {
|
|
23928
|
+
return fonts;
|
|
23929
|
+
}
|
|
23930
|
+
console.log(
|
|
23931
|
+
styleText(
|
|
23932
|
+
"yellow",
|
|
23933
|
+
`
|
|
23934
|
+
Warning: Could not fetch any Google Fonts. Attempting to use a system font as fallback for OG image generation.`
|
|
23935
|
+
)
|
|
23936
|
+
);
|
|
23937
|
+
const [regularFont, boldFont] = await Promise.all([loadSystemFont(false), loadSystemFont(true)]);
|
|
23938
|
+
const systemFonts = [];
|
|
23939
|
+
if (regularFont) {
|
|
23940
|
+
systemFonts.push({
|
|
23941
|
+
name: headerFontName,
|
|
23942
|
+
data: regularFont.data,
|
|
23943
|
+
weight: 400,
|
|
23944
|
+
style: "normal"
|
|
23945
|
+
});
|
|
23946
|
+
systemFonts.push({
|
|
23947
|
+
name: bodyFontName,
|
|
23948
|
+
data: regularFont.data,
|
|
23949
|
+
weight: 400,
|
|
23950
|
+
style: "normal"
|
|
23951
|
+
});
|
|
23952
|
+
}
|
|
23953
|
+
if (boldFont) {
|
|
23954
|
+
systemFonts.push({
|
|
23955
|
+
name: headerFontName,
|
|
23956
|
+
data: boldFont.data,
|
|
23957
|
+
weight: 700,
|
|
23958
|
+
style: "normal"
|
|
23959
|
+
});
|
|
23960
|
+
}
|
|
23961
|
+
if (systemFonts.length > 0) {
|
|
23962
|
+
const fontName = regularFont?.name ?? boldFont?.name;
|
|
23963
|
+
console.log(
|
|
23964
|
+
styleText(
|
|
23965
|
+
"yellow",
|
|
23966
|
+
`Warning: Using system font "${fontName}" as fallback. OG images may look different than intended.`
|
|
23967
|
+
)
|
|
23968
|
+
);
|
|
23969
|
+
}
|
|
23970
|
+
return systemFonts;
|
|
23928
23971
|
}
|
|
23929
23972
|
async function fetchTtf(rawFontName, weight) {
|
|
23930
23973
|
const fontName = rawFontName.replaceAll(" ", "+");
|
|
@@ -23936,31 +23979,127 @@ async function fetchTtf(rawFontName, weight) {
|
|
|
23936
23979
|
return fs.readFile(cachePath);
|
|
23937
23980
|
} catch {
|
|
23938
23981
|
}
|
|
23939
|
-
|
|
23940
|
-
`https://fonts.googleapis.com/css2?family=${fontName}:wght@${weight}
|
|
23941
|
-
|
|
23942
|
-
|
|
23943
|
-
|
|
23944
|
-
|
|
23945
|
-
|
|
23982
|
+
try {
|
|
23983
|
+
const cssUrl = `https://fonts.googleapis.com/css2?family=${fontName}:wght@${weight}`;
|
|
23984
|
+
const cssResponse = await fetch(cssUrl);
|
|
23985
|
+
if (!cssResponse.ok) {
|
|
23986
|
+
console.log(
|
|
23987
|
+
styleText(
|
|
23988
|
+
"yellow",
|
|
23989
|
+
`
|
|
23990
|
+
Warning: Google Fonts returned HTTP ${cssResponse.status} for ${rawFontName} (weight ${weight})`
|
|
23991
|
+
)
|
|
23992
|
+
);
|
|
23993
|
+
return;
|
|
23994
|
+
}
|
|
23995
|
+
const css = await cssResponse.text();
|
|
23996
|
+
const urlRegex = /url\((https:\/\/fonts.gstatic.com\/s\/.*?.ttf)\)/g;
|
|
23997
|
+
const match = urlRegex.exec(css);
|
|
23998
|
+
if (!match) {
|
|
23999
|
+
console.log(
|
|
24000
|
+
styleText(
|
|
24001
|
+
"yellow",
|
|
24002
|
+
`
|
|
24003
|
+
Warning: Could not extract font URL for ${rawFontName} (weight ${weight}) from Google Fonts CSS`
|
|
24004
|
+
)
|
|
24005
|
+
);
|
|
24006
|
+
return;
|
|
24007
|
+
}
|
|
24008
|
+
const fontUrl = match[1];
|
|
24009
|
+
if (!fontUrl) {
|
|
24010
|
+
return;
|
|
24011
|
+
}
|
|
24012
|
+
const fontResponse = await fetch(fontUrl);
|
|
24013
|
+
if (!fontResponse.ok) {
|
|
24014
|
+
console.log(
|
|
24015
|
+
styleText(
|
|
24016
|
+
"yellow",
|
|
24017
|
+
`
|
|
24018
|
+
Warning: Failed to download font file for ${rawFontName} (weight ${weight}): HTTP ${fontResponse.status}`
|
|
24019
|
+
)
|
|
24020
|
+
);
|
|
24021
|
+
return;
|
|
24022
|
+
}
|
|
24023
|
+
const fontData = Buffer.from(await fontResponse.arrayBuffer());
|
|
24024
|
+
await fs.mkdir(cacheDir, { recursive: true });
|
|
24025
|
+
await fs.writeFile(cachePath, fontData);
|
|
24026
|
+
return fontData;
|
|
24027
|
+
} catch (err2) {
|
|
24028
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
23946
24029
|
console.log(
|
|
23947
24030
|
styleText(
|
|
23948
24031
|
"yellow",
|
|
23949
24032
|
`
|
|
23950
|
-
Warning: Failed to fetch font ${rawFontName}
|
|
24033
|
+
Warning: Failed to fetch font "${rawFontName}" (weight ${weight}) from Google Fonts: ${message}`
|
|
23951
24034
|
)
|
|
23952
24035
|
);
|
|
23953
24036
|
return;
|
|
23954
24037
|
}
|
|
23955
|
-
|
|
23956
|
-
|
|
23957
|
-
|
|
24038
|
+
}
|
|
24039
|
+
var SYSTEM_FONT_CANDIDATES = {
|
|
24040
|
+
darwin: [
|
|
24041
|
+
// San Francisco (macOS 10.15+)
|
|
24042
|
+
"/System/Library/Fonts/SFNS.ttf",
|
|
24043
|
+
// Helvetica Neue
|
|
24044
|
+
"/System/Library/Fonts/HelveticaNeue.ttc",
|
|
24045
|
+
// Helvetica
|
|
24046
|
+
"/System/Library/Fonts/Helvetica.ttc",
|
|
24047
|
+
// Arial
|
|
24048
|
+
"/Library/Fonts/Arial.ttf",
|
|
24049
|
+
// Fallback: guaranteed present on every macOS
|
|
24050
|
+
"/System/Library/Fonts/Supplemental/Arial.ttf"
|
|
24051
|
+
],
|
|
24052
|
+
linux: [
|
|
24053
|
+
// DejaVu Sans — ubiquitous on most distros
|
|
24054
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
24055
|
+
// Liberation Sans (Red Hat / Fedora)
|
|
24056
|
+
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
|
|
24057
|
+
"/usr/share/fonts/liberation-sans/LiberationSans-Regular.ttf",
|
|
24058
|
+
// Noto Sans
|
|
24059
|
+
"/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf",
|
|
24060
|
+
"/usr/share/fonts/noto/NotoSans-Regular.ttf",
|
|
24061
|
+
// FreeSans
|
|
24062
|
+
"/usr/share/fonts/truetype/freefont/FreeSans.ttf"
|
|
24063
|
+
],
|
|
24064
|
+
win32: [
|
|
24065
|
+
"C:\\Windows\\Fonts\\arial.ttf",
|
|
24066
|
+
"C:\\Windows\\Fonts\\segoeui.ttf",
|
|
24067
|
+
"C:\\Windows\\Fonts\\calibri.ttf",
|
|
24068
|
+
"C:\\Windows\\Fonts\\verdana.ttf"
|
|
24069
|
+
]
|
|
24070
|
+
};
|
|
24071
|
+
var SYSTEM_FONT_CANDIDATES_BOLD = {
|
|
24072
|
+
darwin: [
|
|
24073
|
+
"/System/Library/Fonts/SFNS.ttf",
|
|
24074
|
+
"/Library/Fonts/Arial Bold.ttf",
|
|
24075
|
+
"/System/Library/Fonts/Supplemental/Arial Bold.ttf"
|
|
24076
|
+
],
|
|
24077
|
+
linux: [
|
|
24078
|
+
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
|
24079
|
+
"/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
|
|
24080
|
+
"/usr/share/fonts/liberation-sans/LiberationSans-Bold.ttf",
|
|
24081
|
+
"/usr/share/fonts/truetype/noto/NotoSans-Bold.ttf",
|
|
24082
|
+
"/usr/share/fonts/noto/NotoSans-Bold.ttf",
|
|
24083
|
+
"/usr/share/fonts/truetype/freefont/FreeSansBold.ttf"
|
|
24084
|
+
],
|
|
24085
|
+
win32: [
|
|
24086
|
+
"C:\\Windows\\Fonts\\arialbd.ttf",
|
|
24087
|
+
"C:\\Windows\\Fonts\\segoeuib.ttf",
|
|
24088
|
+
"C:\\Windows\\Fonts\\calibrib.ttf",
|
|
24089
|
+
"C:\\Windows\\Fonts\\verdanab.ttf"
|
|
24090
|
+
]
|
|
24091
|
+
};
|
|
24092
|
+
async function loadSystemFont(bold) {
|
|
24093
|
+
const candidates = bold ? SYSTEM_FONT_CANDIDATES_BOLD[process.platform] ?? [] : SYSTEM_FONT_CANDIDATES[process.platform] ?? [];
|
|
24094
|
+
for (const fontPath of candidates) {
|
|
24095
|
+
try {
|
|
24096
|
+
const data = await fs.readFile(fontPath);
|
|
24097
|
+
const name = path.basename(fontPath, path.extname(fontPath));
|
|
24098
|
+
return { data, name };
|
|
24099
|
+
} catch {
|
|
24100
|
+
}
|
|
23958
24101
|
}
|
|
23959
|
-
|
|
23960
|
-
const fontData = Buffer.from(await fontResponse.arrayBuffer());
|
|
23961
|
-
await fs.mkdir(cacheDir, { recursive: true });
|
|
23962
|
-
await fs.writeFile(cachePath, fontData);
|
|
23963
|
-
return fontData;
|
|
24102
|
+
return void 0;
|
|
23964
24103
|
}
|
|
23965
24104
|
var defaultImage = ({
|
|
23966
24105
|
cfg,
|
|
@@ -24272,6 +24411,18 @@ var CustomOgImages = (userOpts) => {
|
|
|
24272
24411
|
const headerFont = theme.typography.header;
|
|
24273
24412
|
const bodyFont = theme.typography.body;
|
|
24274
24413
|
const fonts = await getSatoriFonts(headerFont, bodyFont);
|
|
24414
|
+
if (fonts.length === 0) {
|
|
24415
|
+
console.log(
|
|
24416
|
+
styleText(
|
|
24417
|
+
"yellow",
|
|
24418
|
+
`
|
|
24419
|
+
Warning: Skipping OG image generation \u2014 no fonts available (Google Fonts unreachable and no system fonts found). To suppress this warning, disable the plugin in your config:
|
|
24420
|
+
- source: "@quartz-community/og-image"
|
|
24421
|
+
enabled: false`
|
|
24422
|
+
)
|
|
24423
|
+
);
|
|
24424
|
+
return;
|
|
24425
|
+
}
|
|
24275
24426
|
for (const [_tree, vfile] of content) {
|
|
24276
24427
|
const data = vfile.data;
|
|
24277
24428
|
if (data.frontmatter?.socialImage !== void 0) continue;
|
|
@@ -24284,6 +24435,9 @@ var CustomOgImages = (userOpts) => {
|
|
|
24284
24435
|
const headerFont = theme.typography.header;
|
|
24285
24436
|
const bodyFont = theme.typography.body;
|
|
24286
24437
|
const fonts = await getSatoriFonts(headerFont, bodyFont);
|
|
24438
|
+
if (fonts.length === 0) {
|
|
24439
|
+
return;
|
|
24440
|
+
}
|
|
24287
24441
|
for (const changeEvent of changeEvents) {
|
|
24288
24442
|
if (!changeEvent.file) continue;
|
|
24289
24443
|
const data = changeEvent.file.data;
|