-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
926720d
commit 4383d37
Showing
18 changed files
with
520 additions
and
57 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* eslint-disable @typescript-eslint/no-non-null-assertion */ | ||
import { transform } from '@babel/core'; | ||
import TransformFontImports from '.'; | ||
|
||
const example = ` | ||
import { Inter, Roboto } from '@next/font/google' | ||
import localFont from '@next/font/local' | ||
const myFont = localFont({ src: './my-font.woff2' }) | ||
const roboto = Roboto({ | ||
weight: '400', | ||
}) | ||
const inter = Inter({ | ||
subsets: ['latin'], | ||
}); | ||
const randomObj = {} | ||
`; | ||
|
||
it('should transform AST properly', () => { | ||
const { code } = transform(example, { plugins: [TransformFontImports] })!; | ||
expect(code).toMatchInlineSnapshot(` | ||
"import inter from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/google\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"subsets\\\\\\":[\\\\\\"latin\\\\\\"]},\\\\\\"fontFamily\\\\\\":\\\\\\"Inter\\\\\\"}!@next/font/google\\"; | ||
import roboto from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/google\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"weight\\\\\\":\\\\\\"400\\\\\\"},\\\\\\"fontFamily\\\\\\":\\\\\\"Roboto\\\\\\"}!@next/font/google\\"; | ||
import myFont from \\"storybook-nextjs-font-loader?{\\\\\\"source\\\\\\":\\\\\\"@next/font/local\\\\\\",\\\\\\"props\\\\\\":{\\\\\\"src\\\\\\":\\\\\\"./my-font.woff2\\\\\\"},\\\\\\"fontFamily\\\\\\":\\\\\\"localFont\\\\\\"}!@next/font/local\\"; | ||
const randomObj = {};" | ||
`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
code/frameworks/nextjs/src/font/webpack/configureNextFont.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { Configuration } from 'webpack'; | ||
import VirtualLocalFontModulePlugin from './plugin/virtual-local-font-module'; | ||
|
||
export function configureNextFont(baseConfig: Configuration) { | ||
baseConfig.plugins = [...(baseConfig.plugins || []), new VirtualLocalFontModulePlugin()]; | ||
baseConfig.resolveLoader = { | ||
...baseConfig.resolveLoader, | ||
alias: { | ||
...baseConfig.resolveLoader?.alias, | ||
'storybook-nextjs-font-loader': require.resolve( | ||
'./font/webpack/loader/storybook-nextjs-font-loader' | ||
), | ||
}, | ||
}; | ||
} |
47 changes: 47 additions & 0 deletions
47
code/frameworks/nextjs/src/font/webpack/loader/google/get-font-face-declarations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { | ||
fetchCSSFromGoogleFonts, | ||
getFontAxes, | ||
getUrl, | ||
validateData, | ||
} from '@next/font/dist/google/utils'; | ||
import loaderUtils from 'next/dist/compiled/loader-utils3'; | ||
|
||
import type { LoaderOptions } from '../types'; | ||
|
||
const cssCache = new Map<string, Promise<string>>(); | ||
|
||
export async function getFontFaceDeclarations(options: LoaderOptions) { | ||
const { fontFamily, weights, styles, selectedVariableAxes, display, variable } = validateData( | ||
options.fontFamily, | ||
[options.props] | ||
); | ||
|
||
const fontAxes = getFontAxes(fontFamily, weights, styles, selectedVariableAxes); | ||
const url = getUrl(fontFamily, fontAxes, display); | ||
|
||
try { | ||
const hasCachedCSS = cssCache.has(url); | ||
const fontFaceCSS = hasCachedCSS | ||
? cssCache.get(url) | ||
: await fetchCSSFromGoogleFonts(url, fontFamily).catch(() => null); | ||
if (!hasCachedCSS) { | ||
cssCache.set(url, fontFaceCSS); | ||
} else { | ||
cssCache.delete(url); | ||
} | ||
if (fontFaceCSS === null) { | ||
throw Error(`Failed to fetch \`${fontFamily}\` from Google Fonts.`); | ||
} | ||
|
||
return { | ||
id: loaderUtils.getHashDigest(url, 'md5', 'hex', 6), | ||
fontFamily, | ||
fontFaceCSS, | ||
weights, | ||
styles, | ||
variable, | ||
}; | ||
} catch (error) { | ||
throw new Error("Google Fonts couldn't be loaded."); | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
code/frameworks/nextjs/src/font/webpack/loader/local/get-font-face-declarations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import loaderUtils from 'next/dist/compiled/loader-utils3'; | ||
import { validateData } from '@next/font/dist/local/utils'; | ||
import path from 'path'; | ||
|
||
import type { LoaderOptions } from '../types'; | ||
|
||
type LocalFontSrc = string | Array<{ path: string; weight?: string; style?: string }>; | ||
|
||
export async function getFontFaceDeclarations(options: LoaderOptions, rootContext: string) { | ||
const localFontSrc = options.props.src as LocalFontSrc; | ||
|
||
// Parent folder relative to the root context | ||
const parentFolder = options.filename.split('/').slice(0, -1).join('/').replace(rootContext, ''); | ||
|
||
const { weight, style, variable } = validateData('', options.props); | ||
|
||
const id = `font-${loaderUtils.getHashDigest( | ||
Buffer.from(JSON.stringify(localFontSrc)), | ||
'md5', | ||
'hex', | ||
6 | ||
)}`; | ||
|
||
const getFontFaceCSS = () => { | ||
if (typeof localFontSrc === 'string') { | ||
const localFontPath = path.join(parentFolder, localFontSrc); | ||
|
||
return `@font-face { | ||
font-family: ${id}; | ||
src: url(${localFontPath}); | ||
}`; | ||
} | ||
return localFontSrc | ||
.map((font) => { | ||
const localFontPath = path.join(parentFolder, font.path); | ||
|
||
return `@font-face { | ||
font-family: ${id}; | ||
src: url(${localFontPath}); | ||
${font.weight ? `font-weight: ${font.weight};` : ''} | ||
${font.style ? `font-style: ${font.style};` : ''} | ||
}`; | ||
}) | ||
.join(''); | ||
}; | ||
|
||
return { | ||
id, | ||
fontFamily: id, | ||
fontFaceCSS: getFontFaceCSS(), | ||
weights: weight ? [weight] : [], | ||
styles: style ? [style] : [], | ||
variable, | ||
}; | ||
} |
51 changes: 51 additions & 0 deletions
51
code/frameworks/nextjs/src/font/webpack/loader/storybook-nextjs-font-loader.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { getFontFaceDeclarations as getGoogleFontFaceDeclarations } from './google/get-font-face-declarations'; | ||
import { getFontFaceDeclarations as getLocalFontFaceDeclarations } from './local/get-font-face-declarations'; | ||
import type { LoaderOptions } from './types'; | ||
import { getCSSMeta } from './utils/get-css-meta'; | ||
import { setFontDeclarationsInHead } from './utils/set-font-declarations-in-head'; | ||
|
||
type FontFaceDeclaration = { | ||
id: string; | ||
fontFamily: string; | ||
fontFaceCSS: any; | ||
weights: string[]; | ||
styles: string[]; | ||
variable?: string; | ||
}; | ||
|
||
export default async function storybookNextjsFontLoader(this: any) { | ||
const options = this.getOptions() as LoaderOptions; | ||
|
||
// get execution context | ||
const rootCtx = this.rootContext; | ||
|
||
let fontFaceDeclaration: FontFaceDeclaration | undefined; | ||
|
||
if (options.source === '@next/font/google') { | ||
fontFaceDeclaration = await getGoogleFontFaceDeclarations(options); | ||
} | ||
|
||
if (options.source === '@next/font/local') { | ||
fontFaceDeclaration = await getLocalFontFaceDeclarations(options, rootCtx); | ||
} | ||
|
||
if (typeof fontFaceDeclaration !== 'undefined') { | ||
const cssMeta = getCSSMeta(fontFaceDeclaration); | ||
|
||
return ` | ||
${setFontDeclarationsInHead({ | ||
fontFaceCSS: cssMeta.fontFaceCSS, | ||
id: fontFaceDeclaration.id, | ||
classNamesCSS: cssMeta.classNamesCSS, | ||
})} | ||
module.exports = { | ||
className: "${cssMeta.className}", | ||
style: ${JSON.stringify(cssMeta.style)} | ||
${cssMeta.variableClassName ? `, variable: "${cssMeta.variableClassName}"` : ''} | ||
} | ||
`; | ||
} | ||
|
||
return `module.exports = {}`; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
export type LoaderOptions = { | ||
/** | ||
* Initial import name. Can be `@next/font/google` or `@next/font/local` | ||
*/ | ||
source: string; | ||
/** | ||
* Props passed to the `@next/font` function call | ||
*/ | ||
props: Record<string, any>; | ||
/** | ||
* Font Family name | ||
*/ | ||
fontFamily: string; | ||
/** | ||
* Filename of the issuer file, which imports `@next/font/google` or `@next/font/local | ||
*/ | ||
filename: string; | ||
}; |
Oops, something went wrong.