Skip to content

Commit

Permalink
feat: fall back to reading font metrics from remote sources
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Mar 10, 2024
1 parent 541b08d commit 78138b2
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 11 deletions.
10 changes: 8 additions & 2 deletions src/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { fetch } from 'ofetch'
import chalk from 'chalk'
import { defu } from 'defu'
import type { NitroConfig } from 'nitropack'
import { hasProtocol, joinURL } from 'ufo'
import { hasProtocol, joinURL, withTrailingSlash } from 'ufo'
import { extname, join } from 'pathe'
import { filename } from 'pathe/utils'
import { hash } from 'ohash'
Expand Down Expand Up @@ -121,7 +121,13 @@ export function setupPublicAssetStrategy (options: ModuleOptions['assets'] = {})
})
})

return { normalizeFontData }
const base = withTrailingSlash(assetsBaseURL)
function lookupFontURL (url: string) {
if (!url.startsWith(base)) { return }
return renderedFontURLs.get(url.slice(base.length))
}

return { normalizeFontData, lookupFontURL }
}

const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365
11 changes: 5 additions & 6 deletions src/css/render.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { hasProtocol } from 'ufo'
import type { FontSource, NormalizedFontFaceData } from '../types'
import type { FontSource, NormalizedFontFaceData, RemoteFontSource } from '../types'
import { extname } from 'pathe'
import { getMetricsForFamily, generateFontFace as generateFallbackFontFace } from 'fontaine'
import { getMetricsForFamily, generateFontFace as generateFallbackFontFace, readMetrics } from 'fontaine'

export function generateFontFace (family: string, font: NormalizedFontFaceData) {
return [
Expand All @@ -18,12 +18,11 @@ export function generateFontFace (family: string, font: NormalizedFontFaceData)
].filter(Boolean).join('\n')
}

export async function generateFontFallbacks (family: string, data: NormalizedFontFaceData, fallbacks?: Array<{ name: string, font: string }>) {
export async function generateFontFallbacks (family: string, data: NormalizedFontFaceData, fallbacks?: Array<{ name: string, font: string }>, lookupFontURL?: (url: string) => string | undefined) {
if (!fallbacks?.length) return []

// TODO: read metrics from URLs
// const fontURL = data.src!.find(s => 'url' in s) as RemoteFontSource | undefined
const metrics = await getMetricsForFamily(family) // || fontURL && await readMetrics(fontURL.url)
const fontURL = data.src!.find(s => 'url' in s) as RemoteFontSource | undefined
const metrics = await getMetricsForFamily(family) || (fontURL && await readMetrics(lookupFontURL?.(fontURL.url) || fontURL.url))

if (!metrics) return []

Expand Down
3 changes: 2 additions & 1 deletion src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export default defineNuxtModule<ModuleOptions>({
}
})

const { normalizeFontData } = setupPublicAssetStrategy(options.assets)
const { normalizeFontData, lookupFontURL } = setupPublicAssetStrategy(options.assets)

async function resolveFontFaceWithOverride (fontFamily: string, override?: FontFamilyManualOverride | FontFamilyProviderOverride, fallbackOptions?: { fallbacks: string[], generic?: GenericCSSFamily }): Promise<FontFaceResolution | undefined> {
const fallbacks = override?.fallbacks || normalizedDefaults.fallbacks[fallbackOptions?.generic || 'sans-serif']
Expand Down Expand Up @@ -221,6 +221,7 @@ export default defineNuxtModule<ModuleOptions>({

addBuildPlugin(FontFamilyInjectionPlugin({
dev: nuxt.options.dev,
lookupFontURL,
async resolveFontFace (fontFamily, fallbackOptions) {
const override = options.families?.find(f => f.name === fontFamily)

Expand Down
5 changes: 3 additions & 2 deletions src/plugins/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface FontFaceResolution {
}

interface FontFamilyInjectionPluginOptions {
lookupFontURL: (url: string) => string | undefined
resolveFontFace: (fontFamily: string, fallbackOptions?: { fallbacks: string[], generic?: GenericCSSFamily }) => Awaitable<undefined | FontFaceResolution>
dev: boolean
}
Expand All @@ -41,13 +42,13 @@ export const FontFamilyInjectionPlugin = (options: FontFamilyInjectionPluginOpti
fallbacks: fallbackOptions?.fallbacks || []
}) || {}

if (!result.fonts) return
if (!result.fonts || result.fonts.length === 0) return

const fallbackMap = result.fallbacks?.map(f => ({ font: f, name: `${fontFamily} Fallback: ${f}` })) || []
let insertFontFamilies = false

for (const font of result.fonts) {
const fallbackDeclarations = await generateFontFallbacks(fontFamily, font, fallbackMap)
const fallbackDeclarations = await generateFontFallbacks(fontFamily, font, fallbackMap, options.lookupFontURL)
const declarations = [generateFontFace(fontFamily, font), ...fallbackDeclarations]

for (let declaration of declarations) {
Expand Down

0 comments on commit 78138b2

Please sign in to comment.