diff --git a/web/font-assets.test.ts b/web/font-assets.test.ts new file mode 100644 index 000000000..ea32fc06e --- /dev/null +++ b/web/font-assets.test.ts @@ -0,0 +1,28 @@ +import { readFileSync } from 'node:fs' +import { describe, expect, it } from 'vitest' + +const stylesheet = new URL('./public/fonts/fonts.css', import.meta.url) +const css = readFileSync(stylesheet, 'utf8') +const references = [...css.matchAll(/url\(['"]?([^'")]+)['"]?\)/g)].map(match => match[1]) + +describe('self-hosted font assets', () => { + it('keeps every declared font backed by a real WOFF2 file', () => { + expect(references).toHaveLength(12) + for (const reference of references) { + const contents = readFileSync(new URL(reference, stylesheet)) + expect(contents.length).toBeGreaterThan(4) + expect(contents.subarray(0, 4).toString('ascii')).toBe('wOF2') + } + }) + + it.each(['/', '/skillhub/', '/release-v024/', '/nested/skillhub/'])( + 'resolves every font relative to its stylesheet under %s', + (basePath) => { + const stylesheetUrl = new URL(`${basePath}fonts/fonts.css`, 'https://example.test') + for (const reference of references) { + const filename = reference.split('/').at(-1) + expect(new URL(reference, stylesheetUrl).href).toBe(`https://example.test${basePath}fonts/${filename}`) + } + }, + ) +}) diff --git a/web/public/fonts/fonts.css b/web/public/fonts/fonts.css index 7d643dab9..7e44227c9 100644 --- a/web/public/fonts/fonts.css +++ b/web/public/fonts/fonts.css @@ -14,7 +14,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/inter-latin-400-normal.woff2') format('woff2'); + src: url('inter-latin-400-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -22,7 +22,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/inter-latin-ext-400-normal.woff2') format('woff2'); + src: url('inter-latin-ext-400-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -30,7 +30,7 @@ font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/inter-latin-500-normal.woff2') format('woff2'); + src: url('inter-latin-500-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -38,7 +38,7 @@ font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/inter-latin-ext-500-normal.woff2') format('woff2'); + src: url('inter-latin-ext-500-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -46,7 +46,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url('/fonts/inter-latin-600-normal.woff2') format('woff2'); + src: url('inter-latin-600-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -54,7 +54,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url('/fonts/inter-latin-ext-600-normal.woff2') format('woff2'); + src: url('inter-latin-ext-600-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -62,7 +62,7 @@ font-style: normal; font-weight: 700; font-display: swap; - src: url('/fonts/inter-latin-700-normal.woff2') format('woff2'); + src: url('inter-latin-700-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -70,7 +70,7 @@ font-style: normal; font-weight: 700; font-display: swap; - src: url('/fonts/inter-latin-ext-700-normal.woff2') format('woff2'); + src: url('inter-latin-ext-700-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -80,7 +80,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/jetbrains-mono-latin-400-normal.woff2') format('woff2'); + src: url('jetbrains-mono-latin-400-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -88,7 +88,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url('/fonts/jetbrains-mono-latin-ext-400-normal.woff2') format('woff2'); + src: url('jetbrains-mono-latin-ext-400-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; } @font-face { @@ -96,7 +96,7 @@ font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/jetbrains-mono-latin-500-normal.woff2') format('woff2'); + src: url('jetbrains-mono-latin-500-normal.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @font-face { @@ -104,6 +104,6 @@ font-style: normal; font-weight: 500; font-display: swap; - src: url('/fonts/jetbrains-mono-latin-ext-500-normal.woff2') format('woff2'); + src: url('jetbrains-mono-latin-ext-500-normal.woff2') format('woff2'); unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }