Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
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/social-bats-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Adds warnings about using local font files in the `publicDir` when the experimental fonts API is enabled.
18 changes: 13 additions & 5 deletions packages/astro/src/assets/fonts/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createRequire } from 'node:module';
import { extname } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { pathToFileURL } from 'node:url';
import type * as unifont from 'unifont';
import type { Storage } from 'unstorage';
import { AstroError, AstroErrorData } from '../../core/errors/index.js';
Expand Down Expand Up @@ -248,8 +248,11 @@ function dedupe<const T extends Array<any>>(arr: T): T {

function resolveVariants({
variants,
root,
}: { variants: LocalFontFamily['variants']; root: URL }): ResolvedLocalFontFamily['variants'] {
resolveEntrypoint: _resolveEntrypoint,
}: {
variants: LocalFontFamily['variants'];
resolveEntrypoint: (url: string) => string;
}): ResolvedLocalFontFamily['variants'] {
return variants.map((variant) => ({
...variant,
weight: variant.weight.toString(),
Expand All @@ -258,7 +261,7 @@ function resolveVariants({
const url = (isValue ? value : value.url).toString();
const tech = isValue ? undefined : value.tech;
return {
url: fileURLToPath(resolveEntrypoint(root, url)),
url: _resolveEntrypoint(url),
tech,
};
}),
Expand All @@ -275,17 +278,22 @@ export async function resolveFontFamily({
generateNameWithHash,
root,
resolveMod,
resolveLocalEntrypoint,
}: Omit<ResolveProviderOptions, 'provider'> & {
family: FontFamily;
generateNameWithHash: (family: FontFamily) => string;
resolveLocalEntrypoint: (url: string) => string;
}): Promise<ResolvedFontFamily> {
const nameWithHash = generateNameWithHash(family);

if (family.provider === LOCAL_PROVIDER_NAME) {
return {
...family,
nameWithHash,
variants: resolveVariants({ variants: family.variants, root }),
variants: resolveVariants({
variants: family.variants,
resolveEntrypoint: resolveLocalEntrypoint,
}),
fallbacks: family.fallbacks ? dedupe(family.fallbacks) : undefined,
};
}
Expand Down
20 changes: 19 additions & 1 deletion packages/astro/src/assets/fonts/vite-plugin-fonts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { PreloadData, ResolvedFontFamily } from './types.js';
import {
cache,
extractFontType,
resolveEntrypoint,
resolveFontFamily,
sortObjectByKey,
withoutQuotes,
Expand Down Expand Up @@ -118,18 +119,35 @@ export function fontsPlugin({ settings, sync, logger }: Options): Plugin {

const families: Array<ResolvedFontFamily> = [];

const root = settings.config.root;
const pathsToWarn = new Set<string>();

for (const family of settings.config.experimental.fonts!) {
families.push(
await resolveFontFamily({
family,
root: settings.config.root,
root,
resolveMod,
generateNameWithHash: (_family) =>
`${withoutQuotes(_family.name)}-${h64ToString(JSON.stringify(sortObjectByKey(_family)))}`,
resolveLocalEntrypoint: (url) => {
const resolvedPath = fileURLToPath(resolveEntrypoint(root, url));
if (resolvedPath.startsWith(fileURLToPath(settings.config.publicDir))) {
pathsToWarn.add(resolvedPath);
}
return resolvedPath;
},
}),
);
}

for (const path of [...pathsToWarn]) {
logger.warn(
'assets',
`The font file ${JSON.stringify(path)} used by a local family is located in \`config.publicDir\`. This will result in duplicated files in the output.`,
);
}

await loadFonts({
base: baseUrl,
families,
Expand Down
6 changes: 6 additions & 0 deletions packages/astro/test/units/assets/fonts/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
isGenericFontFamily,
proxyURL,
renderFontSrc,
resolveEntrypoint,
resolveFontFamily,
toCSS,
} from '../../../../dist/assets/fonts/utils.js';
Expand Down Expand Up @@ -280,6 +281,7 @@ describe('fonts utils', () => {
resolveMod: async () => ({ provider: () => {} }),
generateNameWithHash: (family) => `${family.name}-x`,
root,
resolveLocalEntrypoint: (url) => fileURLToPath(resolveEntrypoint(root, url)),
}),
{
name: 'Custom',
Expand Down Expand Up @@ -313,6 +315,7 @@ describe('fonts utils', () => {
resolveMod: async () => ({ provider: () => {} }),
generateNameWithHash: (family) => `${family.name}-x`,
root,
resolveLocalEntrypoint: (url) => fileURLToPath(resolveEntrypoint(root, url)),
}),
{
name: 'Custom',
Expand Down Expand Up @@ -341,6 +344,7 @@ describe('fonts utils', () => {
resolveMod: (id) => import(id),
generateNameWithHash: (family) => `${family.name}-x`,
root,
resolveLocalEntrypoint: (url) => fileURLToPath(resolveEntrypoint(root, url)),
});
assert.equal(res.name, 'Custom');
// Required to make TS happy
Expand All @@ -358,6 +362,7 @@ describe('fonts utils', () => {
resolveMod: (id) => import(id),
generateNameWithHash: (family) => `${family.name}-x`,
root,
resolveLocalEntrypoint: (url) => fileURLToPath(resolveEntrypoint(root, url)),
});
assert.equal(res.name, 'Custom');
// Required to make TS happy
Expand All @@ -379,6 +384,7 @@ describe('fonts utils', () => {
resolveMod: async () => ({ provider: () => Object.assign(() => {}, { _name: 'test' }) }),
generateNameWithHash: (family) => `${family.name}-x`,
root,
resolveLocalEntrypoint: (url) => fileURLToPath(resolveEntrypoint(root, url)),
});
assert.equal(res.name, 'Custom');
if (res.provider !== 'local') {
Expand Down