Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for fallback font and css variable for font/local #40990

Merged
merged 10 commits into from Sep 28, 2022
30 changes: 23 additions & 7 deletions packages/font/src/google/loader.ts
@@ -1,8 +1,8 @@
import type { FontLoader } from 'next/font'
import type { AdjustFontFallback, FontLoader } from 'next/font'
// @ts-ignore
import fetch from 'next/dist/compiled/node-fetch'
// @ts-ignore
import { calculateOverrideCSS } from 'next/dist/server/font-utils'
import { calculateOverrideValues } from 'next/dist/server/font-utils'
import {
fetchCSSFromGoogleFonts,
getFontAxes,
Expand Down Expand Up @@ -97,20 +97,36 @@ const downloadGoogleFonts: FontLoader = async ({
}

// Add fallback font
let adjustFontFallbackMetrics: AdjustFontFallback | undefined
if (adjustFontFallback) {
try {
updatedCssResponse += calculateOverrideCSS(
fontFamily,
require('next/dist/server/google-font-metrics.json')
const { ascent, descent, lineGap, fallbackFont } =
calculateOverrideValues(
fontFamily,
require('next/dist/server/google-font-metrics.json')
)
adjustFontFallbackMetrics = {
fallbackFont,
ascentOverride: ascent,
descentOverride: descent,
lineGapOverride: lineGap,
}
} catch {
console.error(
`Failed to find font override values for font \`${fontFamily}\``
)
} catch (e) {
console.log('Error getting font override values - ', e)
}
}

return {
css: updatedCssResponse,
fallbackFonts: fallback,
weight: weight === 'variable' ? undefined : weight,
style,
variable: `--next-font-${fontFamily.toLowerCase().replace(/ /g, '-')}${
weight !== 'variable' ? `-${weight}` : ''
}${style === 'italic' ? `-italic` : ''}`,
adjustFontFallback: adjustFontFallbackMetrics,
}
}

Expand Down
9 changes: 6 additions & 3 deletions packages/font/src/local/index.ts
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import type { FontModule } from 'next/font'
import type { AdjustFontFallback, FontModule } from 'next/font'
type Display = 'auto' | 'block' | 'swap' | 'fallback' | 'optional'
type LocalFont = {
src: string | Array<{ file: string; unicodeRange: string }>
Expand All @@ -8,15 +8,18 @@ type LocalFont = {
style?: string
fallback?: string[]
preload?: boolean
variable?: string

ascentOverride?: string
descentOverride?: string
fontStretch?: string
fontVariant?: string
fontFeatureSettings?: string
fontVariationSettings?: string
ascentOverride?: string
descentOverride?: string
lineGapOverride?: string
sizeAdjust?: string

adjustFontFallback?: AdjustFontFallback
}

export default function localFont(options: LocalFont): FontModule {
Expand Down
6 changes: 6 additions & 0 deletions packages/font/src/local/loader.ts
Expand Up @@ -18,12 +18,14 @@ const fetchFonts: FontLoader = async ({
style,
fallback,
preload,
variable,
ascentOverride,
descentOverride,
lineGapOverride,
fontStretch,
fontFeatureSettings,
sizeAdjust,
adjustFontFallback,
} = validateData(functionName, data)

const fontFaces = await Promise.all(
Expand Down Expand Up @@ -61,6 +63,10 @@ ${fontFaceProperties
return {
css: fontFaces.join('\n'),
fallbackFonts: fallback,
weight,
style,
variable,
adjustFontFallback,
}
}

Expand Down
8 changes: 8 additions & 0 deletions packages/font/src/local/utils.ts
@@ -1,3 +1,5 @@
import { AdjustFontFallback } from 'next/font'

const allowedDisplayValues = ['auto', 'block', 'swap', 'fallback', 'optional']

const formatValues = (values: string[]) =>
Expand All @@ -24,6 +26,7 @@ type FontOptions = {
style?: string
fallback?: string[]
preload: boolean
variable?: string
ascentOverride?: string
descentOverride?: string
fontStretch?: string
Expand All @@ -32,6 +35,7 @@ type FontOptions = {
fontVariationSettings?: string
lineGapOverride?: string
sizeAdjust?: string
adjustFontFallback?: AdjustFontFallback
}
export function validateData(functionName: string, data: any): FontOptions {
if (functionName) {
Expand All @@ -44,6 +48,7 @@ export function validateData(functionName: string, data: any): FontOptions {
style,
fallback,
preload = true,
variable,
ascentOverride,
descentOverride,
fontStretch,
Expand All @@ -52,6 +57,7 @@ export function validateData(functionName: string, data: any): FontOptions {
fontVariationSettings,
lineGapOverride,
sizeAdjust,
adjustFontFallback,
} = data[0] || ({} as any)

if (!allowedDisplayValues.includes(display)) {
Expand Down Expand Up @@ -100,6 +106,7 @@ export function validateData(functionName: string, data: any): FontOptions {
style,
fallback,
preload,
variable,
ascentOverride,
descentOverride,
fontStretch,
Expand All @@ -108,5 +115,6 @@ export function validateData(functionName: string, data: any): FontOptions {
fontVariationSettings,
lineGapOverride,
sizeAdjust,
adjustFontFallback,
}
}
44 changes: 30 additions & 14 deletions packages/next/build/webpack/loaders/next-font-loader/index.ts
Expand Up @@ -43,18 +43,21 @@ export default async function nextFontLoader(this: any) {
this.resourcePath,
'../loader.js'
)).default
let { css, fallbackFonts } = await fontLoader({
functionName,
data,
config: fontLoaderOptions,
emitFontFile,
resolve: (src: string) =>
promisify(this.resolve)(
path.dirname(path.join(this.rootContext, relativeFilePathFromRoot)),
src
),
fs: this.fs,
})
let { css, fallbackFonts, adjustFontFallback, weight, style, variable } =
await fontLoader({
functionName,
data,
config: fontLoaderOptions,
emitFontFile,
resolve: (src: string) =>
promisify(this.resolve)(
path.dirname(
path.join(this.rootContext, relativeFilePathFromRoot)
),
src
),
fs: this.fs,
})

const { postcss } = await getPostcss()

Expand All @@ -68,7 +71,15 @@ export default async function nextFontLoader(this: any) {
)
// Add CSS classes, exports and make the font-family localy scoped by turning it unguessable
const result = await postcss(
postcssFontLoaderPlugn(exports, fontFamilyHash, fallbackFonts)
postcssFontLoaderPlugn({
exports,
fontFamilyHash,
fallbackFonts,
weight,
style,
adjustFontFallback,
variable,
})
).process(css, {
from: undefined,
})
Expand All @@ -79,9 +90,14 @@ export default async function nextFontLoader(this: any) {
version: result.processor.version,
root: result.root,
}
callback(null, result.css, null, { exports, ast, fontFamilyHash })
callback(null, result.css, null, {
exports,
ast,
fontFamilyHash,
})
} catch (err: any) {
err.stack = false
err.message = `Font loader error:\n${err.message}`
err.message += `

${chalk.cyan(`Location: ${relativeFilePathFromRoot}`)}`
Expand Down