Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-ducks-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Adds a terminal warning when a remote provider returns no data for a family when using the experimental fonts API
4 changes: 4 additions & 0 deletions packages/astro/src/assets/fonts/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,7 @@ export interface FontFetcher {
export interface FontTypeExtractor {
extract: (url: string) => FontType;
}

export interface FontLogger {
log: (type: 'warn', message: string) => void;
}
13 changes: 13 additions & 0 deletions packages/astro/src/assets/fonts/implementations/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { Logger } from '../../../core/logger/core.js';
import type { FontLogger } from '../definitions.js';

export function createAstroFontLogger({ logger }: { logger: Logger }): FontLogger {
return {
log: (_type, message) => {
if (_type === 'warn') {
return logger.warn('assets', message);
}
_type satisfies never;
},
};
}
10 changes: 10 additions & 0 deletions packages/astro/src/assets/fonts/orchestrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Storage } from 'unstorage';
import { LOCAL_PROVIDER_NAME } from './constants.js';
import type {
CssRenderer,
FontLogger,
FontMetricsResolver,
FontTypeExtractor,
Hasher,
Expand All @@ -25,6 +26,7 @@ import type {
PreloadData,
} from './types.js';
import { pickFontFaceProperty, unifontFontFaceDataToProperties } from './utils.js';
import { bold } from 'kleur/colors';

/**
* Manages how fonts are resolved:
Expand Down Expand Up @@ -54,6 +56,7 @@ export async function orchestrate({
systemFallbacksProvider,
fontMetricsResolver,
fontTypeExtractor,
logger,
createUrlProxy,
defaults,
}: {
Expand All @@ -66,6 +69,7 @@ export async function orchestrate({
systemFallbacksProvider: SystemFallbacksProvider;
fontMetricsResolver: FontMetricsResolver;
fontTypeExtractor: FontTypeExtractor;
logger: FontLogger;
createUrlProxy: (params: CreateUrlProxyParams) => UrlProxy;
defaults: Defaults;
}): Promise<{
Expand Down Expand Up @@ -163,6 +167,12 @@ export async function orchestrate({
// from families (inside extractUnifontProviders).
[family.provider.name!],
);
if (result.fonts.length === 0) {
logger.log(
'warn',
`No data found for family ${bold(family.name)}. Review your configuration`,
);
}
// The data returned by the remote provider contains original URLs. We proxy them.
fonts = normalizeRemoteFontFaces({ fonts: result.fonts, urlProxy });
}
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/assets/fonts/vite-plugin-fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import {
import { createUrlProxy } from './implementations/url-proxy.js';
import { orchestrate } from './orchestrate.js';
import type { ConsumableMap, FontFileDataMap } from './types.js';
import { createAstroFontLogger } from './implementations/logger.js';

interface Options {
settings: AstroSettings;
Expand Down Expand Up @@ -143,6 +144,7 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {
systemFallbacksProvider,
fontMetricsResolver,
fontTypeExtractor,
logger: createAstroFontLogger({ logger }),
createUrlProxy: ({ local, ...params }) => {
const dataCollector = createDataCollector(params);
const contentResolver = local
Expand Down
35 changes: 30 additions & 5 deletions packages/astro/test/units/assets/fonts/orchestrate.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { createUrlProxy } from '../../../../dist/assets/fonts/implementations/ur
import { orchestrate } from '../../../../dist/assets/fonts/orchestrate.js';
import { defineAstroFontProvider } from '../../../../dist/assets/fonts/providers/index.js';
import {
createSpyLogger,
createSpyStorage,
fakeFontMetricsResolver,
fakeHasher,
Expand All @@ -29,6 +30,8 @@ describe('fonts orchestrate()', () => {
const errorHandler = simpleErrorHandler;
const fontTypeExtractor = createFontTypeExtractor({ errorHandler });
const hasher = fakeHasher;
const { logger, messages } = createSpyLogger();

const { fontFileDataMap, consumableMap } = await orchestrate({
families: [
{
Expand Down Expand Up @@ -56,6 +59,7 @@ describe('fonts orchestrate()', () => {
systemFallbacksProvider: createSystemFallbacksProvider(),
fontMetricsResolver: fakeFontMetricsResolver,
fontTypeExtractor,
logger,
createUrlProxy: ({ local, ...params }) => {
const dataCollector = createDataCollector(params);
const contentResolver = createRemoteUrlProxyContentResolver();
Expand All @@ -69,6 +73,7 @@ describe('fonts orchestrate()', () => {
},
defaults: DEFAULTS,
});

assert.deepStrictEqual(
[...fontFileDataMap.entries()],
[
Expand Down Expand Up @@ -96,10 +101,12 @@ describe('fonts orchestrate()', () => {
assert.equal(entry?.css.includes(':root{--test:Test-'), true);
// Fallback
assert.equal(entry?.css.includes('fallback: Arial"'), true);

assert.equal(messages.length, 0);
});

it('works with a remote provider', async () => {
const fakeUnifontProvider = defineFontProvider('test', () => {
const fakeUnifontProvider = defineFontProvider('normal', () => {
return {
resolveFont: () => {
return {
Expand All @@ -123,14 +130,23 @@ describe('fonts orchestrate()', () => {
};
});
const fakeAstroProvider = defineAstroFontProvider({
entrypoint: 'test',
entrypoint: 'normal',
});

const fakeEmptyUnifontProvider = defineFontProvider('empty', () => ({
resolveFont: () => ({ fonts: [] }),
}));
const fakeEmptyAstroProvider = defineAstroFontProvider({
entrypoint: 'empty',
});

const root = new URL(import.meta.url);
const { storage } = createSpyStorage();
const errorHandler = simpleErrorHandler;
const fontTypeExtractor = createFontTypeExtractor({ errorHandler });
const hasher = fakeHasher;
const { logger, messages } = createSpyLogger();

const { fontFileDataMap, consumableMap } = await orchestrate({
families: [
{
Expand All @@ -139,14 +155,20 @@ describe('fonts orchestrate()', () => {
provider: fakeAstroProvider,
fallbacks: ['serif'],
},
{
name: 'Foo',
cssVariable: '--foo',
provider: fakeEmptyAstroProvider,
fallbacks: ['serif'],
},
],
hasher,
remoteFontProviderResolver: createRemoteFontProviderResolver({
root,
errorHandler,
modResolver: {
resolve: async () => ({
provider: fakeUnifontProvider,
resolve: async (id) => ({
provider: id.endsWith('empty') ? fakeEmptyUnifontProvider : fakeUnifontProvider,
}),
},
}),
Expand All @@ -156,6 +178,7 @@ describe('fonts orchestrate()', () => {
systemFallbacksProvider: createSystemFallbacksProvider(),
fontMetricsResolver: fakeFontMetricsResolver,
fontTypeExtractor,
logger,
createUrlProxy: ({ local, ...params }) => {
const dataCollector = createDataCollector(params);
const contentResolver = createRemoteUrlProxyContentResolver();
Expand Down Expand Up @@ -183,7 +206,7 @@ describe('fonts orchestrate()', () => {
],
],
);
assert.deepStrictEqual([...consumableMap.keys()], ['--test']);
assert.deepStrictEqual([...consumableMap.keys()], ['--test', '--foo']);
const entry = consumableMap.get('--test');
assert.deepStrictEqual(entry?.preloadData, [
{ url: 'https://example.com/foo.woff2.woff2', type: 'woff2' },
Expand All @@ -194,5 +217,7 @@ describe('fonts orchestrate()', () => {
assert.equal(entry?.css.includes(':root{--test:Test-'), true);
// Fallback
assert.equal(entry?.css.includes('fallback: Times New Roman"'), true);

assert.equal(messages.length, 1);
});
});
13 changes: 13 additions & 0 deletions packages/astro/test/units/assets/fonts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,16 @@ export const fakeFontMetricsResolver = {
return JSON.stringify(input, null, 2) + `,`;
},
};

export function createSpyLogger() {
/** @type {Array<string>} */
const messages = [];
/** @type {import('../../../../dist/assets/fonts/definitions').FontLogger} */
const logger = {
log: (_type, message) => {
messages.push(message);
},
};

return { logger, messages };
}
Loading