fix(web): keep self-hosted fonts within the deployment base path (#1016)

* fix(web): keep self-hosted fonts within the deployment base path

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

* test(web): use a lint-safe font URL matcher

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>

---------

Signed-off-by: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com>
This commit is contained in:
XiaoSeS 2026-10-25 22:38:38 +08:00 • committed by GitHub
parent 16fea87abf
commit f9fc339509
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 40 additions and 12 deletions

28
web/font-assets.test.ts Normal file
View file

@ -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}`)
}
},
)
})

View file

@ -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;
}