(context: ResolverContext)
| 24 | }) => Promise<FontFaceResolution | undefined> |
| 25 | |
| 26 | export async function createResolver(context: ResolverContext): Promise<Resolver> { |
| 27 | const { options, normalizeFontData, providers, exposeFont = () => {}, logger = consola.withTag('fontless') } = context |
| 28 | |
| 29 | const resolvedProviders: Array<Provider> = [] |
| 30 | const prioritisedProviders = new Set<string>() |
| 31 | |
| 32 | for (const [key, provider] of Object.entries(providers)) { |
| 33 | if (options.providers?.[key] === false || (options.provider && options.provider !== key)) { |
| 34 | delete providers[key] |
| 35 | } |
| 36 | else { |
| 37 | const providerOptions = (options[key as 'google' | 'local' | 'adobe' | 'npm'] || {}) as Record<string, unknown> |
| 38 | resolvedProviders.push(provider(providerOptions)) |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | if (resolvedProviders.length === 0) { |
| 43 | throw new Error('At least one font provider must be configured') |
| 44 | } |
| 45 | |
| 46 | for (const val of options.priority || []) { |
| 47 | if (val in providers) |
| 48 | prioritisedProviders.add(val) |
| 49 | } |
| 50 | for (const provider in providers) { |
| 51 | prioritisedProviders.add(provider) |
| 52 | } |
| 53 | const unifont = await createUnifont(resolvedProviders as [Provider, ...Provider[]], { |
| 54 | ...options, |
| 55 | storage: context.storage, |
| 56 | }) |
| 57 | |
| 58 | // Custom merging for defaults - providing a value for any default will override module |
| 59 | // defaults entirely (to prevent array merging) |
| 60 | // Note: defaultValues.fallbacks uses shared category-aware presets from fontaine package |
| 61 | const normalizedDefaults = { |
| 62 | weights: [...new Set((options.defaults?.weights || defaultValues.weights).map(v => String(v)))], |
| 63 | styles: [...new Set(options.defaults?.styles || defaultValues.styles)], |
| 64 | subsets: [...new Set(options.defaults?.subsets || defaultValues.subsets)], |
| 65 | formats: [...new Set(options.defaults?.formats || defaultValues.formats)], |
| 66 | fallbacks: Object.fromEntries(Object.entries(defaultValues.fallbacks).map(([key, value]) => [ |
| 67 | key, |
| 68 | Array.isArray(options.defaults?.fallbacks) ? options.defaults.fallbacks : options.defaults?.fallbacks?.[key as GenericCSSFamily] || value, |
| 69 | ])) as Record<GenericCSSFamily, string[]>, |
| 70 | } |
| 71 | |
| 72 | function addFallbacks(fontFamily: string, font: FontFaceData[]) { |
| 73 | if (options.experimental?.disableLocalFallbacks) { |
| 74 | return font |
| 75 | } |
| 76 | return addLocalFallbacks(fontFamily, font) |
| 77 | } |
| 78 | |
| 79 | return async function resolveFontFaceWithOverride(fontFamily: string, override?: FontFamilyManualOverride | FontFamilyProviderOverride, fallbackOptions?: { fallbacks: string[], generic?: GenericCSSFamily }): Promise<FontFaceResolution | undefined> { |
| 80 | const fallbacks = (override && 'fallbacks' in override ? override.fallbacks : undefined) || normalizedDefaults.fallbacks[fallbackOptions?.generic || 'sans-serif'] |
| 81 | |
| 82 | if (override && 'src' in override) { |
| 83 | const fonts = addFallbacks(fontFamily, normalizeFontData({ |
no test coverage detected