Skip to content

Commit f31cfb0

Browse files
NetdocsCopilot
andcommitted
fix(social): don't crash when no font is available; ship a font in the image
The social-cards plugin failed the entire build inside the container with "SixLabors.Fonts.FontException: Cannot use the default value type instance to create a font". Two causes: 1. ResolveFontFamily()'s last-resort `SystemFonts.Families.FirstOrDefault()` returns a *default* FontFamily struct (not null) when no fonts are installed, so the `family is null` guard missed it and CreateFont threw. Now we detect the default and return null, so card generation is skipped with a warning instead of failing the build. 2. The minimal runtime-deps container has no fonts at all. Install fonts-dejavu-core + fontconfig in the image so social cards actually render (ResolveFontFamily already prefers "DejaVu Sans"). Also enable the social plugin on docs-site so the container path is exercised by the action self-test. Verified locally: docs-site build emits 34 social cards. Removes the temporary deploy-test workflow. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent e97155b commit f31cfb0

4 files changed

Lines changed: 24 additions & 40 deletions

File tree

.github/workflows/_tmp-deploy-test.yml

Lines changed: 0 additions & 36 deletions
This file was deleted.

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ RUN dotnet publish src/Netdocs.Cli -c Release -r linux-x64 --self-contained \
1212

1313
FROM mcr.microsoft.com/dotnet/runtime-deps:11.0-preview
1414
WORKDIR /site
15+
# Ship a font so the social-cards plugin can render text. The minimal runtime-deps
16+
# image has no fonts, which otherwise makes SixLabors.Fonts fail with
17+
# "Cannot use the default value type instance to create a font".
18+
RUN apt-get update \
19+
&& apt-get install -y --no-install-recommends fonts-dejavu-core fontconfig \
20+
&& rm -rf /var/lib/apt/lists/*
1521
COPY --from=build /app /opt/netdocs
1622
RUN ln -s /opt/netdocs/netdocs /usr/local/bin/netdocs
1723
EXPOSE 8000

docs-site/appsettings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@
112112
{ "name": "search", "options": { "lang": "en" } },
113113
{ "name": "tags", "options": { "export": true } },
114114
{ "name": "meta" },
115-
{ "name": "arithmatex" }
115+
{ "name": "arithmatex" },
116+
{ "name": "social" }
116117
],
117118

118119
"markdownExtensions": [

src/Netdocs.Plugins/SocialPlugin.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,25 @@ private Image<Rgba32> RenderCard(string title, string siteName, string descripti
119119
private static string Truncate(string s, int max) =>
120120
s.Length <= max ? s : s[..max].TrimEnd() + "…";
121121

122-
private static FontFamily? ResolveFontFamily()
122+
private FontFamily? ResolveFontFamily()
123123
{
124-
foreach (var name in new[] { "Open Sans", "Segoe UI", "Arial", "Helvetica", "DejaVu Sans", "Liberation Sans", "Noto Sans" })
124+
foreach (var name in new[] { "Open Sans", "Roboto", "Segoe UI", "Arial", "Helvetica", "DejaVu Sans", "Liberation Sans", "Noto Sans" })
125125
if (SystemFonts.TryGet(name, out var family))
126126
return family;
127-
return SystemFonts.Families.FirstOrDefault();
127+
128+
// SystemFonts.Families.FirstOrDefault() returns a *default* FontFamily struct
129+
// (not null) when no fonts are installed -- e.g. inside a minimal container.
130+
// Calling CreateFont on that default throws "Cannot use the default value type
131+
// instance to create a font" and fails the whole build. Only return a family
132+
// when one genuinely exists, so callers can skip card generation instead.
133+
var first = SystemFonts.Families.FirstOrDefault();
134+
if (first != default)
135+
{
136+
_log.LogInformation("social: using fallback system font '{Font}'", first.Name);
137+
return first;
138+
}
139+
140+
return null;
128141
}
129142

130143
private static Color PrimaryColor(string? name) => (name ?? "grey").ToLowerInvariant() switch

0 commit comments

Comments
 (0)