summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Florian Lefebvre <contact@florian-lefebvre.dev> 2025-04-28 15:33:52 +0200
committerGravatar GitHub <noreply@github.com> 2025-04-28 15:33:52 +0200
commit28f8716ceef8b30ebb4da8c6ef32acc72405c1e6 (patch)
tree029ea0ca7e1fd3b70addb2438d4aca8f5313a9ec
parent7d8c1dc99d742f9c2992a89b04bf19f43cdf3a43 (diff)
downloadastro-28f8716ceef8b30ebb4da8c6ef32acc72405c1e6.tar.gz
astro-28f8716ceef8b30ebb4da8c6ef32acc72405c1e6.tar.zst
astro-28f8716ceef8b30ebb4da8c6ef32acc72405c1e6.zip
feat(fonts): update unifont (#13705)
-rw-r--r--.changeset/cyan-games-jog.md5
-rw-r--r--packages/astro/package.json2
-rw-r--r--packages/astro/src/assets/fonts/definitions.ts33
-rw-r--r--packages/astro/src/assets/fonts/implementations/data-collector.ts10
-rw-r--r--packages/astro/src/assets/fonts/implementations/font-fetcher.ts8
-rw-r--r--packages/astro/src/assets/fonts/implementations/font-metrics-resolver.ts4
-rw-r--r--packages/astro/src/assets/fonts/implementations/url-proxy.ts5
-rw-r--r--packages/astro/src/assets/fonts/logic/normalize-remote-font-faces.ts1
-rw-r--r--packages/astro/src/assets/fonts/logic/optimize-fallbacks.ts14
-rw-r--r--packages/astro/src/assets/fonts/orchestrate.ts28
-rw-r--r--packages/astro/src/assets/fonts/providers/local.ts1
-rw-r--r--packages/astro/src/assets/fonts/types.ts19
-rw-r--r--packages/astro/src/assets/fonts/vite-plugin-fonts.ts35
-rw-r--r--packages/astro/test/units/assets/fonts/implementations.test.js53
-rw-r--r--packages/astro/test/units/assets/fonts/logic.test.js25
-rw-r--r--packages/astro/test/units/assets/fonts/orchestrate.test.js35
-rw-r--r--packages/astro/test/units/assets/fonts/providers.test.js7
-rw-r--r--pnpm-lock.yaml11
18 files changed, 186 insertions, 110 deletions
diff --git a/.changeset/cyan-games-jog.md b/.changeset/cyan-games-jog.md
new file mode 100644
index 000000000..cd4d8c0a8
--- /dev/null
+++ b/.changeset/cyan-games-jog.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Updates unifont to latest and adds support for `fetch` options from remote providers when using the experimental fonts API
diff --git a/packages/astro/package.json b/packages/astro/package.json
index 0d99e4f8a..934197a83 100644
--- a/packages/astro/package.json
+++ b/packages/astro/package.json
@@ -160,7 +160,7 @@
"tinyglobby": "^0.2.12",
"tsconfck": "^3.1.5",
"ultrahtml": "^1.6.0",
- "unifont": "~0.2.0",
+ "unifont": "~0.4.0",
"unist-util-visit": "^5.0.0",
"unstorage": "^1.15.0",
"vfile": "^6.0.3",
diff --git a/packages/astro/src/assets/fonts/definitions.ts b/packages/astro/src/assets/fonts/definitions.ts
index 2c25f2968..caae27f95 100644
--- a/packages/astro/src/assets/fonts/definitions.ts
+++ b/packages/astro/src/assets/fonts/definitions.ts
@@ -1,7 +1,13 @@
import type * as unifont from 'unifont';
import type { CollectedFontForMetrics } from './logic/optimize-fallbacks.js';
/* eslint-disable @typescript-eslint/no-empty-object-type */
-import type { AstroFontProvider, FontType, PreloadData, ResolvedFontProvider } from './types.js';
+import type {
+ AstroFontProvider,
+ FontFileData,
+ FontType,
+ PreloadData,
+ ResolvedFontProvider,
+} from './types.js';
import type { FontFaceMetrics, GenericFallbackName } from './types.js';
export interface Hasher {
@@ -43,11 +49,12 @@ export interface ErrorHandler {
}
export interface UrlProxy {
- proxy: (input: {
- url: string;
- collectPreload: boolean;
- data: Partial<unifont.FontFaceData>;
- }) => string;
+ proxy: (
+ input: Pick<FontFileData, 'url' | 'init'> & {
+ collectPreload: boolean;
+ data: Partial<unifont.FontFaceData>;
+ },
+ ) => string;
}
export interface UrlProxyContentResolver {
@@ -55,12 +62,12 @@ export interface UrlProxyContentResolver {
}
export interface DataCollector {
- collect: (input: {
- originalUrl: string;
- hash: string;
- data: Partial<unifont.FontFaceData>;
- preload: PreloadData | null;
- }) => void;
+ collect: (
+ input: FontFileData & {
+ data: Partial<unifont.FontFaceData>;
+ preload: PreloadData | null;
+ },
+ ) => void;
}
export type CssProperties = Record<string, string | undefined>;
@@ -87,7 +94,7 @@ export interface SystemFallbacksProvider {
}
export interface FontFetcher {
- fetch: (hash: string, url: string) => Promise<Buffer>;
+ fetch: (input: FontFileData) => Promise<Buffer>;
}
export interface FontTypeExtractor {
diff --git a/packages/astro/src/assets/fonts/implementations/data-collector.ts b/packages/astro/src/assets/fonts/implementations/data-collector.ts
index 6c0f3ad04..43f29b14f 100644
--- a/packages/astro/src/assets/fonts/implementations/data-collector.ts
+++ b/packages/astro/src/assets/fonts/implementations/data-collector.ts
@@ -8,18 +8,14 @@ export function createDataCollector({
saveFontData,
}: Omit<CreateUrlProxyParams, 'local'>): DataCollector {
return {
- collect({ originalUrl, hash, preload, data }) {
+ collect({ hash, url, init, preload, data }) {
if (!hasUrl(hash)) {
- saveUrl(hash, originalUrl);
+ saveUrl({ hash, url, init });
if (preload) {
savePreload(preload);
}
}
- saveFontData({
- hash,
- url: originalUrl,
- data,
- });
+ saveFontData({ hash, url, data, init });
},
};
}
diff --git a/packages/astro/src/assets/fonts/implementations/font-fetcher.ts b/packages/astro/src/assets/fonts/implementations/font-fetcher.ts
index af70bd130..9bc2ae8ff 100644
--- a/packages/astro/src/assets/fonts/implementations/font-fetcher.ts
+++ b/packages/astro/src/assets/fonts/implementations/font-fetcher.ts
@@ -11,19 +11,17 @@ export function createCachedFontFetcher({
}: {
storage: Storage;
errorHandler: ErrorHandler;
- fetch: (url: string) => Promise<Response>;
+ fetch: (url: string, init?: RequestInit) => Promise<Response>;
readFile: (url: string) => Promise<Buffer>;
}): FontFetcher {
return {
- async fetch(hash, url) {
+ async fetch({ hash, url, init }) {
return await cache(storage, hash, async () => {
try {
if (isAbsolute(url)) {
return await readFile(url);
}
- // TODO: find a way to pass headers
- // https://github.com/unjs/unifont/issues/143
- const response = await fetch(url);
+ const response = await fetch(url, init ?? undefined);
if (!response.ok) {
throw new Error(`Response was not successful, received status code ${response.status}`);
}
diff --git a/packages/astro/src/assets/fonts/implementations/font-metrics-resolver.ts b/packages/astro/src/assets/fonts/implementations/font-metrics-resolver.ts
index 093a9d2fc..5dff86d09 100644
--- a/packages/astro/src/assets/fonts/implementations/font-metrics-resolver.ts
+++ b/packages/astro/src/assets/fonts/implementations/font-metrics-resolver.ts
@@ -36,8 +36,8 @@ export function createCapsizeFontMetricsResolver({
const cache: Record<string, FontFaceMetrics | null> = {};
return {
- async getMetrics(name, { hash, url }) {
- cache[name] ??= filterRequiredMetrics(await fromBuffer(await fontFetcher.fetch(hash, url)));
+ async getMetrics(name, input) {
+ cache[name] ??= filterRequiredMetrics(await fromBuffer(await fontFetcher.fetch(input)));
return cache[name];
},
// Source: https://github.com/unjs/fontaine/blob/f00f84032c5d5da72c8798eae4cd68d3ddfbf340/src/css.ts#L170
diff --git a/packages/astro/src/assets/fonts/implementations/url-proxy.ts b/packages/astro/src/assets/fonts/implementations/url-proxy.ts
index 01cfdc40b..424375949 100644
--- a/packages/astro/src/assets/fonts/implementations/url-proxy.ts
+++ b/packages/astro/src/assets/fonts/implementations/url-proxy.ts
@@ -20,16 +20,17 @@ export function createUrlProxy({
fontTypeExtractor: FontTypeExtractor;
}): UrlProxy {
return {
- proxy({ url: originalUrl, data, collectPreload }) {
+ proxy({ url: originalUrl, data, collectPreload, init }) {
const type = fontTypeExtractor.extract(originalUrl);
const hash = `${hasher.hashString(contentResolver.resolve(originalUrl))}.${type}`;
const url = base + hash;
dataCollector.collect({
- originalUrl,
+ url: originalUrl,
hash,
preload: collectPreload ? { url, type } : null,
data,
+ init,
});
return url;
diff --git a/packages/astro/src/assets/fonts/logic/normalize-remote-font-faces.ts b/packages/astro/src/assets/fonts/logic/normalize-remote-font-faces.ts
index 4c4c6513d..c4689f0f7 100644
--- a/packages/astro/src/assets/fonts/logic/normalize-remote-font-faces.ts
+++ b/packages/astro/src/assets/fonts/logic/normalize-remote-font-faces.ts
@@ -35,6 +35,7 @@ export function normalizeRemoteFontFaces({
weight: font.weight,
style: font.style,
},
+ init: font.meta?.init ?? null,
}),
};
index++;
diff --git a/packages/astro/src/assets/fonts/logic/optimize-fallbacks.ts b/packages/astro/src/assets/fonts/logic/optimize-fallbacks.ts
index ed49e4e68..ef988f9fa 100644
--- a/packages/astro/src/assets/fonts/logic/optimize-fallbacks.ts
+++ b/packages/astro/src/assets/fonts/logic/optimize-fallbacks.ts
@@ -1,11 +1,9 @@
-import type * as unifont from 'unifont';
import type { FontMetricsResolver, SystemFallbacksProvider } from '../definitions.js';
-import type { ResolvedFontFamily } from '../types.js';
+import type * as unifont from 'unifont';
+import type { FontFileData, ResolvedFontFamily } from '../types.js';
import { isGenericFontFamily, unifontFontFaceDataToProperties } from '../utils.js';
-export interface CollectedFontForMetrics {
- hash: string;
- url: string;
+export interface CollectedFontForMetrics extends FontFileData {
data: Partial<unifont.FontFaceData>;
}
@@ -64,14 +62,14 @@ export async function optimizeFallbacks({
let css = '';
for (const { font, name } of localFontsMappings) {
- for (const { hash, url, data } of collectedFonts) {
+ for (const collected of collectedFonts) {
// We generate a fallback for each font collected, which is per weight and style
css += fontMetricsResolver.generateFontFace({
- metrics: await fontMetricsResolver.getMetrics(family.name, { hash, url, data }),
+ metrics: await fontMetricsResolver.getMetrics(family.name, collected),
fallbackMetrics: systemFallbacksProvider.getMetricsForLocalFont(font),
font,
name,
- properties: unifontFontFaceDataToProperties(data),
+ properties: unifontFontFaceDataToProperties(collected.data),
});
}
}
diff --git a/packages/astro/src/assets/fonts/orchestrate.ts b/packages/astro/src/assets/fonts/orchestrate.ts
index 1876cbc5d..5e476712b 100644
--- a/packages/astro/src/assets/fonts/orchestrate.ts
+++ b/packages/astro/src/assets/fonts/orchestrate.ts
@@ -16,7 +16,14 @@ import { normalizeRemoteFontFaces } from './logic/normalize-remote-font-faces.js
import { type CollectedFontForMetrics, optimizeFallbacks } from './logic/optimize-fallbacks.js';
import { resolveFamilies } from './logic/resolve-families.js';
import { resolveLocalFont } from './providers/local.js';
-import type { CreateUrlProxyParams, Defaults, FontFamily, PreloadData } from './types.js';
+import type {
+ ConsumableMap,
+ CreateUrlProxyParams,
+ Defaults,
+ FontFamily,
+ FontFileDataMap,
+ PreloadData,
+} from './types.js';
import { pickFontFaceProperty, unifontFontFaceDataToProperties } from './utils.js';
/**
@@ -61,7 +68,10 @@ export async function orchestrate({
fontTypeExtractor: FontTypeExtractor;
createUrlProxy: (params: CreateUrlProxyParams) => UrlProxy;
defaults: Defaults;
-}) {
+}): Promise<{
+ fontFileDataMap: FontFileDataMap;
+ consumableMap: ConsumableMap;
+}> {
let resolvedFamilies = await resolveFamilies({
families,
hasher,
@@ -84,11 +94,11 @@ export async function orchestrate({
* Holds associations of hash and original font file URLs, so they can be
* downloaded whenever the hash is requested.
*/
- const hashToUrlMap = new Map<string, string>();
+ const fontFileDataMap: FontFileDataMap = new Map();
/**
* Holds associations of CSS variables and preloadData/css to be passed to the virtual module.
*/
- const resolvedMap = new Map<string, { preloadData: Array<PreloadData>; css: string }>();
+ const consumableMap: ConsumableMap = new Map();
for (const family of resolvedFamilies) {
const preloadData: Array<PreloadData> = [];
@@ -106,9 +116,9 @@ export async function orchestrate({
*/
const urlProxy = createUrlProxy({
local: family.provider === LOCAL_PROVIDER_NAME,
- hasUrl: (hash) => hashToUrlMap.has(hash),
- saveUrl: (hash, url) => {
- hashToUrlMap.set(hash, url);
+ hasUrl: (hash) => fontFileDataMap.has(hash),
+ saveUrl: ({ hash, url, init }) => {
+ fontFileDataMap.set(hash, { url, init });
},
savePreload: (preload) => {
preloadData.push(preload);
@@ -195,8 +205,8 @@ export async function orchestrate({
css += cssRenderer.generateCssVariable(family.cssVariable, cssVarValues);
- resolvedMap.set(family.cssVariable, { preloadData, css });
+ consumableMap.set(family.cssVariable, { preloadData, css });
}
- return { hashToUrlMap, resolvedMap };
+ return { fontFileDataMap, consumableMap };
}
diff --git a/packages/astro/src/assets/fonts/providers/local.ts b/packages/astro/src/assets/fonts/providers/local.ts
index d4b95d500..1764b277c 100644
--- a/packages/astro/src/assets/fonts/providers/local.ts
+++ b/packages/astro/src/assets/fonts/providers/local.ts
@@ -28,6 +28,7 @@ export function resolveLocalFont({ family, urlProxy, fontTypeExtractor }: Option
weight: variant.weight,
style: variant.style,
},
+ init: null
}),
format: FONT_FORMAT_MAP[fontTypeExtractor.extract(source.url)],
tech: source.tech,
diff --git a/packages/astro/src/assets/fonts/types.ts b/packages/astro/src/assets/fonts/types.ts
index 04678ad83..e55a9d663 100644
--- a/packages/astro/src/assets/fonts/types.ts
+++ b/packages/astro/src/assets/fonts/types.ts
@@ -77,10 +77,27 @@ export type Defaults = Partial<
>
>;
+export interface FontFileData {
+ hash: string;
+ url: string;
+ init: RequestInit | null;
+}
+
export interface CreateUrlProxyParams {
local: boolean;
hasUrl: (hash: string) => boolean;
- saveUrl: (hash: string, url: string) => void;
+ saveUrl: (input: FontFileData) => void;
savePreload: (preload: PreloadData) => void;
saveFontData: (collected: CollectedFontForMetrics) => void;
}
+
+/**
+ * Holds associations of hash and original font file URLs, so they can be
+ * downloaded whenever the hash is requested.
+ */
+export type FontFileDataMap = Map<FontFileData['hash'], Pick<FontFileData, 'url' | 'init'>>;
+
+/**
+ * Holds associations of CSS variables and preloadData/css to be passed to the virtual module.
+ */
+export type ConsumableMap = Map<string, { preloadData: Array<PreloadData>; css: string }>;
diff --git a/packages/astro/src/assets/fonts/vite-plugin-fonts.ts b/packages/astro/src/assets/fonts/vite-plugin-fonts.ts
index d0a4c3496..a7a404815 100644
--- a/packages/astro/src/assets/fonts/vite-plugin-fonts.ts
+++ b/packages/astro/src/assets/fonts/vite-plugin-fonts.ts
@@ -44,7 +44,7 @@ import {
} from './implementations/url-proxy-content-resolver.js';
import { createUrlProxy } from './implementations/url-proxy.js';
import { orchestrate } from './orchestrate.js';
-import type { PreloadData } from './types.js';
+import type { ConsumableMap, FontFileDataMap } from './types.js';
interface Options {
settings: AstroSettings;
@@ -79,18 +79,15 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
// to trailingSlash: never)
const baseUrl = removeTrailingForwardSlash(settings.config.base) + URL_PREFIX;
- let resolvedMap: Map<string, { preloadData: Array<PreloadData>; css: string }> | null = null;
- // Key is `${hash}.${ext}`, value is a URL.
- // When a font file is requested (eg. /_astro/fonts/abc.woff), we use the hash
- // to download the original file, or retrieve it from cache
- let hashToUrlMap: Map<string, string> | null = null;
+ let fontFileDataMap: FontFileDataMap | null = null;
+ let consumableMap: ConsumableMap | null = null;
let isBuild: boolean;
let fontFetcher: FontFetcher | null = null;
let fontTypeExtractor: FontTypeExtractor | null = null;
const cleanup = () => {
- resolvedMap = null;
- hashToUrlMap = null;
+ consumableMap = null;
+ fontFileDataMap = null;
fontFetcher = null;
};
@@ -163,8 +160,8 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
});
// We initialize shared variables here and reset them in buildEnd
// to avoid locking memory
- hashToUrlMap = res.hashToUrlMap;
- resolvedMap = res.resolvedMap;
+ fontFileDataMap = res.fontFileDataMap;
+ consumableMap = res.consumableMap;
}
return {
@@ -190,7 +187,9 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
});
// The map is always defined at this point. Its values contains urls from remote providers
// as well as local paths for the local provider. We filter them to only keep the filepaths
- const localPaths = [...hashToUrlMap!.values()].filter((url) => isAbsolute(url));
+ const localPaths = [...fontFileDataMap!.values()]
+ .filter(({ url }) => isAbsolute(url))
+ .map((v) => v.url);
server.watcher.on('change', (path) => {
if (localPaths.includes(path)) {
logger.info('assets', 'Font file updated');
@@ -214,8 +213,8 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
return next();
}
const hash = req.url.slice(1);
- const url = hashToUrlMap?.get(hash);
- if (!url) {
+ const associatedData = fontFileDataMap?.get(hash);
+ if (!associatedData) {
return next();
}
// We don't want the request to be cached in dev because we cache it already internally,
@@ -228,7 +227,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
// Storage should be defined at this point since initialize it called before registering
// the middleware. hashToUrlMap is defined at the same time so if it's not set by now,
// no url will be matched and this line will not be reached.
- const data = await fontFetcher!.fetch(hash, url);
+ const data = await fontFetcher!.fetch({ hash, ...associatedData });
res.setHeader('Content-Length', data.length);
res.setHeader('Content-Type', `font/${fontTypeExtractor!.extract(hash)}`);
@@ -255,7 +254,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
load(id) {
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
return {
- code: `export const fontsData = new Map(${JSON.stringify(Array.from(resolvedMap?.entries() ?? []))})`,
+ code: `export const fontsData = new Map(${JSON.stringify(Array.from(consumableMap?.entries() ?? []))})`,
};
}
},
@@ -273,11 +272,11 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
} catch (cause) {
throw new AstroError(AstroErrorData.UnknownFilesystemError, { cause });
}
- if (hashToUrlMap) {
+ if (fontFileDataMap) {
logger.info('assets', 'Copying fonts...');
await Promise.all(
- Array.from(hashToUrlMap.entries()).map(async ([hash, url]) => {
- const data = await fontFetcher!.fetch(hash, url);
+ Array.from(fontFileDataMap.entries()).map(async ([hash, associatedData]) => {
+ const data = await fontFetcher!.fetch({ hash, ...associatedData });
try {
writeFileSync(new URL(hash, fontsDir), data);
} catch (cause) {
diff --git a/packages/astro/test/units/assets/fonts/implementations.test.js b/packages/astro/test/units/assets/fonts/implementations.test.js
index b5f2d5a7c..1370f730e 100644
--- a/packages/astro/test/units/assets/fonts/implementations.test.js
+++ b/packages/astro/test/units/assets/fonts/implementations.test.js
@@ -53,7 +53,7 @@ describe('fonts implementations', () => {
});
it('createDataCollector()', () => {
- /** @type {Map<string, string>} */
+ /** @type {import('../../../../dist/assets/fonts/types.js').FontFileDataMap} */
const map = new Map();
/** @type {Array<import('../../../../dist/assets/fonts/types.js').PreloadData>} */
const preloadData = [];
@@ -62,8 +62,8 @@ describe('fonts implementations', () => {
const dataCollector = createDataCollector({
hasUrl: (hash) => map.has(hash),
- saveUrl: (hash, url) => {
- map.set(hash, url);
+ saveUrl: ({ hash, url, init }) => {
+ map.set(hash, { url, init });
},
savePreload: (preload) => {
preloadData.push(preload);
@@ -73,27 +73,40 @@ describe('fonts implementations', () => {
},
});
- dataCollector.collect({ hash: 'xxx', originalUrl: 'abc', preload: null, data: {} });
+ dataCollector.collect({
+ hash: 'xxx',
+ url: 'abc',
+ preload: null,
+ data: {},
+ init: null,
+ });
dataCollector.collect({
hash: 'yyy',
- originalUrl: 'def',
+ url: 'def',
preload: { type: 'woff2', url: 'def' },
data: {},
+ init: null,
+ });
+ dataCollector.collect({
+ hash: 'xxx',
+ url: 'abc',
+ preload: null,
+ data: {},
+ init: null,
});
- dataCollector.collect({ hash: 'xxx', originalUrl: 'abc', preload: null, data: {} });
assert.deepStrictEqual(
[...map.entries()],
[
- ['xxx', 'abc'],
- ['yyy', 'def'],
+ ['xxx', { url: 'abc', init: null }],
+ ['yyy', { url: 'def', init: null }],
],
);
assert.deepStrictEqual(preloadData, [{ type: 'woff2', url: 'def' }]);
assert.deepStrictEqual(collectedFonts, [
- { hash: 'xxx', url: 'abc', data: {} },
- { hash: 'yyy', url: 'def', data: {} },
- { hash: 'xxx', url: 'abc', data: {} },
+ { hash: 'xxx', url: 'abc', data: {}, init: null },
+ { hash: 'yyy', url: 'def', data: {}, init: null },
+ { hash: 'xxx', url: 'abc', data: {}, init: null },
]);
});
@@ -185,9 +198,9 @@ describe('fonts implementations', () => {
fetch,
});
- await fontFetcher.fetch('abc', 'def');
- await fontFetcher.fetch('foo', 'bar');
- await fontFetcher.fetch('abc', 'def');
+ await fontFetcher.fetch({ hash: 'abc', url: 'def', init: null });
+ await fontFetcher.fetch({ hash: 'foo', url: 'bar', init: null });
+ await fontFetcher.fetch({ hash: 'abc', url: 'def', init: null });
assert.deepStrictEqual([...store.keys()], ['abc', 'foo']);
assert.deepStrictEqual(filesUrls, []);
@@ -205,7 +218,7 @@ describe('fonts implementations', () => {
fetch,
});
- await fontFetcher.fetch('abc', '/foo/bar');
+ await fontFetcher.fetch({ hash: 'abc', url: '/foo/bar', init: null });
assert.deepStrictEqual(filesUrls, ['/foo/bar']);
assert.deepStrictEqual(fetchUrls, []);
@@ -222,7 +235,7 @@ describe('fonts implementations', () => {
fetch,
});
- await fontFetcher.fetch('abc', 'https://example.com');
+ await fontFetcher.fetch({ hash: 'abc', url: 'https://example.com', init: null });
assert.deepStrictEqual(filesUrls, []);
assert.deepStrictEqual(fetchUrls, ['https://example.com']);
@@ -239,12 +252,16 @@ describe('fonts implementations', () => {
fetch,
});
- let error = await fontFetcher.fetch('abc', '/foo/bar').catch((err) => err);
+ let error = await fontFetcher
+ .fetch({ hash: 'abc', url: '/foo/bar', init: null })
+ .catch((err) => err);
assert.equal(error instanceof Error, true);
assert.equal(error.message, 'cannot-fetch-font-file');
assert.equal(error.cause, 'fs error');
- error = await fontFetcher.fetch('abc', 'https://example.com').catch((err) => err);
+ error = await fontFetcher
+ .fetch({ hash: 'abc', url: 'https://example.com', init: null })
+ .catch((err) => err);
assert.equal(error instanceof Error, true);
assert.equal(error.message, 'cannot-fetch-font-file');
assert.equal(error.cause instanceof Error, true);
diff --git a/packages/astro/test/units/assets/fonts/logic.test.js b/packages/astro/test/units/assets/fonts/logic.test.js
index 00d43df98..0fe637868 100644
--- a/packages/astro/test/units/assets/fonts/logic.test.js
+++ b/packages/astro/test/units/assets/fonts/logic.test.js
@@ -389,21 +389,24 @@ describe('fonts logic', () => {
url: '/',
collectPreload: true,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/ignored',
collectPreload: false,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/2',
collectPreload: true,
data: { weight: '500', style: 'normal' },
+ init: null,
},
]);
});
- it('collect preloads correctly', () => {
+ it('collects preloads correctly', () => {
const { collected, urlProxy } = createSpyUrlProxy();
normalizeRemoteFontFaces({
urlProxy,
@@ -425,21 +428,25 @@ describe('fonts logic', () => {
url: '/',
collectPreload: true,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/ignored',
collectPreload: false,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/2',
collectPreload: true,
data: { weight: '500', style: 'normal' },
+ init: null,
},
{
url: '/also-ignored',
collectPreload: false,
data: { weight: '500', style: 'normal' },
+ init: null,
},
]);
});
@@ -458,7 +465,7 @@ describe('fonts logic', () => {
await optimizeFallbacks({
family,
fallbacks: [],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: true,
systemFallbacksProvider,
fontMetricsResolver,
@@ -472,7 +479,7 @@ describe('fonts logic', () => {
await optimizeFallbacks({
family,
fallbacks: ['foo'],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: false,
systemFallbacksProvider,
fontMetricsResolver,
@@ -500,7 +507,7 @@ describe('fonts logic', () => {
await optimizeFallbacks({
family,
fallbacks: ['foo'],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: true,
systemFallbacksProvider,
fontMetricsResolver,
@@ -514,7 +521,7 @@ describe('fonts logic', () => {
await optimizeFallbacks({
family,
fallbacks: ['cursive'],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: true,
systemFallbacksProvider,
fontMetricsResolver,
@@ -531,7 +538,7 @@ describe('fonts logic', () => {
nameWithHash: 'Arial-xxx',
},
fallbacks: ['sans-serif'],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: true,
systemFallbacksProvider,
fontMetricsResolver,
@@ -544,7 +551,7 @@ describe('fonts logic', () => {
const result = await optimizeFallbacks({
family,
fallbacks: ['foo', 'sans-serif'],
- collectedFonts: [{ url: '', hash: '', data: {} }],
+ collectedFonts: [{ url: '', hash: '', data: {}, init: null }],
enabled: true,
systemFallbacksProvider,
fontMetricsResolver,
@@ -557,8 +564,8 @@ describe('fonts logic', () => {
family,
fallbacks: ['foo', 'sans-serif'],
collectedFonts: [
- { url: '', hash: '', data: { weight: '400' } },
- { url: '', hash: '', data: { weight: '500' } },
+ { url: '', hash: '', data: { weight: '400' }, init: null },
+ { url: '', hash: '', data: { weight: '500' }, init: null },
],
enabled: true,
systemFallbacksProvider,
diff --git a/packages/astro/test/units/assets/fonts/orchestrate.test.js b/packages/astro/test/units/assets/fonts/orchestrate.test.js
index d745f903c..022d89b87 100644
--- a/packages/astro/test/units/assets/fonts/orchestrate.test.js
+++ b/packages/astro/test/units/assets/fonts/orchestrate.test.js
@@ -29,7 +29,7 @@ describe('fonts orchestrate()', () => {
const errorHandler = simpleErrorHandler;
const fontTypeExtractor = createFontTypeExtractor({ errorHandler });
const hasher = fakeHasher;
- const { hashToUrlMap, resolvedMap } = await orchestrate({
+ const { fontFileDataMap, consumableMap } = await orchestrate({
families: [
{
name: 'Test',
@@ -70,20 +70,20 @@ describe('fonts orchestrate()', () => {
defaults: DEFAULTS,
});
assert.deepStrictEqual(
- [...hashToUrlMap.entries()],
+ [...fontFileDataMap.entries()],
[
[
fileURLToPath(new URL('my-font.woff2.woff2', root)),
- fileURLToPath(new URL('my-font.woff2', root)),
+ { url: fileURLToPath(new URL('my-font.woff2', root)), init: null },
],
[
fileURLToPath(new URL('my-font.woff.woff', root)),
- fileURLToPath(new URL('my-font.woff', root)),
+ { url: fileURLToPath(new URL('my-font.woff', root)), init: null },
],
],
);
- assert.deepStrictEqual([...resolvedMap.keys()], ['--test']);
- const entry = resolvedMap.get('--test');
+ assert.deepStrictEqual([...consumableMap.keys()], ['--test']);
+ const entry = consumableMap.get('--test');
assert.deepStrictEqual(entry?.preloadData, [
{
url: '/test' + fileURLToPath(new URL('my-font.woff2.woff2', root)),
@@ -111,6 +111,11 @@ describe('fonts orchestrate()', () => {
],
weight: '400',
style: 'normal',
+ meta: {
+ init: {
+ method: 'POST',
+ },
+ },
},
],
};
@@ -126,7 +131,7 @@ describe('fonts orchestrate()', () => {
const errorHandler = simpleErrorHandler;
const fontTypeExtractor = createFontTypeExtractor({ errorHandler });
const hasher = fakeHasher;
- const { hashToUrlMap, resolvedMap } = await orchestrate({
+ const { fontFileDataMap, consumableMap } = await orchestrate({
families: [
{
name: 'Test',
@@ -166,14 +171,20 @@ describe('fonts orchestrate()', () => {
});
assert.deepStrictEqual(
- [...hashToUrlMap.entries()],
+ [...fontFileDataMap.entries()],
[
- ['https://example.com/foo.woff2.woff2', 'https://example.com/foo.woff2'],
- ['https://example.com/foo.woff.woff', 'https://example.com/foo.woff'],
+ [
+ 'https://example.com/foo.woff2.woff2',
+ { url: 'https://example.com/foo.woff2', init: { method: 'POST' } },
+ ],
+ [
+ 'https://example.com/foo.woff.woff',
+ { url: 'https://example.com/foo.woff', init: { method: 'POST' } },
+ ],
],
);
- assert.deepStrictEqual([...resolvedMap.keys()], ['--test']);
- const entry = resolvedMap.get('--test');
+ assert.deepStrictEqual([...consumableMap.keys()], ['--test']);
+ const entry = consumableMap.get('--test');
assert.deepStrictEqual(entry?.preloadData, [
{ url: 'https://example.com/foo.woff2.woff2', type: 'woff2' },
]);
diff --git a/packages/astro/test/units/assets/fonts/providers.test.js b/packages/astro/test/units/assets/fonts/providers.test.js
index dec49fbb1..9d88a7b4a 100644
--- a/packages/astro/test/units/assets/fonts/providers.test.js
+++ b/packages/astro/test/units/assets/fonts/providers.test.js
@@ -89,16 +89,19 @@ describe('fonts providers', () => {
url: '/test.woff2',
collectPreload: true,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/ignored.woff',
collectPreload: false,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/2.woff2',
collectPreload: true,
data: { weight: '500', style: 'normal' },
+ init: null,
},
]);
});
@@ -132,21 +135,25 @@ describe('fonts providers', () => {
url: '/test.woff2',
collectPreload: true,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/ignored.woff',
collectPreload: false,
data: { weight: '400', style: 'normal' },
+ init: null,
},
{
url: '/2.woff2',
collectPreload: true,
data: { weight: '500', style: 'normal' },
+ init: null,
},
{
url: '/also-ignored.woff',
collectPreload: false,
data: { weight: '500', style: 'normal' },
+ init: null,
},
]);
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2ae548a3c..c642cd5ce 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -605,8 +605,8 @@ importers:
specifier: ^1.6.0
version: 1.6.0
unifont:
- specifier: ~0.2.0
- version: 0.2.0
+ specifier: ~0.4.0
+ version: 0.4.0
unist-util-visit:
specifier: ^5.0.0
version: 5.0.0
@@ -9969,6 +9969,7 @@ packages:
libsql@0.5.4:
resolution: {integrity: sha512-GEFeWca4SDAQFxjHWJBE6GK52LEtSskiujbG3rqmmeTO9t4sfSBKIURNLLpKDDF7fb7jmTuuRkDAn9BZGITQNw==}
+ cpu: [x64, arm64, wasm32]
os: [darwin, linux, win32]
lightningcss-darwin-arm64@1.29.2:
@@ -11806,8 +11807,8 @@ packages:
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
- unifont@0.2.0:
- resolution: {integrity: sha512-RoF14/tOhLvDa7R5K6A3PjsfJVFKvadvRpWjfV1ttabUe9704P1ie9z1ABLWEts/8SxrBVePav/XhgeFNltpsw==}
+ unifont@0.4.0:
+ resolution: {integrity: sha512-wbc8b02b+K7WRHSxD+YQRYS31iVwOd0dRF7Nv73nolzyQ5n4qMtuJ4OdJSe1hEB7XT+lPb2Qk7FHxOrMReh9lw==}
unist-util-find-after@5.0.0:
resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==}
@@ -18607,7 +18608,7 @@ snapshots:
trough: 2.2.0
vfile: 6.0.3
- unifont@0.2.0:
+ unifont@0.4.0:
dependencies:
css-tree: 3.1.0
ohash: 2.0.11