Skip to content

Commit a509941

Browse files
feat(fonts): npm provider (#15529)
* feat(fonts): npm provider * misc * jsdocs * provide readFile * Apply suggestions from code review Co-authored-by: Sarah Rainsberger <5098874+sarah11918@users.noreply.github.com> --------- Co-authored-by: Sarah Rainsberger <5098874+sarah11918@users.noreply.github.com>
1 parent 3e71b2e commit a509941

File tree

5 files changed

+77
-20
lines changed

5 files changed

+77
-20
lines changed

.changeset/heavy-beers-unite.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
'astro': minor
3+
---
4+
5+
Adds a new build-in font provider `npm` to access fonts installed as NPM packages
6+
7+
You can now add web fonts specified in your `package.json` through Astro's type-safe Fonts API. The `npm` font provider allows you to add fonts either from locally installed packages in `node_modules` or from a CDN.
8+
9+
Set `fontProviders.npm()` as your fonts provider along with the required `name` and `cssVariable` values, and add `options` as needed:
10+
11+
```js
12+
import { defineConfig, fontProviders } from 'astro/config';
13+
14+
export default defineConfig({
15+
experimental: {
16+
fonts: [
17+
{
18+
name: 'Roboto',
19+
provider: fontProviders.npm(),
20+
cssVariable: '--font-roboto',
21+
},
22+
],
23+
},
24+
});
25+
```
26+
27+
See the [NPM font provider reference documentation](https://v6.docs.astro.build/en/reference/font-provider-reference/#npm) for more details.

packages/astro/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@
163163
"tinyglobby": "^0.2.15",
164164
"tsconfck": "^3.1.6",
165165
"ultrahtml": "^1.6.0",
166-
"unifont": "~0.7.3",
166+
"unifont": "~0.7.4",
167167
"unist-util-visit": "^5.1.0",
168168
"unstorage": "^1.17.4",
169169
"vfile": "^6.0.3",

packages/astro/src/assets/fonts/providers/index.ts

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ import {
33
type GoogleFamilyOptions,
44
type GoogleiconsFamilyOptions,
55
type InitializedProvider,
6+
type NpmProviderOptions,
7+
type NpmFamilyOptions,
68
providers,
79
} from 'unifont';
810
import { FontaceFontFileReader } from '../infra/fontace-font-file-reader.js';
911
import type { FontProvider } from '../types.js';
1012
import { type LocalFamilyOptions, LocalFontProvider } from './local.js';
13+
import { fileURLToPath } from 'node:url';
14+
import { readFile } from 'node:fs/promises';
1115

12-
/** [Adobe](https://fonts.adobe.com/) */
16+
/** [Adobe](https://v6.docs.astro.build/en/reference/font-provider-reference/#adobe) */
1317
function adobe(config: AdobeProviderOptions): FontProvider {
1418
const provider = providers.adobe(config);
1519
let initializedProvider: InitializedProvider | undefined;
@@ -28,7 +32,7 @@ function adobe(config: AdobeProviderOptions): FontProvider {
2832
};
2933
}
3034

31-
/** [Bunny](https://fonts.bunny.net/) */
35+
/** [Bunny](https://v6.docs.astro.build/en/reference/font-provider-reference/#bunny) */
3236
function bunny(): FontProvider {
3337
const provider = providers.bunny();
3438
let initializedProvider: InitializedProvider | undefined;
@@ -46,7 +50,7 @@ function bunny(): FontProvider {
4650
};
4751
}
4852

49-
/** [Fontshare](https://www.fontshare.com/) */
53+
/** [Fontshare](https://v6.docs.astro.build/en/reference/font-provider-reference/#fontshare) */
5054
function fontshare(): FontProvider {
5155
const provider = providers.fontshare();
5256
let initializedProvider: InitializedProvider | undefined;
@@ -64,7 +68,7 @@ function fontshare(): FontProvider {
6468
};
6569
}
6670

67-
/** [Fontsource](https://fontsource.org/) */
71+
/** [Fontsource](https://v6.docs.astro.build/en/reference/font-provider-reference/#fontsource) */
6872
function fontsource(): FontProvider {
6973
const provider = providers.fontsource();
7074
let initializedProvider: InitializedProvider | undefined;
@@ -82,7 +86,7 @@ function fontsource(): FontProvider {
8286
};
8387
}
8488

85-
/** [Google](https://fonts.google.com/) */
89+
/** [Google](https://v6.docs.astro.build/en/reference/font-provider-reference/#google) */
8690
function google(): FontProvider<GoogleFamilyOptions | undefined> {
8791
const provider = providers.google();
8892
let initializedProvider: InitializedProvider<GoogleFamilyOptions> | undefined;
@@ -100,7 +104,7 @@ function google(): FontProvider<GoogleFamilyOptions | undefined> {
100104
};
101105
}
102106

103-
/** [Google Icons](https://fonts.google.com/icons) */
107+
/** [Google Icons](https://v6.docs.astro.build/en/reference/font-provider-reference/#google-icons) */
104108
function googleicons(): FontProvider<GoogleiconsFamilyOptions | undefined> {
105109
const provider = providers.googleicons();
106110
let initializedProvider: InitializedProvider<GoogleiconsFamilyOptions> | undefined;
@@ -118,22 +122,46 @@ function googleicons(): FontProvider<GoogleiconsFamilyOptions | undefined> {
118122
};
119123
}
120124

121-
/** A provider that handles local files. */
125+
/** [Local](https://v6.docs.astro.build/en/reference/font-provider-reference/#local) */
122126
function local(): FontProvider<LocalFamilyOptions> {
123127
return new LocalFontProvider({
124128
fontFileReader: new FontaceFontFileReader(),
125129
});
126130
}
127131

132+
/** [NPM](https://v6.docs.astro.build/en/reference/font-provider-reference/#npm) */
133+
function npm(
134+
options?: Omit<NpmProviderOptions, 'root' | 'readFile'>,
135+
): FontProvider<NpmFamilyOptions | undefined> {
136+
let initializedProvider: InitializedProvider<NpmFamilyOptions> | undefined;
137+
return {
138+
name: providers.npm()._name,
139+
async init(context) {
140+
initializedProvider = await providers.npm({
141+
...options,
142+
root: fileURLToPath(context.root),
143+
readFile: (path) => readFile(path, 'utf-8').catch(() => null),
144+
})(context);
145+
},
146+
async resolveFont({ familyName, ...rest }) {
147+
return await initializedProvider?.resolveFont(familyName, rest);
148+
},
149+
async listFonts() {
150+
return await initializedProvider?.listFonts?.();
151+
},
152+
};
153+
}
154+
128155
/**
129156
* Astro exports a few built-in providers:
130-
* - [Adobe](https://fonts.adobe.com/)
131-
* - [Bunny](https://fonts.bunny.net/)
132-
* - [Fontshare](https://www.fontshare.com/)
133-
* - [Fontsource](https://fontsource.org/)
134-
* - [Google](https://fonts.google.com/)
135-
* - [Google Icons](https://fonts.google.com/icons)
136-
* - Local
157+
* - [Adobe](https://v6.docs.astro.build/en/reference/font-provider-reference/#adobe)
158+
* - [Bunny](https://v6.docs.astro.build/en/reference/font-provider-reference/#bunny)
159+
* - [Fontshare](https://v6.docs.astro.build/en/reference/font-provider-reference/#fontshare)
160+
* - [Fontsource](https://v6.docs.astro.build/en/reference/font-provider-reference/#fontsource)
161+
* - [Google](https://v6.docs.astro.build/en/reference/font-provider-reference/#google)
162+
* - [Google Icons](https://v6.docs.astro.build/en/reference/font-provider-reference/#google-icons)
163+
* - [Local](https://v6.docs.astro.build/en/reference/font-provider-reference/#local)
164+
* - [NPM](TODO:)
137165
*/
138166
export const fontProviders = {
139167
adobe,
@@ -143,4 +171,5 @@ export const fontProviders = {
143171
google,
144172
googleicons,
145173
local,
174+
npm,
146175
};

packages/astro/test/units/assets/fonts/providers.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ describe('fonts providers', () => {
1414
assert.equal(fontProviders.fontsource().name, 'fontsource');
1515
assert.equal(fontProviders.google().name, 'google');
1616
assert.equal(fontProviders.googleicons().name, 'googleicons');
17+
assert.equal(fontProviders.npm().name, 'npm');
1718
assert.equal(fontProviders.local().name, 'local');
1819
});
1920

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)