Added font preload links to the Page+Defaults extension in the Website library target.
This commit is contained in:
@@ -6,6 +6,16 @@ import Localization
|
|||||||
/// The site-wide defaults shared by every page of the website.
|
/// The site-wide defaults shared by every page of the website.
|
||||||
extension Page {
|
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
|
// MARK: Computed
|
||||||
|
|
||||||
/// The document language, derived from the page's locale and falling back to the default language.
|
/// The document language, derived from the page's locale and falling back to the default language.
|
||||||
@@ -14,9 +24,29 @@ extension Page {
|
|||||||
?? LanguageList().default
|
?? LanguageList().default
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The icon, manifest, and theme colour metadata shared by every page of the website.
|
/// The site-wide head metadata; a page that adds tags of its own composes ``siteMetadata`` rather than replacing it.
|
||||||
@HTMLBuilder
|
|
||||||
var metadata: some HTML {
|
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(
|
link(
|
||||||
.rel(.icon),
|
.rel(.icon),
|
||||||
.href(StaticFile.favicon.urlPath(
|
.href(StaticFile.favicon.urlPath(
|
||||||
|
|||||||
@@ -32,6 +32,13 @@ struct IndexPageTests {
|
|||||||
#expect(html.contains("/js/index.js"))
|
#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
|
@Test
|
||||||
func `renders versioned asset URLs when given a version`() {
|
func `renders versioned asset URLs when given a version`() {
|
||||||
let html = IndexPage(
|
let html = IndexPage(
|
||||||
|
|||||||
@@ -24,6 +24,15 @@ struct StaticFileTests {
|
|||||||
#expect(file.fileExtensions.map(file.relativePath) == paths)
|
#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
|
// MARK: Constants tests
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user