gaufre: better handle the marianne font subsetting

this should be easier to handle if the one doing it is not… me. Still
not that great but better than nothing!
This commit is contained in:
Emmanuel Pelletier
2025-02-27 14:51:31 +01:00
parent effa2c0ff1
commit 799a362f89
8 changed files with 93 additions and 31 deletions

View File

@@ -1 +1,2 @@
PUBLIC_LASUITE_API_URL=https://integration.lasuite.numerique.gouv.fr
PUBLIC_USE_GAUFRE_SUBSETTED_FONT=1

View File

@@ -39,3 +39,20 @@ Source images are not tracked in the repo. To build images, you must:
backgrounds in `public/api/backgrounds`. Depending on the offset passed, or the current week of
the month, the service gets a different background. This is meant to be run in a cronjob to
generate different backgrounds a few times a month.
### La Gaufre font
For the Gaufre content, we use a subset of Marianne font because we know we use just a few
characters for our list. This shrinks the font file size noticeably!
When you change the Gaufre content (the services shown), use the `npm run gaufre-glyphhanger-cmd`
helper. It will show you the [glyphhanger](https://github.com/zachleat/glyphhanger) command you need
to run locally to generate the new font file before pushing your changes.
:warning: It will also tell you what to do to update the code accordingly, don't miss it :)
If for any reason, you want the Gaufre to use a non-subsetted font, set the env var
`PUBLIC_USE_GAUFRE_SUBSETTED_FONT` to `0` on the machine building the website.
_This is not really streamlined and a bit error-prone, because Astro kinda gets in a way in that
specific case. Any contribution on this is welcome._

View File

@@ -0,0 +1,43 @@
import path from "path"
import { execSync } from "child_process"
import pc from "picocolors"
import services from "../src/data/services.json" with { type: "json" }
const glyphhangerIsInstalled = `glyphhanger --version`
try {
execSync(glyphhangerIsInstalled, { encoding: "utf8", stdio: ["pipe", "pipe", "pipe"] })
} catch (error) {
console.log(pc.yellow("Warning: it seems glyphhanger is not installed."))
console.log("Please see https://github.com/zachleat/glyphhanger for installation instructions.\n")
}
const enabledServices = services.filter((service) => service.enabled)
const originalFontPath = path.join(
import.meta.dirname,
"..",
"public",
"fonts",
"Marianne-Regular.woff2",
)
const outputDir = path.join(import.meta.dirname, "..", "public", "fonts")
const whitelist = [...enabledServices.map(({ name }) => name.replace(/ /g, "")), " ✕beta"].join("")
console.log(`Run this command to generate the new subsetted gaufre font:`)
console.log(`
glyphhanger --formats=woff2 \\
--subset="${originalFontPath}" \\
--whitelist="${Array.from(whitelist).join("")}" \\
--output="${outputDir}"`)
console.log(
pc.yellow(`
Warning: after running the glyphhanger command, don't forget to:
- update the unicode-range of the subsetted font-family in the GaufrePage.astro component. The new unicode-range is outputed in the console when running glyphhanger.
- rename the newly generated \`Marianne-Regular-subset.woff2\` file to add a cachebusting number, that is superior to the one in the previous filename already existing in the folder.
- update the subsetted font-face src url in the GaufrePage.astro component to use the newly named filename.
- delete the previously existing subsetted font file in the \`public/fonts\` directory.
- commit and push the changes.`),
)

View File

@@ -10,6 +10,7 @@
"dev": "astro dev",
"start": "node ./server.mjs",
"build-backgrounds": "node ./bin/build-services-backgrounds.mjs",
"gaufre-glyphhanger-cmd": "node ./bin/gaufre-font-cmd.mjs",
"build": "astro check && npm run build-backgrounds && astro build",
"preview": "astro preview",
"astro": "astro"

Binary file not shown.

View File

@@ -1,18 +0,0 @@
We use a subset of Marianne font because we know we use just a few characters for our list. This
shrinks the font file size noticeably!
Example command to use to generate the subset with glyphhanger:
```
glyphhanger \
--subset="./Marianne-Regular.woff2" \
--formats=woff2 \
--whitelist="DeskLaSuiteNumériqueMessagerieTchapResanaFranceTransfertContactsGristLePadWebConférencedel'ÉtatWebinaire  "
```
## ⚠
Make sure to also update the `unicode-range` on the `@font-face` CSS rule. You can get it on the
glyphhanger command output.
Assuming you have the Marianne-Regular.woff2 file (you can take it from the DSFR).

View File

@@ -8,6 +8,8 @@
import { Image } from "astro:assets"
const logos = import.meta.glob<{ default: ImageMetadata }>("/src/assets/logos/*.{svg,png,jpg}")
const { services } = Astro.props
const useSubsettedFont = import.meta.env.PUBLIC_USE_GAUFRE_SUBSETTED_FONT !== "0"
---
<!doctype html>
@@ -18,16 +20,27 @@ const { services } = Astro.props
</head>
<body>
<div class="lagaufre">
{useSubsettedFont ? (
<style is:inline>
@font-face {
font-family: "La Gaufre";
src: url("/fonts/Marianne-Regular-subset-1.woff2") format("woff2");
unicode-range: U+20,U+27-29,U+44,U+46,U+47,U+50,U+52-54,U+56,U+57,U+61-66,U+68,U+69,U+6C-70,U+72-76,U+C9,U+E9,U+2715;
font-weight: 400;
font-display: swap;
}
</style>
) : (
<style is:inline>
@font-face {
font-family: "La Gaufre";
src: url("/fonts/Marianne-Regular.woff2") format("woff2");
unicode-range: U+20, U+27, U+43, U+44, U+46, U+47, U+4E, U+50, U+52-54, U+56, U+57,
U+61-66, U+68, U+69, U+6C-70, U+72-76, U+A0, U+C9, U+E9, U+2715;
font-weight: 400;
font-display: swap;
}
</style>
)}
<style is:inline>
@font-face {
font-family: "La Gaufre fallback";
src: local("Arial");
@@ -51,8 +64,9 @@ const { services } = Astro.props
height: 100% !important;
width: 100% !important;
font-size: 100% !important;
font-family: "La Gaufre", "La Gaufre fallback", BlinkMacSystemFont, "Segoe UI",
"Noto Sans", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji" !important;
font-family:
"La Gaufre", "La Gaufre fallback", BlinkMacSystemFont, "Segoe UI", "Noto Sans",
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji" !important;
margin: 0 0 8px !important;
border: 2px solid var(--lagaufre-border-color) !important;
background-color: var(--lagaufre-bg-color) !important;
@@ -265,7 +279,7 @@ const { services } = Astro.props
logos[`/src/assets/logos/${id}.svg`] ||
logos[`/src/assets/logos/${id}.jpg`] ||
logos[`/src/assets/logos/${id}.png`]
const ariaLabel = `${name} ${!!beta ? '(bêta)' : ''} - nouvelle fenêtre`
const ariaLabel = `${name} ${!!beta ? "(bêta)" : ""} - nouvelle fenêtre`
return (
<li>
<div class="lagaufre-service lagaufre-enlarge-link">
@@ -273,7 +287,11 @@ const { services } = Astro.props
{!!logo ? (
<Image src={logo()} width="40" height="40" alt="" loading="eager" />
) : null}
{!!beta ? <span class="lagaufre-service__beta" aria-hidden="true">beta</span> : null}
{!!beta ? (
<span class="lagaufre-service__beta" aria-hidden="true">
beta
</span>
) : null}
</div>
<a
target="_blank"