Skip to content
80 changes: 38 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ const unifont = await createUnifont([
providers.google(),
])

const availableFonts = await unifont.listFonts()
const { fonts } = await unifont.resolveFont('Poppins')
const availableProviders = unifont.providers
const availableFonts = await unifont.listFonts({ provider: 'google' })
const { fonts } = await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'google' })
```

## Built-in providers
Expand Down Expand Up @@ -227,7 +228,7 @@ const unifont = await createUnifont([
], { storage })

// cached data is stored in `node_modules/.cache/unifont`
await unifont.resolveFont('Poppins')
await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'google' })
```

#### `throwOnError`
Expand All @@ -254,7 +255,7 @@ const unifont = await createUnifont([

#### `resolveFont()`

- Type: `(fontFamily: string, options?: Partial<ResolveFontOptions>, providers?: T[]) => Promise<ResolveFontResult & { provider?: T }>`
- Type: `(options: Partial<ResolveFontOptions> & { fontFamily: string, provider: string }) => Promise<ResolveFontResult>`

Retrieves font face data from available providers:

Expand All @@ -266,14 +267,28 @@ const unifont = await createUnifont([
providers.fontsource(),
])

const { fonts } = await unifont.resolveFont('Poppins')
const { fonts } = await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'google' })
```

It loops through all providers and returns the result of the first provider that can return some data.

##### Options

It accepts options as the 2nd parameter. Each provider chooses to support them or not.
Each provider chooses to support options or not.

###### `fontFamily`

- Type: `string`
- Required

Which font family to retrieve.

###### `provider`

- Type: `string`
- Required

Which provider to query.

###### `weights`

Expand All @@ -289,7 +304,9 @@ const unifont = await createUnifont([
providers.google(),
])

const { fonts } = await unifont.resolveFont('Poppins', {
const { fonts } = await unifont.resolveFont({
fontFamily: 'Poppins',
provider: 'google',
weights: ['300', '500 900']
})
```
Expand All @@ -308,7 +325,9 @@ const unifont = await createUnifont([
providers.google(),
])

const { fonts } = await unifont.resolveFont('Poppins', {
const { fonts } = await unifont.resolveFont({
fontFamily: 'Poppins',
provider: 'google',
styles: ['normal']
})
```
Expand All @@ -327,33 +346,18 @@ const unifont = await createUnifont([
providers.google(),
])

const { fonts } = await unifont.resolveFont('Poppins', {
const { fonts } = await unifont.resolveFont({
fontFamily: 'Poppins',
provider: 'google',
subsets: ['latin']
})
```

##### Providers

- Type: `string[]`

By default it uses all the providers provided to `createUnifont()`. However you can restrict usage to only a subset:

```js
import { createUnifont, providers } from 'unifont'

const unifont = await createUnifont([
providers.google(),
providers.fontsource(),
])

const { fonts } = await unifont.resolveFont('Poppins', {}, ['google'])
```

#### `listFonts()`

- Type: `(providers?: T[]) => Promise<string[] | undefined>`
- Type: `(options: { provider: string }) => Promise<string[] | undefined>`

Retrieves font names available for all providers:
Retrieves font names available for the specified provider:

```js
import { createUnifont, providers } from 'unifont'
Expand All @@ -362,27 +366,19 @@ const unifont = await createUnifont([
providers.google(),
])

const availableFonts = await unifont.listFont()
const availableFonts = await unifont.listFonts({ provider: 'google' })
```

It may return `undefined` if no provider is able to return names.

##### Providers

- Type: `string[]`
##### Options

By default it uses all the providers provided to `createUnifont()`. However you can restrict usage to only a subset:
###### `provider`

```js
import { createUnifont, providers } from 'unifont'

const unifont = await createUnifont([
providers.google(),
providers.fontsource(),
])
- Type: `string`
- Required

const availableFonts = await unifont.listFont(['google'])
```
Which provider to query.

## Building your own provider

Expand Down
2 changes: 1 addition & 1 deletion playground/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ const storage = createStorage({

const unifont = await createUnifont([providers.google()], { storage })

console.log(await unifont.resolveFont('Poppins'))
console.log(await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'google' }))
2 changes: 1 addition & 1 deletion playground/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ const unifont = await createUnifont([
providers.google(),
])

const fonts = await unifont.resolveFont('Poppins')
const fonts = await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'google' })

console.log(fonts)
87 changes: 40 additions & 47 deletions src/unifont.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ export interface UnifontOptions {
}

export interface Unifont<T extends Provider[]> {
resolveFont: (fontFamily: string, options?: Partial<ResolveFontOptions>, providers?: T[number]['_name'][]) => Promise<ResolveFontResult & {
provider?: T[number]['_name']
}>
listFonts: (providers?: T[number]['_name'][]) => Promise<string[] | undefined>
providers: T[number]['_name'][]
resolveFont: (options: Partial<ResolveFontOptions> & {
fontFamily: string
provider: T[number]['_name']
}) => Promise<ResolveFontResult>
listFonts: (options: { provider: T[number]['_name'] }) => Promise<string[] | undefined>
}

export const defaultResolveOptions: ResolveFontOptions = {
Expand Down Expand Up @@ -62,62 +64,53 @@ export async function createUnifont<T extends [Provider, ...Provider[]]>(provide
const allProviders = Object.keys(stack)

async function resolveFont(
fontFamily: string,
options: Partial<ResolveFontOptions> = {},
providers: T[number]['_name'][] = allProviders,
): Promise<
ResolveFontResult & {
provider?: T[number]['_name']
{ fontFamily, provider: id, ...options }: Partial<ResolveFontOptions> & {
fontFamily: string
provider: T[number]['_name']
},
): Promise<ResolveFontResult> {
const provider = stack[id]
if (!provider) {
const message = `Could not found \`${id}\` provider.`
if (unifontOptions?.throwOnError) {
throw new Error(message)
}
console.error(message)
return { fonts: [] }
}
> {
const mergedOptions = { ...defaultResolveOptions, ...options }
for (const id of providers) {
const provider = stack[id]

try {
const result = await provider?.resolveFont(fontFamily, mergedOptions)
if (result) {
return {
provider: id,
...result,
}
}
try {
const result = await provider?.resolveFont(fontFamily, { ...defaultResolveOptions, ...options })
if (result) {
return result
}
catch (cause) {
const message = `Could not resolve font face for \`${fontFamily}\` from \`${id}\` provider.`
if (unifontOptions?.throwOnError) {
throw new Error(message, { cause })
}
console.error(message, cause)
}
catch (cause) {
const message = `Could not resolve font face for \`${fontFamily}\` from \`${id}\` provider.`
if (unifontOptions?.throwOnError) {
throw new Error(message, { cause })
}
console.error(message, cause)
}
return { fonts: [] }
}

async function listFonts(providers: T[number]['_name'][] = allProviders): Promise<string[] | undefined> {
let names: string[] | undefined
for (const id of providers) {
const provider = stack[id]
async function listFonts({ provider: id }: { provider: T[number]['_name'] }): Promise<string[] | undefined> {
const provider = stack[id]

try {
const result = await provider?.listFonts?.()
if (result) {
names ??= []
names.push(...result)
}
}
catch (cause) {
const message = `Could not list names from \`${id}\` provider.`
if (unifontOptions?.throwOnError) {
throw new Error(message, { cause })
}
console.error(message, cause)
try {
return await provider?.listFonts?.()
}
catch (cause) {
const message = `Could not list names from \`${id}\` provider.`
if (unifontOptions?.throwOnError) {
throw new Error(message, { cause })
}
console.error(message, cause)
}
return names
}

return {
providers: allProviders,
resolveFont,
listFonts,
}
Expand Down
2 changes: 1 addition & 1 deletion test/cache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('cache storage', () => {
}
})
const unifont = await createUnifont([provider()], { storage: customStorage })
await unifont.resolveFont('Poppins')
await unifont.resolveFont({ fontFamily: 'Poppins', provider: 'custom-storage' })
expect(customStorage.getItem).toHaveBeenCalledWith('key')
expect(customStorage.setItem).toHaveBeenCalledWith('key', expect.objectContaining({ data: 'value' }))
expect(customStorage.setItem).toHaveBeenCalledWith('another-key', expect.objectContaining({ data: 'value' }))
Expand Down
Loading