Added font preload links to the Page+Defaults extension in the Website library target.

This commit is contained in:
2026-08-25 17:05:08 +02:00
parent 7aee1cd949
commit c09ac657ab
3 changed files with 48 additions and 2 deletions
@@ -6,6 +6,16 @@ import Localization
/// The site-wide defaults shared by every page of the website.
extension Page {
// MARK: Constants
/// The fonts preloaded on every page: one per face the stylesheets actually render.
///
/// Listed rather than derived from every WOFF2 in ``StaticFile/all``: a subset gated by a `unicode-range` no page reaches would add a
/// download that never otherwise happens. Empty until the site ships fonts of its own.
static var preloadedFonts: [StaticFile] {
[]
}
// MARK: Computed
/// The document language, derived from the page's locale and falling back to the default language.
@@ -14,9 +24,29 @@ extension Page {
?? LanguageList().default
}
/// The icon, manifest, and theme colour metadata shared by every page of the website.
@HTMLBuilder
/// The site-wide head metadata; a page that adds tags of its own composes ``siteMetadata`` rather than replacing it.
var metadata: some HTML {
siteMetadata
}
/// The ``preloadedFonts`` links, then the icon, manifest, and theme colour metadata shared by every page of the website.
///
/// A preload URL must match the stylesheet's `@font-face` source exactly unversioned, with `crossorigin` or the browser fetches the
/// font twice.
@HTMLBuilder
var siteMetadata: some HTML {
for file in Self.preloadedFonts {
link(
.rel("preload"),
.href(file.urlPath(for: .woff2)),
.as(.font),
.custom(
name: "type",
value: AssetExtension.woff2.contentType
),
.crossorigin(.anonymous)
)
}
link(
.rel(.icon),
.href(StaticFile.favicon.urlPath(
@@ -32,6 +32,13 @@ struct IndexPageTests {
#expect(html.contains("/js/index.js"))
}
@Test
func `renders no font preloads until fonts are declared`() {
// The template ships no fonts, so a preload link here would point at a file the service does not serve.
#expect(IndexPage.preloadedFonts.isEmpty)
#expect(!IndexPage(locale: .init(identifier: "en")).render().contains(#"rel="preload""#))
}
@Test
func `renders versioned asset URLs when given a version`() {
let html = IndexPage(
@@ -24,6 +24,15 @@ struct StaticFileTests {
#expect(file.fileExtensions.map(file.relativePath) == paths)
}
/// A preload URL must match the stylesheet's `@font-face` source exactly, so it carries the extension's folder and no version query.
@Test
func `unversioned font paths`() {
let font = File("a-font-400", as: .woff2)
#expect(font.relativePath(for: .woff2) == "font/a-font-400.woff2")
#expect(font.urlPath(for: .woff2) == "/font/a-font-400.woff2")
}
// MARK: Constants tests
@Test