From 10869c6992c11008feb7067d2b057a132f64c0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:17:15 +0100 Subject: [PATCH 01/14] Add @next/font as dep in next --- packages/next/package.json | 1 + pnpm-lock.yaml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/next/package.json b/packages/next/package.json index 6cf9cccd898f8..f4023db19c545 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -78,6 +78,7 @@ }, "dependencies": { "@next/env": "13.1.7-canary.7", + "@next/font": "13.1.7-canary.7", "@swc/helpers": "0.4.14", "caniuse-lite": "^1.0.30001406", "postcss": "8.4.14", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2320023395d96..6ad693d86d0af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -511,6 +511,7 @@ importers: '@napi-rs/cli': 2.13.3 '@napi-rs/triples': 1.1.0 '@next/env': 13.1.7-canary.7 + '@next/font': 13.1.7-canary.7 '@next/polyfill-module': 13.1.7-canary.7 '@next/polyfill-nomodule': 13.1.7-canary.7 '@next/react-dev-overlay': 13.1.7-canary.7 @@ -685,6 +686,7 @@ importers: ws: 8.2.3 dependencies: '@next/env': link:../next-env + '@next/font': link:../font '@swc/helpers': 0.4.14 caniuse-lite: 1.0.30001406 fibers: 5.0.3 From a3f359ec77218eeb78d0fa5037b55c014eda2ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:18:24 +0100 Subject: [PATCH 02/14] Reexport @next/font in next/font --- packages/next/font/google/index.d.ts | 1 + packages/next/font/google/index.js | 3 --- packages/next/font/google/loader.js | 1 + packages/next/font/google/target.css | 1 + packages/next/font/index.js | 3 --- packages/next/font/local/index.d.ts | 1 + packages/next/font/local/index.js | 3 --- packages/next/font/local/loader.js | 1 + packages/next/font/local/target.css | 1 + 9 files changed, 6 insertions(+), 9 deletions(-) create mode 100644 packages/next/font/google/index.d.ts create mode 100644 packages/next/font/google/loader.js create mode 100644 packages/next/font/google/target.css delete mode 100644 packages/next/font/index.js create mode 100644 packages/next/font/local/index.d.ts create mode 100644 packages/next/font/local/loader.js create mode 100644 packages/next/font/local/target.css diff --git a/packages/next/font/google/index.d.ts b/packages/next/font/google/index.d.ts new file mode 100644 index 0000000000000..455eb96a8e31b --- /dev/null +++ b/packages/next/font/google/index.d.ts @@ -0,0 +1 @@ +export * from '@next/font/dist/google' diff --git a/packages/next/font/google/index.js b/packages/next/font/google/index.js index dbd5f2de02bb4..e69de29bb2d1d 100644 --- a/packages/next/font/google/index.js +++ b/packages/next/font/google/index.js @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font/google`, did you mean `@next/font/google`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/google/loader.js b/packages/next/font/google/loader.js new file mode 100644 index 0000000000000..ea72adc944a4f --- /dev/null +++ b/packages/next/font/google/loader.js @@ -0,0 +1 @@ +module.exports = require('@next/font/dist/google/loader') diff --git a/packages/next/font/google/target.css b/packages/next/font/google/target.css new file mode 100644 index 0000000000000..e3eb179b3405e --- /dev/null +++ b/packages/next/font/google/target.css @@ -0,0 +1 @@ +/* target file for webpack loader */ diff --git a/packages/next/font/index.js b/packages/next/font/index.js deleted file mode 100644 index 829031b71436c..0000000000000 --- a/packages/next/font/index.js +++ /dev/null @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font`, did you mean `@next/font`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/local/index.d.ts b/packages/next/font/local/index.d.ts new file mode 100644 index 0000000000000..1ee8bfd766390 --- /dev/null +++ b/packages/next/font/local/index.d.ts @@ -0,0 +1 @@ +export { default } from '@next/font/dist/local' diff --git a/packages/next/font/local/index.js b/packages/next/font/local/index.js index 50a6649791c4f..e69de29bb2d1d 100644 --- a/packages/next/font/local/index.js +++ b/packages/next/font/local/index.js @@ -1,3 +0,0 @@ -throw new Error( - 'You tried to import `next/font/local`, did you mean `@next/font/local`?\nRead more: https://nextjs.org/docs/basic-features/font-optimization' -) diff --git a/packages/next/font/local/loader.js b/packages/next/font/local/loader.js new file mode 100644 index 0000000000000..e29e59c52cb13 --- /dev/null +++ b/packages/next/font/local/loader.js @@ -0,0 +1 @@ +module.exports = require('@next/font/dist/local/loader') diff --git a/packages/next/font/local/target.css b/packages/next/font/local/target.css new file mode 100644 index 0000000000000..e3eb179b3405e --- /dev/null +++ b/packages/next/font/local/target.css @@ -0,0 +1 @@ +/* target file for webpack loader */ From 4428f6276df6fa975e9b77b55d3d61f359bdd1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:19:40 +0100 Subject: [PATCH 03/14] Remove default config --- packages/next/src/server/config-shared.ts | 36 ----------------------- packages/next/src/server/config.ts | 36 ----------------------- 2 files changed, 72 deletions(-) diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index 1f2b867981c3f..3fd624924c9d5 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -629,42 +629,6 @@ export const defaultConfig: NextConfig = { }, } -export function setFontLoaderDefaults(config: NextConfig) { - try { - // eslint-disable-next-line import/no-extraneous-dependencies - require('@next/font/package.json') - - const googleFontLoader = { - loader: '@next/font/google', - } - const localFontLoader = { - loader: '@next/font/local', - } - if (!config.experimental) { - config.experimental = {} - } - if (!config.experimental.fontLoaders) { - config.experimental.fontLoaders = [] - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === googleFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(googleFontLoader) - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === localFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(localFontLoader) - } - } catch {} -} - -setFontLoaderDefaults(defaultConfig) - export async function normalizeConfig(phase: string, config: any) { if (typeof config === 'function') { config = config(phase, { defaultConfig }) diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index 7d152df002e59..631740c0b16c1 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -95,40 +95,6 @@ export function setHttpClientAndAgentOptions( ) } -function setFontLoaderDefaults(config: NextConfigComplete) { - try { - // eslint-disable-next-line import/no-extraneous-dependencies - require('@next/font/package.json') - - const googleFontLoader = { - loader: '@next/font/google', - } - const localFontLoader = { - loader: '@next/font/local', - } - if (!config.experimental) { - config.experimental = {} - } - if (!config.experimental.fontLoaders) { - config.experimental.fontLoaders = [] - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === googleFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(googleFontLoader) - } - if ( - !config.experimental.fontLoaders.find( - ({ loader }: any) => loader === localFontLoader.loader - ) - ) { - config.experimental.fontLoaders.push(localFontLoader) - } - } catch {} -} - export function warnOptionHasBeenMovedOutOfExperimental( config: NextConfig, oldKey: string, @@ -973,7 +939,6 @@ export default async function loadConfig( }, silent ) as NextConfigComplete - setFontLoaderDefaults(completeConfig) return completeConfig } else { const configBaseName = basename(CONFIG_FILES[0], extname(CONFIG_FILES[0])) @@ -1004,6 +969,5 @@ export default async function loadConfig( ) as NextConfigComplete completeConfig.configFileName = configFileName setHttpClientAndAgentOptions(completeConfig, silent) - setFontLoaderDefaults(completeConfig) return completeConfig } From 07629d77ae14cc3515a3e2c5461154b4e8304df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:22:49 +0100 Subject: [PATCH 04/14] Configure webpack loaders --- packages/next/src/build/webpack-config.ts | 7 -- .../build/webpack/config/blocks/css/index.ts | 68 ++++++++++++------- .../config/blocks/css/loaders/next-font.ts | 2 + .../webpack/loaders/next-font-loader/index.ts | 6 +- 4 files changed, 46 insertions(+), 37 deletions(-) diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index 05ded9851d1a9..a6e8f33ee385c 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -1364,13 +1364,6 @@ export default async function getBaseWebpackConfig( }, } - const fontLoaderTargets = - config.experimental.fontLoaders && - config.experimental.fontLoaders.map(({ loader }) => { - const resolved = require.resolve(loader) - return path.join(resolved, '../target.css') - }) - let webpackConfig: webpack.Configuration = { parallelism: Number(process.env.NEXT_WEBPACK_PARALLELISM) || undefined, ...(isNodeServer ? { externalsPresets: { node: true } } : {}), diff --git a/packages/next/src/build/webpack/config/blocks/css/index.ts b/packages/next/src/build/webpack/config/blocks/css/index.ts index 486857a7ac766..23af18b6bcdba 100644 --- a/packages/next/src/build/webpack/config/blocks/css/index.ts +++ b/packages/next/src/build/webpack/config/blocks/css/index.ts @@ -173,32 +173,48 @@ export const css = curry(async function css( const fns: ConfigurationFn[] = [] - // Resolve the configured font loaders, the resolved files are noop files that next-font-loader will match - let fontLoaders: [string, string][] | undefined = ctx.experimental.fontLoaders - ? ctx.experimental.fontLoaders.map(({ loader: fontLoader, options }) => [ - path.join(require.resolve(fontLoader), '../target.css'), - options, - ]) - : undefined - - fontLoaders?.forEach(([fontLoaderPath, fontLoaderOptions]) => { - // Matches the resolved font loaders noop files to run next-font-loader - fns.push( - loader({ - oneOf: [ - markRemovable({ - sideEffects: false, - test: fontLoaderPath, - use: getNextFontLoader( - ctx, - lazyPostCSSInitializer, - fontLoaderOptions - ), - }), - ], - }) - ) - }) + const googleLoaderOptions = + ctx.experimental?.fontLoaders?.find( + (loaderConfig) => loaderConfig.loader === '@next/font/google' + )?.options ?? {} + const fontLoaders: Array<[string | RegExp, string, any?]> = [ + [ + require.resolve('next/font/google/target.css'), + '@next/font/google/loader', + googleLoaderOptions, + ], + [require.resolve('next/font/local/target.css'), '@next/font/local/loader'], + + // TODO: remove this in the next major version + [ + /node_modules\/@next\/font\/google\/target.css/, + '@next/font/google/loader', + googleLoaderOptions, + ], + [/node_modules\/@next\/font\/local\/target.css/, '@next/font/local/loader'], + ] + + fontLoaders.forEach( + ([fontLoaderTarget, fontLoaderPath, fontLoaderOptions]) => { + // Matches the resolved font loaders noop files to run next-font-loader + fns.push( + loader({ + oneOf: [ + markRemovable({ + sideEffects: false, + test: fontLoaderTarget, + use: getNextFontLoader( + ctx, + lazyPostCSSInitializer, + fontLoaderPath, + fontLoaderOptions + ), + }), + ], + }) + ) + } + ) // CSS cannot be imported in _document. This comes before everything because // global CSS nor CSS modules work in said file. diff --git a/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts b/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts index 67440b8c6625f..b3273ba97c650 100644 --- a/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts +++ b/packages/next/src/build/webpack/config/blocks/css/loaders/next-font.ts @@ -6,6 +6,7 @@ import { cssFileResolve } from './file-resolve' export function getNextFontLoader( ctx: ConfigurationContext, postcss: any, + fontLoaderPath: string, fontLoaderOptions: any ): webpack.RuleSetUseItem[] { const loaders: webpack.RuleSetUseItem[] = [] @@ -62,6 +63,7 @@ export function getNextFontLoader( isDev: ctx.isDevelopment, isServer: ctx.isServer, assetPrefix: ctx.assetPrefix, + fontLoaderPath, fontLoaderOptions, postcss, }, diff --git a/packages/next/src/build/webpack/loaders/next-font-loader/index.ts b/packages/next/src/build/webpack/loaders/next-font-loader/index.ts index be7c30463e04f..d5bf2f4d6024b 100644 --- a/packages/next/src/build/webpack/loaders/next-font-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-font-loader/index.ts @@ -37,6 +37,7 @@ export default async function nextFontLoader(this: any) { isDev, isServer, assetPrefix, + fontLoaderPath, fontLoaderOptions, postcss: getPostcss, } = this.getOptions() @@ -82,10 +83,7 @@ export default async function nextFontLoader(this: any) { } try { - const fontLoader: FontLoader = require(path.join( - this.resourcePath, - '../loader.js' - )).default + const fontLoader: FontLoader = require(fontLoaderPath).default let { css, fallbackFonts, adjustFontFallback, weight, style, variable } = await fontLoader({ functionName, From 7b404e26f59b472dfb8f3a7630c8d703f98d65ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:23:31 +0100 Subject: [PATCH 05/14] Update next-swc options --- packages/next/src/build/swc/options.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/next/src/build/swc/options.ts b/packages/next/src/build/swc/options.ts index 274f5a10939bc..7499ec9c47c7c 100644 --- a/packages/next/src/build/swc/options.ts +++ b/packages/next/src/build/swc/options.ts @@ -250,14 +250,16 @@ any) { hasServerComponents, isServerLayer, }) + baseOptions.fontLoaders = { + fontLoaders: [ + 'next/font/local', + 'next/font/google', - if (nextConfig?.experimental?.fontLoaders && relativeFilePathFromRoot) { - baseOptions.fontLoaders = { - fontLoaders: nextConfig.experimental.fontLoaders.map( - ({ loader }: any) => loader - ), - relativeFilePathFromRoot, - } + // TODO: remove this in the next major version + '@next/font/local', + '@next/font/google', + ], + relativeFilePathFromRoot, } const isNextDist = nextDistPath.test(filename) From 0cd4bbdce595abefc6a507c7eb89352945b1ff3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:28:16 +0100 Subject: [PATCH 06/14] Always generate font-loader-manifest --- packages/next/src/build/entries.ts | 1 - packages/next/src/build/index.ts | 8 ++----- packages/next/src/build/webpack-config.ts | 3 --- .../loaders/next-edge-ssr-loader/index.ts | 6 +---- .../plugins/font-loader-manifest-plugin.ts | 21 ++++++++++------- .../webpack/plugins/middleware-plugin.ts | 23 ++++--------------- packages/next/src/export/index.ts | 8 ++++--- packages/next/src/server/base-server.ts | 4 +--- packages/next/src/server/next-server.ts | 1 - 9 files changed, 27 insertions(+), 48 deletions(-) diff --git a/packages/next/src/build/entries.ts b/packages/next/src/build/entries.ts index af20875bc0fc3..1ce9f4c92aee4 100644 --- a/packages/next/src/build/entries.ts +++ b/packages/next/src/build/entries.ts @@ -199,7 +199,6 @@ export function getEdgeServerEntry(opts: { pagesType: opts.pagesType, appDirLoader: Buffer.from(opts.appDirLoader || '').toString('base64'), sriEnabled: !opts.isDev && !!opts.config.experimental.sri?.algorithm, - hasFontLoaders: !!opts.config.experimental.fontLoaders, } return { diff --git a/packages/next/src/build/index.ts b/packages/next/src/build/index.ts index 91597f1f5382c..e57db75c8df34 100644 --- a/packages/next/src/build/index.ts +++ b/packages/next/src/build/index.ts @@ -912,12 +912,8 @@ export default async function build( : null, BUILD_ID_FILE, appDir ? path.join(SERVER_DIRECTORY, APP_PATHS_MANIFEST) : null, - ...(config.experimental.fontLoaders - ? [ - path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.js'), - path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.json'), - ] - : []), + path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.js'), + path.join(SERVER_DIRECTORY, FONT_LOADER_MANIFEST + '.json'), ] .filter(nonNullable) .map((file) => path.join(config.distDir, file)), diff --git a/packages/next/src/build/webpack-config.ts b/packages/next/src/build/webpack-config.ts index a6e8f33ee385c..08c09fa4b2ca2 100644 --- a/packages/next/src/build/webpack-config.ts +++ b/packages/next/src/build/webpack-config.ts @@ -2086,7 +2086,6 @@ export default async function getBaseWebpackConfig( new MiddlewarePlugin({ dev, sriEnabled: !dev && !!config.experimental.sri?.algorithm, - hasFontLoaders: !!config.experimental.fontLoaders, }), isClient && new BuildManifestPlugin({ @@ -2151,10 +2150,8 @@ export default async function getBaseWebpackConfig( !!config.experimental.sri?.algorithm && new SubresourceIntegrityPlugin(config.experimental.sri.algorithm), isClient && - fontLoaderTargets && new FontLoaderManifestPlugin({ appDirEnabled: !!config.experimental.appDir, - fontLoaderTargets, }), !dev && isClient && diff --git a/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts b/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts index 59ebcf17f55d1..1de9b6617a398 100644 --- a/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts +++ b/packages/next/src/build/webpack/loaders/next-edge-ssr-loader/index.ts @@ -15,7 +15,6 @@ export type EdgeSSRLoaderQuery = { appDirLoader?: string pagesType: 'app' | 'pages' | 'root' sriEnabled: boolean - hasFontLoaders: boolean } /* @@ -45,7 +44,6 @@ export default async function edgeSSRLoader(this: any) { appDirLoader: appDirLoaderBase64, pagesType, sriEnabled, - hasFontLoaders, } = this.getOptions() const appDirLoader = Buffer.from( @@ -127,9 +125,7 @@ export default async function edgeSSRLoader(this: any) { const subresourceIntegrityManifest = ${ sriEnabled ? 'self.__SUBRESOURCE_INTEGRITY_MANIFEST' : 'undefined' } - const fontLoaderManifest = ${ - hasFontLoaders ? 'self.__FONT_LOADER_MANIFEST' : 'undefined' - } + const fontLoaderManifest = self.__FONT_LOADER_MANIFEST const render = getRender({ pageType, diff --git a/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts b/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts index 898f5140129ee..465ab4c8ff120 100644 --- a/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts +++ b/packages/next/src/build/webpack/plugins/font-loader-manifest-plugin.ts @@ -14,17 +14,20 @@ export type FontLoaderManifest = { } const PLUGIN_NAME = 'FontLoaderManifestPlugin' +const fontLoaderTargets = [ + require.resolve('next/font/google/target.css'), + require.resolve('next/font/local/target.css'), + // TODO: remove this in the next major version + /node_modules\/@next\/font\/google\/target\.css\?{.+}$/, + /node_modules\/@next\/font\/local\/target\.css\?{.+}$/, +] + // Creates a manifest of all fonts that should be preloaded given a route export class FontLoaderManifestPlugin { private appDirEnabled: boolean - private fontLoaderTargets: string[] - constructor(options: { - appDirEnabled: boolean - fontLoaderTargets: string[] - }) { + constructor(options: { appDirEnabled: boolean }) { this.appDirEnabled = options.appDirEnabled - this.fontLoaderTargets = options.fontLoaderTargets } apply(compiler: webpack.Compiler) { @@ -36,8 +39,10 @@ export class FontLoaderManifestPlugin { compilation.hooks.finishModules.tap(PLUGIN_NAME, (modules) => { const modulesArr = Array.from(modules) fontLoaderModules = modulesArr.filter((mod: any) => - this.fontLoaderTargets.some((fontLoaderTarget) => - mod.userRequest?.startsWith(`${fontLoaderTarget}?`) + fontLoaderTargets.some((fontLoaderTarget) => + typeof fontLoaderTarget === 'string' + ? mod.userRequest?.startsWith(`${fontLoaderTarget}?`) + : fontLoaderTarget.test(mod.userRequest) ) ) }) diff --git a/packages/next/src/build/webpack/plugins/middleware-plugin.ts b/packages/next/src/build/webpack/plugins/middleware-plugin.ts index 0b957799c0069..1bf5761db5e85 100644 --- a/packages/next/src/build/webpack/plugins/middleware-plugin.ts +++ b/packages/next/src/build/webpack/plugins/middleware-plugin.ts @@ -90,7 +90,7 @@ function isUsingIndirectEvalAndUsedByExports(args: { function getEntryFiles( entryFiles: string[], meta: EntryMetadata, - opts: { sriEnabled: boolean; hasFontLoaders: boolean } + opts: { sriEnabled: boolean } ) { const files: string[] = [] if (meta.edgeSSR) { @@ -120,9 +120,7 @@ function getEntryFiles( `server/${MIDDLEWARE_REACT_LOADABLE_MANIFEST}.js` ) - if (opts.hasFontLoaders) { - files.push(`server/${FONT_LOADER_MANIFEST}.js`) - } + files.push(`server/${FONT_LOADER_MANIFEST}.js`) } files.push( @@ -136,7 +134,7 @@ function getEntryFiles( function getCreateAssets(params: { compilation: webpack.Compilation metadataByEntry: Map - opts: { sriEnabled: boolean; hasFontLoaders: boolean } + opts: { sriEnabled: boolean } }) { const { compilation, metadataByEntry, opts } = params return (assets: any) => { @@ -787,20 +785,10 @@ function getExtractMetadata(params: { export default class MiddlewarePlugin { private readonly dev: boolean private readonly sriEnabled: boolean - private readonly hasFontLoaders: boolean - - constructor({ - dev, - sriEnabled, - hasFontLoaders, - }: { - dev: boolean - sriEnabled: boolean - hasFontLoaders: boolean - }) { + + constructor({ dev, sriEnabled }: { dev: boolean; sriEnabled: boolean }) { this.dev = dev this.sriEnabled = sriEnabled - this.hasFontLoaders = hasFontLoaders } public apply(compiler: webpack.Compiler) { @@ -845,7 +833,6 @@ export default class MiddlewarePlugin { metadataByEntry, opts: { sriEnabled: this.sriEnabled, - hasFontLoaders: this.hasFontLoaders, }, }) ) diff --git a/packages/next/src/export/index.ts b/packages/next/src/export/index.ts index 79a92a37dd876..f2e8477b4f006 100644 --- a/packages/next/src/export/index.ts +++ b/packages/next/src/export/index.ts @@ -404,9 +404,11 @@ export default async function exportApp( optimizeFonts: nextConfig.optimizeFonts as FontConfig, largePageDataBytes: nextConfig.experimental.largePageDataBytes, serverComponents: hasAppDir, - fontLoaderManifest: nextConfig.experimental.fontLoaders - ? require(join(distDir, 'server', `${FONT_LOADER_MANIFEST}.json`)) - : undefined, + fontLoaderManifest: require(join( + distDir, + 'server', + `${FONT_LOADER_MANIFEST}.json` + )), } const { serverRuntimeConfig, publicRuntimeConfig } = nextConfig diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 4cf2d193bf15a..24dfbd4e1f60a 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -376,9 +376,7 @@ export default abstract class Server { this.serverCSSManifest = serverComponents ? this.getServerCSSManifest() : undefined - this.fontLoaderManifest = this.nextConfig.experimental.fontLoaders - ? this.getFontLoaderManifest() - : undefined + this.fontLoaderManifest = this.getFontLoaderManifest() this.renderOpts = { poweredByHeader: this.nextConfig.poweredByHeader, diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index df71efb5662d7..3208154429933 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -1017,7 +1017,6 @@ export default class NextNodeServer extends BaseServer { } protected getFontLoaderManifest() { - if (!this.nextConfig.experimental.fontLoaders) return undefined return require(join(this.distDir, 'server', `${FONT_LOADER_MANIFEST}.json`)) } From a08d790d33bb9d9955ea7f3641404212af893b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:32:32 +0100 Subject: [PATCH 07/14] Update babel error --- errors/babel-font-loader-conflict.md | 4 ++-- .../src/build/babel/plugins/next-font-unsupported.ts | 11 +++++++---- test/production/next-font/babel-unsupported.test.ts | 5 +---- .../next-font/babel-unsupported/pages/index.js | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/errors/babel-font-loader-conflict.md b/errors/babel-font-loader-conflict.md index 00fb535e0b869..3f078db3abc25 100644 --- a/errors/babel-font-loader-conflict.md +++ b/errors/babel-font-loader-conflict.md @@ -1,8 +1,8 @@ -# Babel and `@next/font` conflict +# Babel and `next/font` conflict #### Why This Error Occurred -You have tried to use `@next/font` with a custom babel config. When your application has a custom babel config you opt-out of the Next.js Compiler which is required to use `@next/font`. +You have tried to use `next/font` with a custom babel config. When your application has a custom babel config you opt-out of the Next.js Compiler which is required to use `next/font`. #### Possible Ways to Fix It diff --git a/packages/next/src/build/babel/plugins/next-font-unsupported.ts b/packages/next/src/build/babel/plugins/next-font-unsupported.ts index dd17ebf551f1f..49dc853ea3e64 100644 --- a/packages/next/src/build/babel/plugins/next-font-unsupported.ts +++ b/packages/next/src/build/babel/plugins/next-font-unsupported.ts @@ -5,12 +5,15 @@ export default function NextPageDisallowReExportAllExports(): PluginObj { visitor: { ImportDeclaration(path: NodePath) { if ( - ['@next/font/local', '@next/font/google'].includes( - path.node.source.value - ) + [ + '@next/font/local', + '@next/font/google', + 'next/font/local', + 'next/font/google', + ].includes(path.node.source.value) ) { const err = new SyntaxError( - `"@next/font" requires SWC although Babel is being used due to a custom babel config being present.\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict` + `"next/font" requires SWC although Babel is being used due to a custom babel config being present.\nRead more: https://nextjs.org/docs/messages/babel-font-loader-conflict` ) ;(err as any).code = 'BABEL_PARSE_ERROR' ;(err as any).loc = diff --git a/test/production/next-font/babel-unsupported.test.ts b/test/production/next-font/babel-unsupported.test.ts index 1214ef377b578..ae2fe4868385b 100644 --- a/test/production/next-font/babel-unsupported.test.ts +++ b/test/production/next-font/babel-unsupported.test.ts @@ -9,9 +9,6 @@ describe('@next/fon babel unsupported', () => { next = await createNext({ skipStart: true, files: new FileRef(join(__dirname, 'babel-unsupported')), - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) @@ -21,7 +18,7 @@ describe('@next/fon babel unsupported', () => { 'next build failed with code/signal 1' ) expect(next.cliOutput).toMatch( - /"@next\/font" requires SWC although Babel is being used due to a custom babel config being present./ + /"next\/font" requires SWC although Babel is being used due to a custom babel config being present./ ) }) }) diff --git a/test/production/next-font/babel-unsupported/pages/index.js b/test/production/next-font/babel-unsupported/pages/index.js index a5942d198ea38..cd0c6a8237d0e 100644 --- a/test/production/next-font/babel-unsupported/pages/index.js +++ b/test/production/next-font/babel-unsupported/pages/index.js @@ -1,4 +1,4 @@ -import { Inter } from '@next/font/google' +import { Inter } from 'next/font/google' console.log(Inter) From 8e2467bf9190c2a318586e76afd17191f72f714e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:33:05 +0100 Subject: [PATCH 08/14] Update next/jest --- packages/next/src/build/jest/jest.ts | 2 ++ test/production/jest/index.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/next/src/build/jest/jest.ts b/packages/next/src/build/jest/jest.ts index 9ba1fb0b2a9d5..195fb065dc3c6 100644 --- a/packages/next/src/build/jest/jest.ts +++ b/packages/next/src/build/jest/jest.ts @@ -118,6 +118,8 @@ export default function nextJest(options: { dir?: string } = {}) { // Handle @next/font '@next/font/(.*)': require.resolve('./__mocks__/nextFontMock.js'), + // Handle next/font + 'next/font/(.*)': require.resolve('./__mocks__/nextFontMock.js'), // custom config comes last to ensure the above rules are matched, // fixes the case where @pages/(.*) -> src/pages/$! doesn't break diff --git a/test/production/jest/index.test.ts b/test/production/jest/index.test.ts index 998619bc15892..d17bd3f33db17 100644 --- a/test/production/jest/index.test.ts +++ b/test/production/jest/index.test.ts @@ -21,8 +21,8 @@ describe('next/jest', () => { import Image from "next/image"; import img from "../public/vercel.svg"; import styles from "../styles/index.module.css"; - import localFont from "@next/font/local"; - import { Inter } from "@next/font/google"; + import localFont from "next/font/local"; + import { Inter } from "next/font/google"; const inter = Inter({ subsets: ["latin"] }); const myFont = localFont({ src: "./my-font.woff2" }); From 11d3e91134ae729d967317036f108e743b721220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:34:33 +0100 Subject: [PATCH 09/14] Add telemetry for next/font usage --- .../build/webpack/plugins/telemetry-plugin.ts | 4 + packages/next/src/telemetry/events/build.ts | 2 + .../next-font/telemetry-old.test.ts | 78 ++++++++++++++++++ .../telemetry-old/pages-unused/index.js | 3 + .../next-font/telemetry-old/pages/_app.js | 13 +++ .../next-font/telemetry-old/pages/index.js | 11 +++ .../telemetry-old/pages/my-font.woff2 | Bin 0 -> 17508 bytes test/production/next-font/telemetry.test.ts | 28 ++----- .../next-font/telemetry/next.config.js | 13 --- .../next-font/telemetry/pages/_app.js | 2 +- .../next-font/telemetry/pages/index.js | 2 +- 11 files changed, 121 insertions(+), 35 deletions(-) create mode 100644 test/production/next-font/telemetry-old.test.ts create mode 100644 test/production/next-font/telemetry-old/pages-unused/index.js create mode 100644 test/production/next-font/telemetry-old/pages/_app.js create mode 100644 test/production/next-font/telemetry-old/pages/index.js create mode 100644 test/production/next-font/telemetry-old/pages/my-font.woff2 delete mode 100644 test/production/next-font/telemetry/next.config.js diff --git a/packages/next/src/build/webpack/plugins/telemetry-plugin.ts b/packages/next/src/build/webpack/plugins/telemetry-plugin.ts index 1f7891192f087..156ef5802d24d 100644 --- a/packages/next/src/build/webpack/plugins/telemetry-plugin.ts +++ b/packages/next/src/build/webpack/plugins/telemetry-plugin.ts @@ -26,6 +26,8 @@ export type Feature = | 'next/dynamic' | '@next/font/google' | '@next/font/local' + | 'next/font/google' + | 'next/font/local' | 'swcLoader' | 'swcMinify' | 'swcRelay' @@ -73,6 +75,8 @@ const FEATURE_MODULE_MAP: ReadonlyMap = new Map([ const FEATURE_MODULE_REGEXP_MAP: ReadonlyMap = new Map([ ['@next/font/google', /\/@next\/font\/google\/target.css?.+$/], ['@next/font/local', /\/@next\/font\/local\/target.css?.+$/], + ['next/font/google', /\/next\/font\/google\/target.css?.+$/], + ['next/font/local', /\/next\/font\/local\/target.css?.+$/], ]) // List of build features used in webpack configuration diff --git a/packages/next/src/telemetry/events/build.ts b/packages/next/src/telemetry/events/build.ts index 1e020ef5d2fd2..d5afddbccdd2d 100644 --- a/packages/next/src/telemetry/events/build.ts +++ b/packages/next/src/telemetry/events/build.ts @@ -150,6 +150,8 @@ export type EventBuildFeatureUsage = { | 'next/dynamic' | '@next/font/google' | '@next/font/local' + | 'next/font/google' + | 'next/font/local' | 'experimental/optimizeCss' | 'experimental/nextScriptWorkers' | 'optimizeFonts' diff --git a/test/production/next-font/telemetry-old.test.ts b/test/production/next-font/telemetry-old.test.ts new file mode 100644 index 0000000000000..c27ec16e94795 --- /dev/null +++ b/test/production/next-font/telemetry-old.test.ts @@ -0,0 +1,78 @@ +import { createNext, FileRef } from 'e2e-utils' +import { NextInstance } from 'test/lib/next-modes/base' +import { findAllTelemetryEvents } from 'next-test-utils' +import { join } from 'path' + +const mockedGoogleFontResponses = require.resolve( + './google-font-mocked-responses.js' +) + +describe('@next/font used telemetry', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, 'telemetry-old/pages')), + }, + dependencies: { + '@next/font': 'canary', + }, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, + NEXT_TELEMETRY_DEBUG: '1', + }, + }) + }) + afterAll(() => next.destroy()) + + it('should send @next/font/google and @next/font/local usage event', async () => { + const events = findAllTelemetryEvents( + next.cliOutput, + 'NEXT_BUILD_FEATURE_USAGE' + ) + expect(events).toContainEqual({ + featureName: '@next/font/google', + invocationCount: 1, + }) + expect(events).toContainEqual({ + featureName: '@next/font/local', + invocationCount: 1, + }) + }) +}) + +describe('@next/font unused telemetry', () => { + let next: NextInstance + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, 'telemetry/pages-unused')), + }, + dependencies: { + '@next/font': 'canary', + }, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, + NEXT_TELEMETRY_DEBUG: '1', + }, + }) + }) + afterAll(() => next.destroy()) + + it('should not send @next/font/google and @next/font/local usage event', async () => { + const events = findAllTelemetryEvents( + next.cliOutput, + 'NEXT_BUILD_FEATURE_USAGE' + ) + expect(events).toContainEqual({ + featureName: '@next/font/google', + invocationCount: 0, + }) + expect(events).toContainEqual({ + featureName: '@next/font/local', + invocationCount: 0, + }) + }) +}) diff --git a/test/production/next-font/telemetry-old/pages-unused/index.js b/test/production/next-font/telemetry-old/pages-unused/index.js new file mode 100644 index 0000000000000..a681aa7ce257c --- /dev/null +++ b/test/production/next-font/telemetry-old/pages-unused/index.js @@ -0,0 +1,3 @@ +export default function Page() { + return

Hello world

+} diff --git a/test/production/next-font/telemetry-old/pages/_app.js b/test/production/next-font/telemetry-old/pages/_app.js new file mode 100644 index 0000000000000..05702a3dc4834 --- /dev/null +++ b/test/production/next-font/telemetry-old/pages/_app.js @@ -0,0 +1,13 @@ +import localFont from '@next/font/local' + +const myFont = localFont({ src: './my-font.woff2' }) + +function MyApp({ Component, pageProps }) { + return ( +
+ +
+ ) +} + +export default MyApp diff --git a/test/production/next-font/telemetry-old/pages/index.js b/test/production/next-font/telemetry-old/pages/index.js new file mode 100644 index 0000000000000..26400dc9cebe7 --- /dev/null +++ b/test/production/next-font/telemetry-old/pages/index.js @@ -0,0 +1,11 @@ +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ subsets: ['latin'] }) + +export default function Page() { + return ( + <> +

Hello world 1

+

Hello world 2

+ + ) +} diff --git a/test/production/next-font/telemetry-old/pages/my-font.woff2 b/test/production/next-font/telemetry-old/pages/my-font.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a6b3c3a9d69faa7447699b148f39a2205119ac31 GIT binary patch literal 17508 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 literal 0 HcmV?d00001 diff --git a/test/production/next-font/telemetry.test.ts b/test/production/next-font/telemetry.test.ts index 8867c1ec780f8..00f1d4ebd3be8 100644 --- a/test/production/next-font/telemetry.test.ts +++ b/test/production/next-font/telemetry.test.ts @@ -7,19 +7,13 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font used telemetry', () => { +describe('next/font used telemetry', () => { let next: NextInstance beforeAll(async () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'telemetry/pages')), - 'next.config.js': new FileRef( - join(__dirname, 'telemetry/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, @@ -29,35 +23,29 @@ describe('@next/font used telemetry', () => { }) afterAll(() => next.destroy()) - it('should send @next/font/google and @next/font/local usage event', async () => { + it('should send next/font/google and next/font/local usage event', async () => { const events = findAllTelemetryEvents( next.cliOutput, 'NEXT_BUILD_FEATURE_USAGE' ) expect(events).toContainEqual({ - featureName: '@next/font/google', + featureName: 'next/font/google', invocationCount: 1, }) expect(events).toContainEqual({ - featureName: '@next/font/local', + featureName: 'next/font/local', invocationCount: 1, }) }) }) -describe('@next/font unused telemetry', () => { +describe('next/font unused telemetry', () => { let next: NextInstance beforeAll(async () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'telemetry/pages-unused')), - 'next.config.js': new FileRef( - join(__dirname, 'telemetry/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, @@ -67,17 +55,17 @@ describe('@next/font unused telemetry', () => { }) afterAll(() => next.destroy()) - it('should not send @next/font/google and @next/font/local usage event', async () => { + it('should not send next/font/google and next/font/local usage event', async () => { const events = findAllTelemetryEvents( next.cliOutput, 'NEXT_BUILD_FEATURE_USAGE' ) expect(events).toContainEqual({ - featureName: '@next/font/google', + featureName: 'next/font/google', invocationCount: 0, }) expect(events).toContainEqual({ - featureName: '@next/font/local', + featureName: 'next/font/local', invocationCount: 0, }) }) diff --git a/test/production/next-font/telemetry/next.config.js b/test/production/next-font/telemetry/next.config.js deleted file mode 100644 index 6a94ea94ad864..0000000000000 --- a/test/production/next-font/telemetry/next.config.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = { - experimental: { - fontLoaders: [ - { - loader: '@next/font/google', - options: { subsets: ['latin'] }, - }, - { - loader: '@next/font/local', - }, - ], - }, -} diff --git a/test/production/next-font/telemetry/pages/_app.js b/test/production/next-font/telemetry/pages/_app.js index 05702a3dc4834..5475f7ef54428 100644 --- a/test/production/next-font/telemetry/pages/_app.js +++ b/test/production/next-font/telemetry/pages/_app.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const myFont = localFont({ src: './my-font.woff2' }) diff --git a/test/production/next-font/telemetry/pages/index.js b/test/production/next-font/telemetry/pages/index.js index 26400dc9cebe7..b99c8aacbbeae 100644 --- a/test/production/next-font/telemetry/pages/index.js +++ b/test/production/next-font/telemetry/pages/index.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ subsets: ['latin'] }) export default function Page() { From 71c722592b48c2555286256f5a79bd803670bcb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:35:17 +0100 Subject: [PATCH 10/14] Update next-font error handling --- .../parseNextFontError.ts | 28 +++++-------- .../error-overlay/format-webpack-messages.ts | 2 +- .../next-font/incompatible-versions.test.ts | 40 ------------------- .../incompatible-versions/pages/index.js | 7 ---- 4 files changed, 11 insertions(+), 66 deletions(-) delete mode 100644 test/development/next-font/incompatible-versions.test.ts delete mode 100644 test/development/next-font/incompatible-versions/pages/index.js diff --git a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts index 5c433dea1c228..e86ce98bba1ff 100644 --- a/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts +++ b/packages/next/src/build/webpack/plugins/wellknown-errors-plugin/parseNextFontError.ts @@ -6,7 +6,11 @@ export function getNextFontError( ): SimpleWebpackError | false { try { const resourceResolveData = module.resourceResolveData - if (resourceResolveData.descriptionFileData.name !== '@next/font') { + if ( + !module.loaders.find((loader: any) => + loader.loader.includes('next-font-loader/index.js') + ) + ) { return false } @@ -18,26 +22,14 @@ export function getNextFontError( // Known error thrown by @next/font, display the error message return new SimpleWebpackError( file, - `\`@next/font\` error:\n${err.message}` + `\`next/font\` error:\n${err.message}` ) } else { // Unknown error thrown by @next/font - // It might be becuase of incompatible versions of @next/font and next are being used, or it might be a bug - - // eslint-disable-next-line import/no-extraneous-dependencies - const nextFontVersion = require('@next/font/package.json').version - const nextVersion = process.env.__NEXT_VERSION - - let message = `An error occured in \`@next/font\`.` - - // Using different versions of @next/font and next, add message that it's possibly fixed by updating both - if (nextFontVersion !== nextVersion) { - message += `\n\nYou might be using incompatible version of \`@next/font\` (${nextFontVersion}) and \`next\` (${nextVersion}). Try updating both \`@next/font\` and \`next\`, if the error still persists it may be a bug.` - } - - message += `\n\n${err.stack}` - - return new SimpleWebpackError(file, message) + return new SimpleWebpackError( + file, + `An error occured in \`next/font\`.\n\n${err.stack}` + ) } } catch { return false diff --git a/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts b/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts index 9b9c0074812a1..ef641e9e39a47 100644 --- a/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts +++ b/packages/next/src/client/dev/error-overlay/format-webpack-messages.ts @@ -184,7 +184,7 @@ function formatMessage( export default function formatWebpackMessages(json: any, verbose?: boolean) { const formattedErrors = json.errors.map((message: any) => { const isUnknownNextFontError = message.message.includes( - 'An error occured in `@next/font`.' + 'An error occured in `next/font`.' ) return formatMessage(message, isUnknownNextFontError || verbose) }) diff --git a/test/development/next-font/incompatible-versions.test.ts b/test/development/next-font/incompatible-versions.test.ts deleted file mode 100644 index 4f824b49a8479..0000000000000 --- a/test/development/next-font/incompatible-versions.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { createNext, FileRef } from 'e2e-utils' -import { NextInstance } from 'test/lib/next-modes/base' -import { join } from 'path' -import webdriver from 'next-webdriver' -import { getRedboxSource, hasRedbox } from 'next-test-utils' - -describe('incompatible-versions', () => { - let next: NextInstance - - beforeAll(async () => { - next = await createNext({ - files: { - pages: new FileRef(join(__dirname, 'incompatible-versions/pages')), - }, - // Make sure @next/font 13.0.0 is installed from npm - not the version from the monorepo - installCommand: 'pnpm add @next/font@13.0.0', - }) - }) - afterAll(() => next.destroy()) - - it('should warn that you might be using incompatible versions of next and @next/font on unknown error', async () => { - const browser = await webdriver(next.url, '/') - expect(await hasRedbox(browser, true)).toBeTrue() - - const errorMessage = await getRedboxSource(browser) - - // @next/font error info - expect(errorMessage).toInclude('pages/index.js') - expect(errorMessage).toInclude('An error occured in `@next/font`.') - expect(errorMessage).toInclude( - 'You might be using incompatible version of `@next/font` (13.0.0) and `next`' - ) - // Error - expect(errorMessage).toInclude( - 'TypeError: Cannot read properties of undefined' - ) - // Stacktrace - expect(errorMessage).toInclude('at fetchFonts') - }) -}) diff --git a/test/development/next-font/incompatible-versions/pages/index.js b/test/development/next-font/incompatible-versions/pages/index.js deleted file mode 100644 index 1a226165f5ded..0000000000000 --- a/test/development/next-font/incompatible-versions/pages/index.js +++ /dev/null @@ -1,7 +0,0 @@ -import localFont from '@next/font/local' - -const font = localFont({ src: './fake-font.woff2' }) - -export default function Index() { - return

Hello world!

-} From b9a1c3fab5cf0fbd9265ec18b2cd0684b94a119b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:35:44 +0100 Subject: [PATCH 11/14] Fix unit tests --- packages/font/src/google/utils.ts | 2 +- packages/font/src/local/utils.ts | 2 +- test/unit/google-font-loader.test.ts | 4 ++-- test/unit/local-font-loader.test.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/font/src/google/utils.ts b/packages/font/src/google/utils.ts index 51de0a2c95dc6..07d5484bd6181 100644 --- a/packages/font/src/google/utils.ts +++ b/packages/font/src/google/utils.ts @@ -39,7 +39,7 @@ export function validateData( const subsets = callSubsets ?? config?.subsets ?? [] if (functionName === '') { - nextFontError(`@next/font/google has no default export`) + nextFontError(`next/font/google has no default export`) } const fontFamily = functionName.replace(/_/g, ' ') diff --git a/packages/font/src/local/utils.ts b/packages/font/src/local/utils.ts index 623e875eadbd7..0ffe7ba3ecd8c 100644 --- a/packages/font/src/local/utils.ts +++ b/packages/font/src/local/utils.ts @@ -32,7 +32,7 @@ type FontOptions = { } export function validateData(functionName: string, fontData: any): FontOptions { if (functionName) { - nextFontError(`@next/font/local has no named exports`) + nextFontError(`next/font/local has no named exports`) } let { src, diff --git a/test/unit/google-font-loader.test.ts b/test/unit/google-font-loader.test.ts index 25dca9d3201ee..14890a96d9e96 100644 --- a/test/unit/google-font-loader.test.ts +++ b/test/unit/google-font-loader.test.ts @@ -3,7 +3,7 @@ import fetch from 'next/dist/compiled/node-fetch' jest.mock('next/dist/compiled/node-fetch') -describe('@next/font/google loader', () => { +describe('next/font/google loader', () => { afterEach(() => { jest.resetAllMocks() }) @@ -148,7 +148,7 @@ describe('@next/font/google loader', () => { variableName: 'myFont', }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"@next/font/google has no default export"` + `"next/font/google has no default export"` ) }) diff --git a/test/unit/local-font-loader.test.ts b/test/unit/local-font-loader.test.ts index 86acc47d0dd6b..8ab46a58b930d 100644 --- a/test/unit/local-font-loader.test.ts +++ b/test/unit/local-font-loader.test.ts @@ -1,6 +1,6 @@ import loader from '@next/font/local/loader' -describe('@next/font/local', () => { +describe('next/font/local', () => { describe('generated CSS', () => { test('Default CSS', async () => { const { css } = await loader({ @@ -251,7 +251,7 @@ describe('@next/font/local', () => { loaderContext: {} as any, }) ).rejects.toThrowErrorMatchingInlineSnapshot( - `"@next/font/local has no named exports"` + `"next/font/local has no named exports"` ) }) From 42de1440aa2cf5f386f18e1d59bf76b4548b905e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 15:36:47 +0100 Subject: [PATCH 12/14] Update tests to use next/font, also keep most important @next/font tests for now --- .../font-loader-in-document-error.test.ts | 7 +- .../pages/_document.js | 2 +- .../pages/fake-font.woff2 | 1 - .../next-font/validation-error.test.ts | 7 +- .../next-font/validation-error/pages/index.js | 2 +- .../app-dir/app-external/app-external.test.ts | 3 +- .../node_modules_bak/font/index.ts | 2 +- .../next-font/app-old/(preconnect)/layout.js | 10 + .../(preconnect)/no-preconnect/page.js | 9 + .../no-preconnect/styles.module.css | 3 + .../(preconnect)/preconnect-component/comp.js | 9 + .../preconnect-component/comp.woff2 | 1 + .../(preconnect)/preconnect-component/page.js | 5 + .../(preconnect)/preconnect-layout/layout.js | 12 + .../preconnect-layout/layout.woff2 | 1 + .../(preconnect)/preconnect-layout/page.js | 3 + .../(preconnect)/preconnect-page/page.js | 12 + .../(preconnect)/preconnect-page/page.woff2 | 1 + .../next-font/app-old/(preload)/Comp.js | 9 + .../app-old/(preload)/client/Comp.js | 10 + .../app-old/(preload)/client/layout.js | 13 + .../app-old/(preload)/client/page.js | 14 + .../layout-with-fonts/layout-font.woff2 | 1 + .../(preload)/layout-with-fonts/layout.js | 14 + .../(preload)/layout-with-fonts/page.js | 3 + .../next-font/app-old/(preload)/layout.js | 17 + .../(preload)/page-with-fonts/layout.js | 4 + .../(preload)/page-with-fonts/page-font.woff2 | 1 + .../app-old/(preload)/page-with-fonts/page.js | 11 + .../next-font/app-old/(preload)/page.js | 16 + .../(preconnect)/preconnect-component/comp.js | 2 +- .../(preconnect)/preconnect-layout/layout.js | 2 +- .../app/(preconnect)/preconnect-page/page.js | 2 +- .../app/(preload)/layout-with-fonts/layout.js | 2 +- .../app/(preload)/page-with-fonts/page.js | 2 +- test/e2e/app-dir/next-font/fonts/index.js | 2 +- test/e2e/app-dir/next-font/next-font.test.ts | 729 +++++------ .../app-old/components/CompWithFonts.js | 22 + .../e2e/next-font/app-old/fonts/my-font.woff2 | Bin 0 -> 17508 bytes .../app-old/fonts/my-other-font.woff2 | Bin 0 -> 19100 bytes .../fonts/roboto/roboto-100-italic.woff2 | Bin 0 -> 12440 bytes .../app-old/fonts/roboto/roboto-100.woff2 | Bin 0 -> 10972 bytes .../fonts/roboto/roboto-400-italic.woff2 | Bin 0 -> 12684 bytes .../app-old/fonts/roboto/roboto-400.woff2 | Bin 0 -> 11028 bytes .../fonts/roboto/roboto-900-italic.woff2 | Bin 0 -> 12672 bytes .../app-old/fonts/roboto/roboto-900.woff2 | Bin 0 -> 10992 bytes .../next.config.js | 1 + test/e2e/next-font/app-old/pages/_app.js | 16 + .../pages/font-without-preloadable-subsets.js | 7 + .../variable-font-without-weight-range.js | 11 + test/e2e/next-font/app-old/pages/variables.js | 67 + .../next-font/app-old/pages/with-fallback.js | 36 + .../e2e/next-font/app-old/pages/with-fonts.js | 14 + .../app-old/pages/with-google-fonts.js | 40 + .../app-old/pages/with-local-fonts.js | 153 +++ .../next-font/app-old/pages/without-fonts.js | 3 + .../next-font/app/components/CompWithFonts.js | 2 +- test/e2e/next-font/app/next.config.js | 3 - test/e2e/next-font/app/pages/_app.js | 2 +- .../pages/font-without-preloadable-subsets.js | 2 +- .../variable-font-without-weight-range.js | 2 +- test/e2e/next-font/app/pages/variables.js | 4 +- test/e2e/next-font/app/pages/with-fallback.js | 4 +- .../next-font/app/pages/with-google-fonts.js | 2 +- .../next-font/app/pages/with-local-fonts.js | 2 +- test/e2e/next-font/basepath.test.ts | 5 +- test/e2e/next-font/basepath/next.config.js | 7 - test/e2e/next-font/basepath/pages/index.js | 2 +- test/e2e/next-font/google-fetch-error.test.ts | 8 +- .../google-fetch-error/pages/index.js | 2 +- test/e2e/next-font/index.test.ts | 1122 +++++++++-------- .../with-font-declarations-file.test.ts | 5 +- .../with-font-declarations-file/fonts.js | 4 +- .../next-font/without-preloaded-fonts.test.ts | 10 +- .../without-preloaded-fonts/pages/_app.js | 2 +- .../pages/no-preload.js | 2 +- 76 files changed, 1514 insertions(+), 992 deletions(-) delete mode 100644 test/development/next-font/incompatible-versions/pages/fake-font.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/Comp.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/client/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js create mode 100644 test/e2e/app-dir/next-font/app-old/(preload)/page.js create mode 100644 test/e2e/next-font/app-old/components/CompWithFonts.js create mode 100644 test/e2e/next-font/app-old/fonts/my-font.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/my-other-font.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 create mode 100644 test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 rename test/e2e/next-font/{google-fetch-error => app-old}/next.config.js (75%) create mode 100644 test/e2e/next-font/app-old/pages/_app.js create mode 100644 test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js create mode 100644 test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js create mode 100644 test/e2e/next-font/app-old/pages/variables.js create mode 100644 test/e2e/next-font/app-old/pages/with-fallback.js create mode 100644 test/e2e/next-font/app-old/pages/with-fonts.js create mode 100644 test/e2e/next-font/app-old/pages/with-google-fonts.js create mode 100644 test/e2e/next-font/app-old/pages/with-local-fonts.js create mode 100644 test/e2e/next-font/app-old/pages/without-fonts.js diff --git a/test/development/next-font/font-loader-in-document-error.test.ts b/test/development/next-font/font-loader-in-document-error.test.ts index fa384b37020b5..b76dcc9d47cc2 100644 --- a/test/development/next-font/font-loader-in-document-error.test.ts +++ b/test/development/next-font/font-loader-in-document-error.test.ts @@ -12,19 +12,16 @@ describe('font-loader-in-document-error', () => { files: { pages: new FileRef(join(__dirname, 'font-loader-in-document/pages')), }, - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) - test('@next/font inside _document', async () => { + test('next/font inside _document', async () => { const browser = await webdriver(next.url, '/') expect(await hasRedbox(browser, true)).toBeTrue() expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` "pages/_document.js - \`@next/font\` error: + \`next/font\` error: Cannot be used within pages/_document.js." `) }) diff --git a/test/development/next-font/font-loader-in-document/pages/_document.js b/test/development/next-font/font-loader-in-document/pages/_document.js index 309ef3d66ad89..3f4422d3c3b3f 100644 --- a/test/development/next-font/font-loader-in-document/pages/_document.js +++ b/test/development/next-font/font-loader-in-document/pages/_document.js @@ -1,5 +1,5 @@ import { Html, Head, Main, NextScript } from 'next/document' -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' // eslint-disable-next-line no-unused-vars const abel = Abel({ weight: '400' }) diff --git a/test/development/next-font/incompatible-versions/pages/fake-font.woff2 b/test/development/next-font/incompatible-versions/pages/fake-font.woff2 deleted file mode 100644 index 114b10d92cf02..0000000000000 --- a/test/development/next-font/incompatible-versions/pages/fake-font.woff2 +++ /dev/null @@ -1 +0,0 @@ -fake-font \ No newline at end of file diff --git a/test/development/next-font/validation-error.test.ts b/test/development/next-font/validation-error.test.ts index a749a65c72799..35b43189f1e7c 100644 --- a/test/development/next-font/validation-error.test.ts +++ b/test/development/next-font/validation-error.test.ts @@ -12,19 +12,16 @@ describe('validation-error', () => { files: { pages: new FileRef(join(__dirname, 'validation-error/pages')), }, - dependencies: { - '@next/font': 'canary', - }, }) }) afterAll(() => next.destroy()) - it('show a @next/font error when input is wrong', async () => { + it('show a next/font error when input is wrong', async () => { const browser = await webdriver(next.url, '/') expect(await hasRedbox(browser, true)).toBeTrue() expect(await getRedboxSource(browser)).toMatchInlineSnapshot(` "pages/index.js - \`@next/font\` error: + \`next/font\` error: Missing required \`src\` property" `) }) diff --git a/test/development/next-font/validation-error/pages/index.js b/test/development/next-font/validation-error/pages/index.js index 8db5668af599c..18954160b1067 100644 --- a/test/development/next-font/validation-error/pages/index.js +++ b/test/development/next-font/validation-error/pages/index.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const font = localFont() diff --git a/test/e2e/app-dir/app-external/app-external.test.ts b/test/e2e/app-dir/app-external/app-external.test.ts index 748d09721237f..3074f6e0fabe7 100644 --- a/test/e2e/app-dir/app-external/app-external.test.ts +++ b/test/e2e/app-dir/app-external/app-external.test.ts @@ -19,7 +19,6 @@ createNextDescribe( { files: __dirname, dependencies: { - '@next/font': 'canary', react: 'latest', 'react-dom': 'latest', swr: '2.0.0-rc.0', @@ -143,7 +142,7 @@ createNextDescribe( ).toBe('rgb(255, 0, 0)') }) - it('should handle external @next/font', async () => { + it('should handle external next/font', async () => { const browser = await next.browser('/font') expect( diff --git a/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts b/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts index 5a31d967538f1..4833089fa6ed7 100644 --- a/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts +++ b/test/e2e/app-dir/app-external/node_modules_bak/font/index.ts @@ -1,3 +1,3 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' export const myFont = localFont({ src: './my-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js new file mode 100644 index 0000000000000..c84b681925ebc --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/layout.js @@ -0,0 +1,10 @@ +export default function Root({ children }) { + return ( + + + Hello World + + {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js new file mode 100644 index 0000000000000..d861b42e63d1f --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/page.js @@ -0,0 +1,9 @@ +import styles from './styles.module.css' + +export default function Page() { + return ( + <> +

hello world

+ + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css new file mode 100644 index 0000000000000..c8cf8ee5c5b2c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/no-preconnect/styles.module.css @@ -0,0 +1,3 @@ +.p { + color: wheat; +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js new file mode 100644 index 0000000000000..50be0f9f3c7a2 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.js @@ -0,0 +1,9 @@ +import localFont from '@next/font/local' + +const componentFont = localFont({ src: './comp.woff2', preload: false }) + +export default function Component() { + return ( +

{JSON.stringify(componentFont)}

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 new file mode 100644 index 0000000000000..c62250d2cbfe7 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/comp.woff2 @@ -0,0 +1 @@ +comp-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js new file mode 100644 index 0000000000000..2bd70262127ef --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-component/page.js @@ -0,0 +1,5 @@ +import Comp from './comp' + +export default function Page() { + return +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js new file mode 100644 index 0000000000000..b4950beabc051 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.js @@ -0,0 +1,12 @@ +import localFont from '@next/font/local' + +const layoutFont = localFont({ src: './layout.woff2', preload: false }) + +export default function Layout({ children }) { + return ( + <> +

{JSON.stringify(layoutFont)}

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 new file mode 100644 index 0000000000000..ac7fe0c6b67c0 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/layout.woff2 @@ -0,0 +1 @@ +layout-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js new file mode 100644 index 0000000000000..c17431379f962 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-layout/page.js @@ -0,0 +1,3 @@ +export default function Page() { + return null +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js new file mode 100644 index 0000000000000..d84badf1eec69 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.js @@ -0,0 +1,12 @@ +'use client' +import localFont from '@next/font/local' + +const pageFont = localFont({ src: './page.woff2', preload: false }) + +export default function Page() { + return ( + <> +

{JSON.stringify(pageFont)}

+ + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 new file mode 100644 index 0000000000000..cb4ed2b24f421 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preconnect)/preconnect-page/page.woff2 @@ -0,0 +1 @@ +page-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js b/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js new file mode 100644 index 0000000000000..07a0875d88947 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/Comp.js @@ -0,0 +1,9 @@ +import { font3 } from '../../fonts' + +export default function Component() { + return ( +

+ {JSON.stringify(font3)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js new file mode 100644 index 0000000000000..2679352a57119 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/Comp.js @@ -0,0 +1,10 @@ +'use client' +import { font6 } from '../../../fonts' + +export default function Component() { + return ( +

+ {JSON.stringify(font6)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js new file mode 100644 index 0000000000000..83816c21a59b9 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/layout.js @@ -0,0 +1,13 @@ +'use client' +import { font4 } from '../../../fonts' + +export default function Root({ children }) { + return ( + <> +

+ {JSON.stringify(font4)} +

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js new file mode 100644 index 0000000000000..9606c96a020d9 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/client/page.js @@ -0,0 +1,14 @@ +'use client' +import Comp from './Comp' +import { font5 } from '../../../fonts' + +export default function HomePage() { + return ( + <> +

+ {JSON.stringify(font5)} +

+ + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 new file mode 100644 index 0000000000000..ac7fe0c6b67c0 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout-font.woff2 @@ -0,0 +1 @@ +layout-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js new file mode 100644 index 0000000000000..f7dbe5f5ea43a --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/layout.js @@ -0,0 +1,14 @@ +import localFont from '@next/font/local' + +const layoutFont = localFont({ src: './layout-font.woff2' }) + +export default function Layout({ children }) { + return ( + <> +

+ {JSON.stringify(layoutFont)} +

+ {children} + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js new file mode 100644 index 0000000000000..338cd4773f66c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout-with-fonts/page.js @@ -0,0 +1,3 @@ +export default function HomePage() { + return

Only layout

+} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/layout.js new file mode 100644 index 0000000000000..82758ca4f485d --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/layout.js @@ -0,0 +1,17 @@ +import { font1 } from '../../fonts' + +export default function Root({ children }) { + return ( + + + Hello World + + +

+ {JSON.stringify(font1)} +

+ {children} + + + ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js new file mode 100644 index 0000000000000..f927b11a8caad --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/layout.js @@ -0,0 +1,4 @@ +'use client' +export default function Layout({ children }) { + return children +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 new file mode 100644 index 0000000000000..cb4ed2b24f421 --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page-font.woff2 @@ -0,0 +1 @@ +page-font \ No newline at end of file diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js new file mode 100644 index 0000000000000..31df82aa277bb --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page-with-fonts/page.js @@ -0,0 +1,11 @@ +import localFont from '@next/font/local' + +const pageFont = localFont({ src: './page-font.woff2' }) + +export default function HomePage() { + return ( +

+ {JSON.stringify(pageFont)} +

+ ) +} diff --git a/test/e2e/app-dir/next-font/app-old/(preload)/page.js b/test/e2e/app-dir/next-font/app-old/(preload)/page.js new file mode 100644 index 0000000000000..64e1768d9e36c --- /dev/null +++ b/test/e2e/app-dir/next-font/app-old/(preload)/page.js @@ -0,0 +1,16 @@ +import Comp from './Comp' +import { font1, font2 } from '../../fonts' + +export default function HomePage() { + return ( + <> +

Hello world

+

+ {JSON.stringify(font2)} +

+ + + ) +} + +export const runtime = 'experimental-edge' diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js index 50be0f9f3c7a2..b76c81ef9ba78 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-component/comp.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const componentFont = localFont({ src: './comp.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js index b4950beabc051..be8c9716e6c4f 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-layout/layout.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const layoutFont = localFont({ src: './layout.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js index d84badf1eec69..cbd3d397105ac 100644 --- a/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js +++ b/test/e2e/app-dir/next-font/app/(preconnect)/preconnect-page/page.js @@ -1,5 +1,5 @@ 'use client' -import localFont from '@next/font/local' +import localFont from 'next/font/local' const pageFont = localFont({ src: './page.woff2', preload: false }) diff --git a/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js b/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js index f7dbe5f5ea43a..3ed0c60361884 100644 --- a/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js +++ b/test/e2e/app-dir/next-font/app/(preload)/layout-with-fonts/layout.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const layoutFont = localFont({ src: './layout-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js b/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js index 31df82aa277bb..9a32b3881a07f 100644 --- a/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js +++ b/test/e2e/app-dir/next-font/app/(preload)/page-with-fonts/page.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const pageFont = localFont({ src: './page-font.woff2' }) diff --git a/test/e2e/app-dir/next-font/fonts/index.js b/test/e2e/app-dir/next-font/fonts/index.js index d9d8746396cef..4bf7fbadcd96f 100644 --- a/test/e2e/app-dir/next-font/fonts/index.js +++ b/test/e2e/app-dir/next-font/fonts/index.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' export const font1 = localFont({ src: './font1.woff2', variable: '--font-1' }) export const font2 = localFont({ src: 'font2.woff2', variable: '--font-2' }) diff --git a/test/e2e/app-dir/next-font/next-font.test.ts b/test/e2e/app-dir/next-font/next-font.test.ts index 534a27077d69a..c1e6818ffc58a 100644 --- a/test/e2e/app-dir/next-font/next-font.test.ts +++ b/test/e2e/app-dir/next-font/next-font.test.ts @@ -1,5 +1,6 @@ -import { createNextDescribe } from 'e2e-utils' +import { createNextDescribe, FileRef } from 'e2e-utils' import { getRedboxSource, hasRedbox } from 'next-test-utils' +import { join } from 'path' const getAttrs = (elems: Cheerio) => Array.from(elems) @@ -8,394 +9,398 @@ const getAttrs = (elems: Cheerio) => // My machine behaves differently to CI .sort((a, b) => (a.href < b.href ? -1 : 1)) -createNextDescribe( - 'app dir next-font', - { - files: __dirname, - dependencies: { - '@next/font': 'canary', - react: 'latest', - 'react-dom': 'latest', +describe.each([['app'], ['app-old']])('%s', (fixture: string) => { + createNextDescribe( + 'app dir next-font', + { + files: { + app: new FileRef(join(__dirname, fixture)), + fonts: new FileRef(join(__dirname, 'fonts')), + 'next.config.js': new FileRef(join(__dirname, 'next.config.js')), + }, + dependencies: { + '@next/font': 'canary', + }, + skipDeployment: true, }, - skipDeployment: true, - }, - ({ next, isNextDev: isDev }) => { - describe('import values', () => { - it('should have correct values at /', async () => { - const $ = await next.render$('/') - - // layout - expect(JSON.parse($('#root-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), - }, - }) - // page - expect(JSON.parse($('#root-page').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font2_.{6}'$/), - }, - }) - // Comp - expect(JSON.parse($('#root-comp').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font3_.{6}'$/), - fontStyle: 'italic', - fontWeight: 900, - }, - }) - }) - - it('should have correct values at /client', async () => { - const $ = await next.render$('/client') - - // root layout - expect(JSON.parse($('#root-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), - }, - }) - - // layout - expect(JSON.parse($('#client-layout').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font4_.{6}'$/), - fontWeight: 100, - }, - }) - // page - expect(JSON.parse($('#client-page').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font5_.{6}'$/), - fontStyle: 'italic', - }, - }) - // Comp - expect(JSON.parse($('#client-comp').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching(/^'__font6_.{6}'$/), - }, - }) - }) - }) - - describe('computed styles', () => { - it('should have correct styles at /', async () => { - const browser = await next.browser('/') - - // layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' - ) - ).toMatch(/^__font1_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' - ) - ).toBe('normal') - - // page - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontFamily' - ) - ).toMatch(/^__font2_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-page")).fontStyle' - ) - ).toBe('normal') - - // Comp - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontFamily' - ) - ).toMatch(/^__font3_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontWeight' - ) - ).toBe('900') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-comp")).fontStyle' - ) - ).toBe('italic') - }) - - it('should have correct styles at /client', async () => { - const browser = await next.browser('/client') - - // root layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' - ) - ).toMatch(/^__font1_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' - ) - ).toBe('normal') - - // layout - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontFamily' - ) - ).toMatch(/^__font4_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontWeight' - ) - ).toBe('100') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-layout")).fontStyle' - ) - ).toBe('normal') - - // page - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontFamily' - ) - ).toMatch(/^__font5_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-page")).fontStyle' - ) - ).toBe('italic') - - // Comp - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontFamily' - ) - ).toMatch(/^__font6_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#client-comp")).fontStyle' - ) - ).toBe('normal') - }) - }) - - if (!isDev) { - describe('preload', () => { - it('should preload correctly with server components', async () => { + ({ next, isNextDev: isDev }) => { + describe('import values', () => { + it('should have correct values at /', async () => { const $ = await next.render$('/') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/b2104791981359ae-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + // layout + expect(JSON.parse($('#root-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/b61859a50be14c53-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // page + expect(JSON.parse($('#root-page').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font2_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // Comp + expect(JSON.parse($('#root-comp').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font3_.{6}'$/), + fontStyle: 'italic', + fontWeight: 900, }, - ]) + }) }) - it('should preload correctly with client components', async () => { + it('should have correct values at /client', async () => { const $ = await next.render$('/client') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e1053f04babc7571-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + // root layout + expect(JSON.parse($('#root-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font1_.{6}'$/), }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + + // layout + expect(JSON.parse($('#client-layout').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font4_.{6}'$/), + fontWeight: 100, }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/feab2c68f2a8e9a4-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + }) + // page + expect(JSON.parse($('#client-page').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font5_.{6}'$/), + fontStyle: 'italic', }, - ]) + }) + // Comp + expect(JSON.parse($('#client-comp').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching(/^'__font6_.{6}'$/), + }, + }) }) + }) - it('should preload correctly with layout using fonts', async () => { - const $ = await next.render$('/layout-with-fonts') - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/75c5faeeb9c86969-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - ]) + describe('computed styles', () => { + it('should have correct styles at /', async () => { + const browser = await next.browser('/') + + // layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' + ) + ).toMatch(/^__font1_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' + ) + ).toBe('normal') + + // page + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontFamily' + ) + ).toMatch(/^__font2_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-page")).fontStyle' + ) + ).toBe('normal') + + // Comp + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontFamily' + ) + ).toMatch(/^__font3_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontWeight' + ) + ).toBe('900') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-comp")).fontStyle' + ) + ).toBe('italic') }) - it('should preload correctly with page using fonts', async () => { - const $ = await next.render$('/page-with-fonts') - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From root layout - expect(getAttrs($('link[as="font"]'))).toEqual([ - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/568e4c6d8123c4d6-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - { - as: 'font', - crossorigin: '', - href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }, - ]) + it('should have correct styles at /client', async () => { + const browser = await next.browser('/client') + + // root layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontFamily' + ) + ).toMatch(/^__font1_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#root-layout")).fontStyle' + ) + ).toBe('normal') + + // layout + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontFamily' + ) + ).toMatch(/^__font4_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontWeight' + ) + ).toBe('100') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-layout")).fontStyle' + ) + ).toBe('normal') + + // page + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontFamily' + ) + ).toMatch(/^__font5_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-page")).fontStyle' + ) + ).toBe('italic') + + // Comp + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontFamily' + ) + ).toMatch(/^__font6_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#client-comp")).fontStyle' + ) + ).toBe('normal') }) }) - describe('preconnect', () => { - it.each([['page'], ['layout'], ['component']])( - 'should add preconnect when preloading is disabled in %s', - async (type: string) => { - const $ = await next.render$(`/preconnect-${type}`) + if (!isDev) { + describe('preload', () => { + it('should preload correctly with server components', async () => { + const $ = await next.render$('/') // Preconnect - expect($('link[rel="preconnect"]').length).toBe(1) - expect($('link[rel="preconnect"]').get(0).attribs).toEqual({ - crossorigin: 'anonymous', - href: '/', - rel: 'preconnect', - 'data-next-font': 'size-adjust', - }) - // Preload - expect($('link[as="font"]').length).toBe(0) - } - ) + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/b2104791981359ae-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/b61859a50be14c53-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with client components', async () => { + const $ = await next.render$('/client') - it('should not preconnect when css is used but no fonts', async () => { - const $ = await next.render$('/no-preconnect') + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e1053f04babc7571-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/feab2c68f2a8e9a4-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with layout using fonts', async () => { + const $ = await next.render$('/layout-with-fonts') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - // Preload - expect(getAttrs($('link[as="font"]'))).toEqual([]) - }) - }) - } + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/75c5faeeb9c86969-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + + it('should preload correctly with page using fonts', async () => { + const $ = await next.render$('/page-with-fonts') - if (isDev) { - describe('Dev errors', () => { - it('should recover on font loader error', async () => { - const browser = await next.browser('/') - const font1Content = await next.readFile('fonts/index.js') + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From root layout + expect(getAttrs($('link[as="font"]'))).toEqual([ + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/568e4c6d8123c4d6-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + { + as: 'font', + crossorigin: '', + href: '/_next/static/media/e9b9dc0d8ba35f48-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }, + ]) + }) + }) - // Break file - await next.patchFile( - 'fonts/index.js', - font1Content.replace('./font1.woff2', './does-not-exist.woff2') - ) - expect(await hasRedbox(browser, true)).toBeTrue() - expect(await getRedboxSource(browser)).toInclude( - "Can't resolve './does-not-exist.woff2'" + describe('preconnect', () => { + it.each([['page'], ['layout'], ['component']])( + 'should add preconnect when preloading is disabled in %s', + async (type: string) => { + const $ = await next.render$(`/preconnect-${type}`) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(1) + expect($('link[rel="preconnect"]').get(0).attribs).toEqual({ + crossorigin: 'anonymous', + href: '/', + rel: 'preconnect', + 'data-next-font': 'size-adjust', + }) + // Preload + expect($('link[as="font"]').length).toBe(0) + } ) - // Fix file - await next.patchFile('fonts/index.js', font1Content) - await browser.waitForElementByCss('#root-page') + it('should not preconnect when css is used but no fonts', async () => { + const $ = await next.render$('/no-preconnect') + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + // Preload + expect(getAttrs($('link[as="font"]'))).toEqual([]) + }) }) - }) + } + + if (isDev) { + describe('Dev errors', () => { + it('should recover on font loader error', async () => { + const browser = await next.browser('/') + const font1Content = await next.readFile('fonts/index.js') + + // Break file + await next.patchFile( + 'fonts/index.js', + font1Content.replace('./font1.woff2', './does-not-exist.woff2') + ) + expect(await hasRedbox(browser, true)).toBeTrue() + expect(await getRedboxSource(browser)).toInclude( + "Can't resolve './does-not-exist.woff2'" + ) + + // Fix file + await next.patchFile('fonts/index.js', font1Content) + await browser.waitForElementByCss('#root-page') + }) + }) + } } - } -) + ) +}) diff --git a/test/e2e/next-font/app-old/components/CompWithFonts.js b/test/e2e/next-font/app-old/components/CompWithFonts.js new file mode 100644 index 0000000000000..104526effb17d --- /dev/null +++ b/test/e2e/next-font/app-old/components/CompWithFonts.js @@ -0,0 +1,22 @@ +import { Inter, Roboto } from '@next/font/google' +const inter = Inter({ weight: '900', display: 'swap', preload: false }) +const roboto = Roboto({ + weight: '100', + style: 'italic', + display: 'swap', + preload: true, + subsets: ['vietnamese'], +}) + +export default function Component() { + return ( + <> +
+ {JSON.stringify(inter)} +
+
+ {JSON.stringify(roboto)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/fonts/my-font.woff2 b/test/e2e/next-font/app-old/fonts/my-font.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..a6b3c3a9d69faa7447699b148f39a2205119ac31 GIT binary patch literal 17508 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 literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/app-old/fonts/my-other-font.woff2 b/test/e2e/next-font/app-old/fonts/my-other-font.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ac8adf10ed94280cababe8fd87d0a4971b6d2e8f GIT binary patch literal 19100 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 literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..1f22fa96cdfe52fdd4d7ebe3910c443cad4d8ad0 GIT binary patch literal 12440 zcmV;JFlWzqPew8T0RR9105F&U4gdfE09>E|05CxS0RR9100000000000000000000 z0000QWE+`e9EDy6U;u+45ey1}f*|P&3xo;)0X7081Beg=AO(Xa2Ot{^O|zn`?_ymP zm6IjKf0e+U$~+Vf!5|m}$=>nuyFi3cF~OyEb8kG`4a1NlwDb`#5Ak+UuRgkGcF#}* zAy;}A!>N>th{Ty1qPg8~qc#>r14j9oTDM*E2fzno>SOH=nW+eC% zfQoP)nTuTlMz~>U`vAsGDYg5*Tr0Tk`@i+UC>F??N>%;P2`>zd_lS48{~Fh1=5D?> zmy=4RDv%Xy{r_yHt^SSoon#&p%N(K}OOoA`p<4S#D`|Fi4|J!zTj^wwanCYH3drY> zB*V%fCT;l6zyVf(xT2y=`t(qy=+d^pU0$D}>eB)15;Y5Kx`vJrhtQwC`KsoT8tGP# zN8=QTf@zq7C1lLMes&pCd(hp}JNOX^Cm^ohq5=#C0EdA=lA#Y`#utQ*4U!`VBu^el zp+b-nB_L%gK#n;MX4wxA2n?_YUujf$aGK ziA*31I`52lCcuGUkN^ar01AQ;;H9c){|N$cz>qmDv=ZL=cjHHzN=|jA2Zr{?cMP8D zj1gnvSo*X-3(xh>aD4vkeyI}}9R7&uCY5jdm;IhVzsq0YyCcI>XG-cUIXzIWBMc>S z0h?QP# zzpQ%nML1A=`lo?BUa9h9u77|?sXlwA{mN!i+e>TOANdaUs%0eS{*m6}XNwBHmMa$T z(T`#7pXs@O;sqr0%ZbGYXvm2@|EA4pcY4>Vike zwVw9@nrFU-Pn8M3oJa=Q(aY*|(cMi})jVJcxGZmFpUr95l+}bl;(*Z?HzhsuZ99=Y zXot>f)8bW;c#Dnqj4qZp^UCb;7ga3p(phi9x>q{5>MJa;rPl4V zoIlbgwPxM7Z4ir*-bOs9v@ZVl5)bG60cXaA(_v6oTX419vAC;FS3^uz5Ok2}A~=lCBYYslq&NVVdS4?<|LObsi_e#22g*8}*4Y=TboR2+$r|=A( z!wdJzd}|wa;1%q`d)S8$@DV<_Kj%-rz*qR@{+>VhF$v<8=hNHT2gV&nP9DWUD>v!n zOS<{a;e6x~IAR79d@qLUrM-?DBDc8aEU#P_J)f7J@^aEfVOA>1ZU|^3M)285&jla? zu)qs%1xCa4+c>G_d)fr|;66Nnhb!gB2?ym9OeUb`E(?Gq903=sz$={D1gBY`725dA z3Eu|nz$@5w|Ag}key9;iPhz zd+zhfC*aVz!zjN9h)o!)d_OhcfaGK*VIcFleNjwavyfXQOxN7v?$Elg&gdMIo>$~# zm%==+B+u!{TOiFj0b&IW;sphUgcB!VAruG>4h#VSoD2mB$~5rMqL07~oghn=L|C&X z%7HU6u3Sm-lBp0_C7ek<=*40m?_6LNq9e7DdyhNIF!AE)}3haSl^n`V`BIax$k}=#-XAR7rh9pSTY zI6$~7@n3YLK*A(U!o1{o$kQ*3i3WxLwayHn{QU6H0MM9{cKgBenXG6qaehot6gaUE zj|XQirbA1Yho(0mRcqE|(1dyCkbK>iivVo6_B_^%0`cwb=-e{*b2OrWcZY6`(Xhkz zbOk-?aGUnW9Cc)+e1O26UUA~W^AljAWj;cIY=naV!b9L#0w6jA5z41F2uT~#d#629VY(+@;@V;0~c;QG#LvKBbfl)$~l&gIZ+NXAR`okVv}4pSm*H>0yBs=s&oGM z>!1G+@OVH`2oV9(iq}~Sgpu*#CqQuC5Jk#FnjuzZbULI_C3qHt95e9wHvv-*Y0Rh* z<0ed+GHu2zm{dq7q)L!z&b*UOIqeJxq!vuDC@@hH!N8D+0-8ATDtK!bEb7NW4IKi( zz<_dsC_%e*$L=w^<334o$D5gH;}{r=;}o?w;I;>W<_~ZC_=N-LH;pQKpoIlw~MF6fue`95-B5t zl9Ggf|8rJ?MNxF=Hfqc{>#lp{LmUi8xdBU41SlfIKSa@PKJr`NkjN$EJP)X?%G8u+ zI&*`+8?)Kj%okNpOY9?(`!q|YG%41fhVY^Kc<7OQ1s;3isb`*hp-|C>-j_tN5}$qX)i>Xj`T+vN4VM2c4iF8X zOaOlai=PXu^dZpp0LnK2x+qG&#UUKvAS)~b7>ECmtN|MTYH%taB-qA<0JfX704ka# z2}CYE0;W(xVAaPYNI zr4T*51IDS5M-A=9=1AHgA;z{{&ke1sF4}EZrCOX}wxMn@8{IO1cP1KFiYd`nDlI=0 zMQ4RpqUB{q5Jy@pp#3`1H)d|WnQvlahRmJg4tZze8B3^z1T~_Tw2_2nAJvyp$El13 zsp71+k&ydzmWlORrt|Vrv!Ki$lzaX5f4|47MSjKVvdsUw%464T^3kggjt)Oq8^68T zu<%W&5w~A$wQfe%du&S*z_=-viR9;hqsb%gWvhJY4VmW&{bxbBPqqv^>ejJZahsRt z?X`C0il*$YGA47<{i@#BD!tf!8>u{O>4DJ!5B#k?Oi`Id7?zz{Q_BRljV_;|2+~f3WYUf`J*@jzVEBb=SEvGMNLK;+5aUMu|jx-cN?pPc-`9a zL*z<|c4(2Uj)IH({~p`UZiIK>jS0$;8t!m*y6l`!_0H*C@-D|CcgpU1SQ%T0J*8e0 zz1~*GTd|?DIcd&;W1k9+I6*!%wXh8F;%X-J{1PT~+2+zMFObduUcvo;dOFkXG`%mi za?fTiEXtOq!)vE%VAv(8BzAG-DmW%jVz7HGj6$H3pkY&Nl<<;bSJDYb z=&Vu52H{1$LG|PXN{NqJ8khhdOV2#Bo@8!j)l-6&Bs)kh0#X zI9dYNm~PVTSc~$yeFHMMn5+%SL(b>d=H2l{rx2-d5C&aH-LbclGImgTR9OysHxfX| z8NG-YL;Mxg=s}HyL>_kE*L0ukpN==Wg%^|!P24^MSD&H^p&b&Z2{l>D$j|}OLI*v> z467wdASwyqFBhtw4JIYmHj9Zcc@d5S0wLIkWEE>`UboARsUwRlKx&4R4|M^w%D;KzP4tA}r^DOuj=cVA;lPIsFeheoL0gZN@v z#Mir@VM0U}dZrx6iITgecOn+!r-zL4dYtllA4|zfzey>DW`(asR6iZ z)fI88o`^Xit_zK_q-~YLd7Kg{EmJ8V+w*~s(qHL0{3)J&8OH%4Ka9DYs9x@yb#&VB zwAkiUT(so+)8L0sA4-X6(cx){h}(%M#*(^2259IuQT-a^t!+IYc#BOgrZXr z#G>r*o&qII5NQPdeim-L}>b zRIn!%ZsF7Y1M(P^Sc)Es-mDOMdvY^L=Vh8bYvIyjhWzj5kgG+klfV|nqN-bCPs_2y z-b0X2&I^NIa;wZGoUh0ccEE{IH>DU_j=)XRH`oow2F`M)qC2X}np!!T6r`#rC&t^w zDQ{VM853;X%xbeVFtvDJkAG5gCkZiHWUhtgC@a#+=&Ov|2bSLb929?zikJrJm{|@X zULgB7u35t@5k+xbW%$6ZwXRk7Qv*Wb){&b&5scCN^hQ>vPc+G?FJy_&&?xr78vNzW z>LWFkOMYn_xD8@oZf?8G{Zo^7OibN2K5^^h_?B1+MTRJBj3g-FqTU;f~#Y#dqLfb_v=iA6PPj(V`U_)lC6NDuDYM zGI##M7Zs)M!p>S3(QW})Yo&6QFY7Tl^-lZfP}p+TkSlRDC3iy7Rgqi9G+FSlxw1}9 zzBM>t$BCr-MB4G9)4M7Ihb`M?u+t|Toj%2Q9?PdY=K!go0=sbo)}TZxLX;@x>N`w~<)d4|Ek*rj$0C1710(T>a< zIK1)L_h6}8{r&eRd>9UX_mnwNmv75sVap5nxrrZ=)I#Cf`r&4U!%*v)l03YATus&J zX1=Lem@nNa5vohSa-#OsnHuT9D0(y4DE98H9U6r=>{9@f4SNLKqK^WU&23SI*s5hP zM;LSO!Ac74Uzdp!M1lRtI5 zD75a7(18JVKs(t(<)Wb#qd8s1MxAo$#gHeRpoQ41UGGHpLD1vpm*(r}fB+inX*@7p z^o8%|uieZ!?_5Bn3cU?>7Wf$GE4R1e#rjUCcYH@yoifd7XcXLXQ|3fVUmI6PB&k>3 z`Bw$P|BV@=?h=?~Q37CKf33X*GnqWenHp+93m_PgG@Z`&NKNHz%j7`XLth+ zE_|+8(mpErMK>JsDTaLDV78iuau%l%S2LuH$o$hXQubv3NkA%yI>d8G6-O%99H|=@ zmt0N*qbNh@ru=F;wW>P5Fu)v&5F}casylPV$8Lo$(Cl^> zAL$KGc4-on#zj3n!;cVRdZ;5o z_zYj$&e9M@>@h_%iPVy%%`-NFA{ANrORdE=4kF)R?Npj-8ri19CH+im`KsQmEt2%{!YsS zaiQ@=P52m6)wRZ4)n&03r1}uvj{b9h#>}@v2Lx5nT+Tdc)EfoN(CII#YG{Q$!CD|l z!*Ya=HM8#>M}q3&O_*>)Ot=H@~_g-c1uf$^B(yYT=IHxZu>4t@u;~5GKMr zMt=?oRteU1pJ{I2U7)nvi%p^)PmY~`C^(9Z?VBu8$(G7pAm$29p`M>gI~VD*f=;H9 zI+kxA8`wQ7)FIfhGJ44e9L!n%%=l_rPBkeX26|L!gb`5h-E%`q^)d3n-(Mp$lg>HK z^c>$QD0PHobq$|EdHfx5c69jx*9jU|PuI!T;`NRoRU(U&*q+M*Gf-0^(A{2P2<1iD znHacuXl2_s?-BAzCFO6|Gh*`36guq_i}~txa|X^K^vXGpNyL+~2^4J8 zBm`8JTHlem@CxdaiICN!cwbs5yCsXMm@sgtjwQ3b6-6oi1iUOxgSTUU_NK zaAlSNKFT|xv>JO#E|-u98Nn0H&s2GbXF@jy4p&n%;cQr4`)SbKblkP{ZE67R89N2& zn;cPMDcW3CWGDe@PiL=d>RWaI?M5macvp)Z&&$e)4GVO=%NxS$nauFcIo~T;p()Y% ze7&iz^}1j?o>{OC)|6UCOT7cI^)mIRrEM(9KPZcn(Y}4fFQf>{@9JdjU#`>-KX|&v zZ~+Iiv+$r7uK%R&2`~|1+-EZcxU0^da_z%wcQ zuEOv3ouJqyVSFIDXMNSCbyG*zm-&`>F zWx!`R>N{ zH=Zpj*SY1b)A>7P!z8f@>FY=%Qz+N@dOtIM1$|d{N%^CfR|IXcG9GXjBb?AqLS14f zRuyChjsZ@WR7}6A!G|b&HMDRifr$?lJN9g)4+aiP-ds&+lV$k|yl%W%a#3;1Kp%Gb zcG@Kxc6B0>p&8A(1mO66j^w=E( z6OVrgIt+I4#;4iJ_g2<)tAVkQSKtUO?M8n34H|ZKf|fXt&l;eDx!>+LU|=>uLoRR2 zJm7}SEllrb-{Oaojs6wO>8rFGTB_D@h1U7Rqh zPBfrK%w1tcK7*G-*1Xmd>y)KaYRHbZyp^QL=dcpsG;<$sh|Qf)LG_9*zk*%8^mgWv zzKtqI@)FV*7+<-xKU4C)Xap@WDtn*T0{jdK4^j7VW%eR;cU$b7_&MRnPhzR@3y8Cn zn;h9Mu-+nG@~nXg^qMGmeM*6>95N#LjTisa90S5S0qUZ6Hpors9rgd0PTtr>hj$3ZdT8!s1 zmQ54rS-m~p%T+7QCR^Mix=$r`D1SCxyd+SIV>TY!^DcP#`>oJYw%hQ7%a@v{R!R|d z1a`BjaI8!!E%^$E7&^d#I)SX)lzn;-{h(}}?e>hX969}fitK$Lwz&N1L$xFzD zi(s#U*IChBks+$5MjkgJe4W$=B|eOO@tHt9p4$=pufq04NdbB?+v9pjjU~QXi&lx1 zQ-^t0Cv<@9G~qzInfs;U=Z4XzEl-=oyh&X(0@hygQcfm7Nvgz0n&zj%-~b=Bou<;?g3(kKr?0d5dsqFAm!IJmlZ## z7G^mJm;N5_>>oeH*BWTVX=0kky+}4Pc2fLcoJ?3;xdBBbM(CdFjHHOFFw=|eEiPcm6@73n)!!!vT+J|w^7uu{ z>8#AiS{;m00vCw6r)wPl5KH6uYuf+bElBG-`4N3awURJ|cH(s*SB?#3gHupLgKpgj z;_mz3+NIIU?SOKa~2>49Myg-Xk?eK6mWbo|S{>Lz=rj{>Du!@|-ha$m2 zq>&E=>sX>xu+%CIr9qN;41UdAiJi*{=^Ji;dQ)amw2|()7Q{08ao6UZExcZmb1l;- z-t7&sxVlX zo#RY|nP9>N8k>JUFD;B23=Cf2NP-(5jwDu(4iwHrko0Z zr014XBIUxQ&QS$jF=2EI_q9M)SWUn!W9HGC^yIVknTkN!lw^n~++LNfNL{h&e?8#uzny5Yy&>6FM|pgKf1R9>{|u(@fHwHL%TkY| z*4?d6x(}G(>Rgm;`cY&ICmnf2_G_5~-_a>9ZX*^)RT+Pd)ElihdPGIpfze0&t&-2> zIPU7v`5c%W)>2HFFG#Z(;^k#);De^&))r`>tyn7b5S_9q2fu4TCp$zVtPjP=eB&{N z8{%#)S?Mt4Q@fBc9M&jXnGa?5+(*J(-Qe6tDI7J8#7xQOT1@kBU_;m!EbHoLK?(jo zj1WgVZ~vS^fmDB?>Z83ZC^pEO$+Wd}^Mi5<`IEt!x%H$!m42bIAyIj~Q?7s}UH@qI zC`SI7ru?&3-hs!^G|QaBz_0B38=~BnrrcIDw(Bywm4>cto-R!~m6H2dr~(%P=NM|g z0K!{UOoSFa0v-d#F-E+fyv*c+n$>02C6&XJrQMI+UH!NC$EZA}i_2QHp>KOXWn=g}9$fiXMFyL4_-aAmIHb+#N+*!HYo-eqG~p+6?mbA0(&Mqfpx@U3w1b!=!!`<6@E z`i0lRD>Q7B=}3ofWba-jg-tN+!a6oZ9CT}-J2+Cp1>~}jgTaPryXZt1j`-7R~7Q7Q4O_G4b`7_a!W5p z|GLXw&2Tf8G4ItP76qB0t<(EJ8kP{!`Y)iR~ue+dNau3q}`( zbrN#Qpva^Ij5juHHnj>qgf>l+<21B2HwFaF( zS(K?x1c&$l+QP*dPy@S~vRVL)efrRi^J7XsTwe)?b`pG)dp!S*J)zr!D@m;T&< zs;~XBlUrIZRQm95oFQ+c*00cu5nr#iJ$0t}(YWFI+c{7{IyRP6bkscYAgKju1YyK= zOw=*qXm@i*4`@Sk$sH;T#5hPyJx81Xhh#$KoaF)T_HDFZXO)k4Y&FIg>(^B7>mOHT zE|6oTPtyxErzV%wTNr2@j_Cnu24okkAt&t-gKey;Cxe6C5(6V@bPKnEb;o}_JbyNi|rOe|P z;^Pp1v{&V?5WtfCq6U!9744j+MfLbHXjFdxq54W%zUYEc)egmON4w& z)WM=!wSxHqphlcaVHWh6fSyZXHJo=i-R0g>&dsZ$j+-rk?RgN$j7aGYVoH4kit*Z`~xk+LHfn)Pj zt)NBtwa3Df!cziIuls1*^g+Mfb1~UxT*jb9kv8GxiRA$}h^FyMhe#}6xZTKZ>&7K8 zrJbW@L@mM>3|ak+#yKc6QvS#JYPSy6Uyl`w<&Cp8+xZfCjg8Zeme4birU~*szTM(B zY^+;Co(Gf-O^%880Xl`0buw2nNd;!k{FGkMeC#;6K(LE*eglp5KpGz5@?%9XYHv4+ zq|-#}zKr$fHMT){Hu=w5GYf`l30Ww6v@^!(hw?S7Gp7@(w5y|Nz9*-wqs)M!5%(m5 z>T=izHoDg#SWJq}D>3c;QTOJ);mT4B+Jegr6I+!9v}T2CZ=jVCfr2&4|9NkoO`FNF ze?iKWdWb?U#!q;u+LIM)*Z<@=ykWHGp_2i_CZ8S+ta zE3B2oHd%Tsxem(1V98Edm@4QRT=9U?-vdHOLtqFyd;TGi>$7dWavs-Z)AM_=YV71s zkwuInR{0v*j>iF4)O#!qT!ZTK(^@N^LKPdUxMtg4*s0d$wUd0E_+)*_&UcTpQ|Dp* zqn8_!FK1Lg7s$u@p`Z}E@mg>HQi3mTxchPTwOlP!@P*T`o}5_{C!c zYL++88=(<<@&G#=fb`3BTMw=g@TA6mxWCA%Qjh&)^#_A%$ zB_hyVajkMzE?hEI6Jrw|WTo&ba!pRd!t58|TO;7Z6ZmooVN_hG$T5H>W!;!u415?3 z7a}?U4$b0269ux#IkffMzwS#Vj+GXSKg3vsx|+~!yt#~R&}JcSX681oT;|}I(!*qv zr||^uSULcrKKeLa()0ec=$n2o7l`DIYdXh_gP-*I8bT=AlU%*t)gF>UNsbl^AKso7 zZpQ}`<7+lTHYf{g$*Y!!I4zW4yJm~A!z4p)%W@su3pky8Qet5qn6r$xj~}pKvRTsf z6fp5z|G8!gJOwoSo*Z*{qUG?UHzfxg{&b`C`}(IlF-J-j?p--q1LZ<#x;GLu)1YK% zxLu%(%^{tCgC;fdUB4fd? z!$+NanwGL&g;v?e8XKyQmO`1A2z5%@SsH%cx}JurUe*^pFAiO_nnqXzD0Y6`EAVt_ z(I=i}e8hZdKiS4v7385*1%Gl1Nj1FVBf+tkGb1noW9DaaA*sFAqSP9xXdbC zI6kqfIwd$cIfx3`xO&-vz`R&OFxD$5%8LPc>i{XDXaKSeetSl_F)*@(nb?GnBqa2; zL?&kU;Mg6Kcc8DpoStPBHJlNFH1)Ejo3Y*X>rqBS?q;Cm%hxa3`_Df)sDS`WQd+x? zrHFYjw;?)UH048C3O0aPG^f{W09H2wITR8t6G}}RCw!d z@R|kt*t_L;3s(fYIXLCJ0-l7R#ES6LHe56zVYDaCH!ck6x(R z=_qG}alj+2o!zW0vb`zRViqW)QCBNq__dNsF4xjvrJxx$AUSQLpLHzx#^&kdZurO5 zvL*9~PW6c+0Mx>l->4Wkyg9V1I)&TJN{dwp5S@9+F*QM5!axo~jaJNyWnyOoi9W+ut)=~d~_IDq* z3H0?F^c26M&zmYYPVwea*<3SRnscps9UchATUJpR05~Fl?M~rhO7prsqZ&)ax>)v; zj)Ce8gtt!nt<0>;t_|@7;oE6*uvD+hx@Nb0x3^}6oa@M}=vSb8Gc$}!Rw0(z=7F~I zXm}^-6XlL4jOf^gBLa3#^5&-4oE07|_RwPpNncWKkC0OxpQPM5K)D;i?*xK>iUoNB z{fH4QIp3Y9j|(Ix$w-oHFQ}~d5Jy8vUs84>OatpyN6xo<=!V+N|FXR?2hm?e?E0*- z=TBlXH!V*dTiW?^KJXS^x^ zyc>?QU;2MHr=pVtFg#!Y0vOMq^8zsWJ>&Z4c1!?0Y+7x!dYxe5_%^Y-hEjoh(JbLx zX^-?<&bAf0;cT<}lkB*nu#dtIpZd)49?yIF|@GLkv&4z6I&aYkrzvYA21dMdsP0Zse7cSH<(fe$KV8D@C}JC9R{gA8 z#E@uG$j#E>`iqHr+xnSyNmtg6kO;5UAbMHHssCy{A;yRQVB6VI&5n@^<=4Wh(i5(w z?ocUNVlw0FqQw42uT*!JU^H`YmC}!T@<=Lpf)xahK6l$)cnis&a~gO3$H6FvYa_ki z?2s8eWz;xVYl_T9Q#=G>RZ+hy%-<$Xuw0fXOO_J9Ja3lyZFi}S+s?#xJ=4p{Xobs=;2vz2 z+#1W(C51KBSLdUX<6V!f1M^07B)TyxAhO_hVr~pWQ-&@?r{xXkJak=FK=XHtN>j(> z#4wiPWt5HLlNX=VxFflroXI}oS{!``waul0fN1LQal=7fD;5I^=y{yuf+j-1L2U{+ z5g-OZ`1lTj;gvWDPFnW*5ra6$>KnvK(#6|~;p`m~F=DaB3l}O(B8o!}IQZ&EK^G%W zX%xmvEinaAFMExG@BLBfCf#2@zV=?(S-xqB_NDh=hob6U%hZy`x7$jBxn$vFSf= z^AQ^RB$puGF6gTtW_C_W<;X^OmqJKEX7D$*5BRzLy^WD&|BrX^p*EHO5h z%b1STKa-A~MK(e-rPQ@7WWC%qj>G*IFEVUrg^B#}FI2!_1z>j=jLwsWP+|cQC=en- z1Vof5h!`;t@!}y8B}0^}f-&d^1Ofvr1S|#t0wNFsEa050Xtv#6Qy=(`2_(7#{|Q7p z7vMkD%Euk}A*UQibO&|_R@?vq6rkW#3*Mmy?Y}_->^Ou@G5RVF(F0}Tp3Y2!NoXh- zEk@gkFglMuW5QT4_KeRa+423jK9Ob^D3*w#8F^MPh0j`1J2Az~){;mhOx)AXOhS_g zhbB9bAiO5#M}wLD1r3-^U!c`VM@=?e!nXOL6$f;2b8>6FbhT+`(>B|%^2+8Q_y+Q8 zLe!mVudqtpg^oa+=(G)2@i%_jy8G|~Bv1VG!embB?8J0?>sxCLSc+-=pR&rkYeV0f zOk*qkMC<>OZSeC^qrE&!&7y~$S>Tj!cGr8YV$lCHq3q+lS`TSm!IPt?i0& z;LMTUw~qyo8#wY>D<=GW$a}4nL4_qXmQwpGu!lX98XDc;A-3diJCDW=&Ww2CwOd;| zPT3tSzC5wL%8#{j3wvytE|M?GHdp?EJG327y!P-;!|dm9!eSR9?|K2l8tK^$x0N&|<=j%Xt@E zbjf9cgxnxP6iN(%1S!&Fs8Ofs79G0u7&2zcjJZ3q<;at7(2!vxMvZxF+!GTfO?hS7 zj9GKuTD9h*bvt(L+4sq3-~I5@pgJ1V(FHGmpufF2k`8|E65++>>T%!5d7MJ_{uC?tI-4GqHxjKUZ^*5Bnji?9UC z@E$(sE4gJA*5D(o!!GQ>K74}D`j`BTukZ~H^zZqL9~}s@?2lu;55pL%h%AC5meUBi zLL#?GqKMQIlVtH(f(8q2ayS^~dsesr zY`_d#l2y2P6)l0>B~CC83-B7=)IEY0J0^oCpOZ?iQw6Aj1{ff(NX|hvb~yxjkgu=g zx>Z<%kFc))#O@G&)n%fR+f+dfG{69oVFgxU4L-tpbu4vkj0rQtftFq?b^&{^51-(3 zT^#m|#tFGl0EO5eY{NEe!!~R))McWH&n?i7*2{24naT{4-6Hk?`|t@q4R? zX1NH9CD+L1S5{4cp`N>5un7^->0rf}?@i0G=2PQ@x*r(k9OI0J<-29Q;G7(sNU@mg z7oUCZW-; z8hW5u`ZisUo8kfn2Fl5tGO(bm5+vQbROX0W$P@2Ytk41lXaJmG9FG|C7{>VUI6N^0 z=ao5#d2cX!8{(P0^8u}ucpj_P(c3AcvFkJJdl_Z$v+;<9goAKoxN(rpYviW5B`swz zt`Nl#phw)G7@`ydZ?oFADMrFTcnB9^BTR%H4GYvDG)N*=5iFs}U>SfSj3_e`8)sVr zdW1g1A_^2EiDD!dBC=5M8c8?^H{l@M8EylRydbm^VZN>_JZH=w$D*tkOL+(v{h z&#Y;{hpLYO4Q7-oN3lv&?fQ`a%$#w62)eBfR^mf=x6#!PYj3YB#|PWH?b1XmX7{ZO zLHFK6YpZ?t)~L%11p2~?79ECbz{s}ddlO6vjsRgGSgZudHKU*&u@SH z^$!7fF_0*ZI|(BXvu-_3;KA#NqmC5^p27_y2hG#*tPnv#h7Am~9DE+Z3`QnK_3G4W zK-H+pL(N)XkT7aR;>|~!b{!t+)CGY^hhfVVhAST!7~D<)B^`_q%!2Fms>V}0#3fA` z30WjpBP~(V@|c!!u4j@DeTD^E%3+eMN~pF9T^j;;z_eR-ak6S7r3-ZqZf5Gu%UI9MHoq)D+r{cp0`*=>WH_Ku8CcXvvmf}0k_aEOGK7PI%d;~s4J|Di? z(`U|b{>}Voe+^kM`qw=(23HB;QfKld~7*6My8$gZ#ni9Ke(P%9)q6 zYNio>i$8DuzvchU-=r+X>u*WqQdkKsK_#G!F4-6JBCz;<@#=RONR4`kNo-@WZ5@=S zJO20D>qi*$@;mKsK2nr<3toHUt!Q_>vuMe(_dbXb`(5`d5hvakUww1ny97TVFz8|O zpG5)D0A&XJ3oLRxSY{D`wmB$20CYi?lOvA6!9v2AHDGKkKO-|kIM}2dRLmYl0AogT z%jv{5^78Rj*ce@#qbXhM=9B}FhDfksq?7spX`sF(grp6!X0_7=N?BEU%G+#Af6htT z5^);`igCxUjT$F&>{^!$f?3)=8JAJhEHZlnra|am^Q}|92*y+%1y!S##+e3p`pA_! zp^}kTe%de6>fXvi<0(DJ$ne}ZwbfSrW$aTUU0JZqpoja@SKzM_t<_G7R(pboV0pzL z7vk2jvh57cFjj=^}6z5_6K#SNWdY-z@Oql_uqmQ+M(m z{2X|Hq(Xn$2v#_t;Yu!SokSb09xFvVA1V_xj~Wa66d;FL&UB575kaM7uJ%oHNmc%} z!Sh9SoNuqIkFN^v-gIKhqrDrBkMBM>y7Qh5mPWdTw$6h)0|gA_J@x{Fp4)(gWfN82 zNPU}ik*Wu_4QgYhZPL?Z>5`nnJ?{5#-6-jHKv__~eBm+wezP8NR&j>SRe1-Wj@Xhg zkVd+L!m-=-!_Wn1_S?ijQ!G~;_1P_OG}xaTBn~ss;&yx_cL-z1KF4uIPk2Jj;9vuL zo%?0t)WZ*tlJmkB5O}Zyuo)bui}=j=%-x>zW_(FkN%#zuecShxh9} zpQbhaNLaEnBH@HmH)XN8*|IWhM%ugEiEU3>QWll_#$uL(E?PsiSNWgdyJ9UBwwjYptNsl_yzj9=rpya(;%tPE@meo8x;G}QiHjXZF7sQd5LO2JqUzjN_j84$w|}D zzp9eRnint9YC+M8qp$M~GWYF)2ggu#jtoKxgC%y04sItFvXCrj%}YkL>O&LuYEc0! zT?^URlMkqHyD`)&y)0ixob>q0A^e}aKqC1>Cv-P46I!|EwCb zY2RqbD|B z$wr&vas9%=PCV#`Sd{;JiE=_wOlN)a*RAD=Y~J)(0=>PR!HJN_m=qg;v+|*G>~_C$ zR(G0NB4*k7Hd){Pb6s=q^93Kxds@&;s1-D2r0)u(BT(!i&*+6@>!VzIozSSwrvY{;wa4N0JdnoDU|_B1Eu znj_rRF61QSTAGpAxv-Q)!J14T_xMoBe8l8Ov{HSxUhR|n#a5&yPCG8+eu7SZfzuiMf{ z#({PrQ@8P`5)IyB;mVtSQYP$RWwS^76Q^vJv7{Y0lA|=#y7+XB6h16Mn9!}-x$Iz9 zaFrk&8P1zYZ|h%6wY`bihK2Vp^s0&}1qK)IIp%uCj@vk+iJYwswdc&`b&f@l9-lr7 zcei^6+UK0~Tw*|UX_AHh;22(95RlORF=2tFnrL7I#^TGlTC>h;0}Xw`faNzX2f68h z3Wla7`O1_;&hxa~;b!JE9M@K2w$`y>GaVn&h6i+rbCv_xr}<&olYz>m5p2v5GNOq_CXc6V&~tHYme6MWaXjJ*bN<#E+b+Y7a~h&I&LW`@x&bF< za<@61K6UxU3rR@uF(ir8Bztw2(auDEXp9orb!ecrh#4|ob+ z3PH@R!q87M5D;1?*1WKFe>(lGwcdAPeU4(=Z)enmpFA+BS_c|uX<^^NX@74)YX{vZ z$!DVMXTp&@+QYZ!-ul$a8e%U*I**%R`h&5z}M&nVjFn%YOm$ z)35Si24>sqeIioHZ;#3ULkSi!k3-C{@Fo@gAEkK^c4S`w1lR=rvCn%kunN;KrQ^rQ zs^Hc_VKvuPEm!P06r0E~3#O|ms$L|fQRJqv{>J%>(%)e^CBm0WsQ$uwO zUHHzIbRU<7(Z)BUJ@=kG1iEuM5&1PfzPYt`Rl{;@m6;N zti+6o;~D%##xUs3k{?9XT*H% zh>d3CsRkMvkHRc!eL`x0|80`5l~-I6FyA#|`6^8RxdsmzYI9B{0~(&nm#t*$1RYW^ z10o|fltyV=`ODs_J(AA%VM25{u{W!p@Unwaqk?71;kC%F%bPeH4DIlkQQ`0rDqQ$O$!{`Z!)1Fbuhqv_Z};0&EX zXCPfjgwK6HSc0GSngmG8>z@B0J2m-HfuH`&isIB$`)?S(9>d6mw)UZmEI9hdms(nf zFR?%d3OLu20*Q$#CIAO?Uow#F_tw0)gIZ-@VP#S4jQYBa_Imjb%uaSx_iUTGw*em< z=faSxF)te8^1E6p@4xIVKz%&ghV25n-@a<~NpA^0Pv$FbNqw~QdMJ9)%d0a8E#7+3 z{BW$jtYoHY3Wy+5GWZ+)os1?A{CC9%CwEz4$GuiB9@c&;w2X*m5mX4(qPjyH-zRon z9*lIZPP2C5*{XXRtD5WQUbc?U*Er?lUxUcqAyin$iCJ0P{&hf9-wJLv(P6ba(l=%{ zC~y@?e;DmnV=9@nUVJJbd}`y*qx{F1u7S}Nkp4!#$V0|octEm6OF`Ovcf0lf{ zYBap#_wAT+%aA-+pW3g``YS&mI{+Z~P#Sl&7ZToqm_knojmeST zUb!F%NJv3EWXTUJRP6ZNw9;}P#HQY_L1Iv(WOA6$F_7dNgdT*ByWAFdlxk|&&Z`A|{k zZ{O&JhSS*~>Gkk&Nt47G9;!Tj3rUDZY?Sa|V_*z$)Ud7np4RBQb%96XIoigf9_`P} z7Ea|p=y=gun((Bl8q*8iQ*4ZGvWT0jj}eQ(pS#9{GQy z_E``(u=N`vxkMHWj3DJbDcW$OwudMOp+Ya^#P2FDU=lkDK7Y9?*KEx(Zz$Mv621R zw@9{V+VDbmHFaTVI1PV)m?*rFp~gsKeS+QO)E&6CPwqcG@HfV@*O=vjtoC>0QRWE!6B{az1hJS0xQkx&~oCu$06!_O=WEPZ@Pa0{_e_3ZF&fuu>ct<5*-9&DWC)!?;$JSnUPhpR9$X?>;U8)ps zW{+^LP%iIKkJQmDswC%%J@DV)m@ZWOKE}AFu+g>EC6`&Lq6n5I|9>!)Kcg3W3B8nF zPgST89YC3{5_oO}iVpF^DO&YapwnDMPXJx}3BYDi3H-Fz2mmqRS1EL*!))#2ID3X9 ziOVx0(n|_No}oA8??? z$F|Cb$$Cs7uBn&d7hldoEJ{KS*GXnJ>Yg_D;z63o^=JN47pd14HK{>?7SKd7=SOZq zJ@aSiyf@lu%j3EdFURj+CUylURJ1U_@zWVS`SkH9UBPls#gpChzt0`)o_}1sI7wTL z(x&xLvs)%;*3W*J!a(2!?EIM?(jzx<*W_HkmFiHlURzSv{3RN{wHC&Tm~Ovo#9z1B zxysvdAjB25kQDTda*g8u^Lb)$%PR6h{E9@h`_e!d(Je=npkW$N&wlP|;p=6!$JVv*C4RdUCem|e_`hJez#k*xr~vX z^sOv?yNZr+OnW)rtj9XA8rAIA+vv;VdqXb}w~US+sR$EcJu58|GMN@qUpWLL1LzRc zC6?zTO^lo^XlcTlu!j;*9UXi5<8WyRos_J5vDdL@KM8vJMF)2BJ}6MC90f6bSsob| z>c2IjwLih;stkJ|f3P>9vrw8;nAhZ4AaBm&Rf{L!0gZZ+5*%0Se>_&uXEq_Gp?VmG z2hg4-a&-dd zJt09I>pZXjzw5Hx6B^jDaco8kb`;cWBWk3&bKC;jkGJo33j~{|tBC7Px)gPI$)kr9 zU*1M1S}U;224w%McS=> zzd!9*(oZ}AHVlsHtq_ju6GV?I5(wZXMp);1xryg`xGA~LGKk1&Biw zM2o8HvNGwXi4w={bO zV*3WO8^3HO)wguSDt`{jOK19-lbT|qNN38+O{G7~RhHnxxgwj(?oX5O^)IU7xu_-z4x{I>Fn;(6k0L=ytREgH_lAO<-T6w z)u%U_&5a|!@74mDrYzFMT+5})@KCV;=?=Fu(DCRn0mjv2e$IW4cmGa!K;AK@pd>l9 zVTP(v*Emg1$-kc|5)~G{o7R@Eo|W1faDc@>^Xj6?3$)c!1v~3xAJG#_3w1Qq3ARvW z@m=GOOw>ohh246OkG2@8PbGli_dQhf@yNJDs;C5pdEIdSJx`i2;q4p(_ z5kB!L(UP~18OmH#&NL@HtYEG$1o7)hsL%(|V?dmPv(V2Q)X55VHWqJDjphFU-|krA zrT0$nr{+jS@mF~OyTr?++nPG&$P#|i(#KZU+Fs8G8G$P;4tP;KFbuu2iYHrJ#*(e9 zV-qZ`nl`rDy0-QjH|?F^Y{vOAv}_8U>O?!I(4&f96;K68$o~K8Y5tp< zYTh@rtW2%!y&Mcs2TF{;PqeSKg(pc)>G1m-U|*5fumxXZB`s&;J7xj5HAO8cfkgi} zZ+r1u*6O?lTt+skwi$t>;L=b#^k#(Jl&6_a#UDxFY6bZL21#J~O31==rg<(__2bf&-0-JB?| z@VFdrVr+ISAgzcUr>dYFQA^|IO{Frsta~NN35EBu$tY6Z(^vYSbL>H&!+2)wg{wNp zK`{k?)xu$)qtg3dr5v7zN{_Z5bI?T9Pdw;0(5ckHc;|rC*|0cU7ke9*7h@~D_+c@R zpaR*n^i zwio)_`b`rh^qn44Ok%Z79a8IbP0U(Ro$#iT>uRwb_k84Zy{57aNh%(m%Vwr&QFo4E zRp6E^cg9%E4I(ol=)4k{TKT9fsqjt5W8{))K}t<#VOMsDa@xD5#^m}8-b8%d6eaS} z{QC4QF0F-U-@7NmBIa-2td%ARiRk2u5zXf6zb3MFN?$zQUw3m11MQOpIG}npGS=f3 zO3oXU%i(q$@t#(KdbKiEWA=)kUvqS#t>+A7PGAF!L_F{iBA$#S)0evP$3OV#UUmq^ zC4KPWrz=Kd?JZwFa?eyy9pR3mY-L6=BNY<0;p{sU3b~t0^>@mPLKg~T)%bXtoR|Tp z=gj=@`5*q@R|k)5NVSTA_}!9YJm%-6J1|k-uc@ z^j|9wEZ=P_iccQi3GGk&g>&niZJ$q9jnBX(nnOm#M}zHyvaGAS7lC7jTh-bw)!Ir` z$3DM~)QqAMC5avVBAwLKEG) zBWO_)aC2z%TL~lF-GyQqvEe8oLkZ9@j;=x07vy4eCB8geya$6%W%oZ3=J9I$W-;pF z<&><{q68%L31`L?@i37)wrl6Dcm&Mgb zg(ugS#g--3M?@w}zuYUvdSp5}cxEJ|#1S*?9o;h%fTb!t{O{+f-x=34CPXJH*orSo zQjSX7b7Z-dfmdYBtd&zKS2ovkx?;k3;u z;o81Nx_f_oq_n(~lDAW{J%aO#!nLMmw^3!~P<2g7*U)fVBk$loPj3kS8unEz-N_-DyE>7~ zS6xhrChDr*hOJ)4NxtSF>ixxER?9mj&%-~v$TvFaL8ivUlj$Bf!gjm_sjYfzrX8ru zBgY@<6K-c75Pipt7#iFF@z=>0aLF6+X9ZqF?P2ZhYP7l$|BuI`(7$!cBfamU8o0VY zJBDRfI+n^{E^KC_omx1Ww5Cc|Khqc^9K}m3< z_b9d0BZZ}EQ!5^18eGMQls)(wG~bs6*ujHz0>>XOD@wEf3wpL@ zpyf!WbSt&WD$1(4D5rX5JpxMBsi54X)~i&tQEgHms?DS&pmqE|c;?CfgC?Gj_Jtgv ztm3>tkD}iplO*~^Pa@fi9a6oFo9A~{TF#|}8ps7bFuvqJolESS23EZk9!4VB{1j(Z z-eH0>&QdnUgP@-?-Cz3U6mx_wDXW)DVTu(^}epkh0;<=I9EKl>F zs^+B;hxY);rk(eXBz7sLa~oJb@Lls14fbS<9Fje8bTLaK=0-hH?=K-taG1arwcOBv z*NzERcmt9|-zZEZYntLL(lxL0tblCxcJ2lymIy7$A-v=WIjS5}(Bn%1IZ00e!CjV9 zO&_^o1H;IfCM-bf(QSl zx4T!Kx7bR@J!rlB)v;`;Q8{qZYGIK+06d+C?HDI=C8sp@Iu<3l1Z-&_2oVVcECfjA&Fmatf&mCHo;qg+m{#e;{%(0ei0K;9 z>UC@r_cx2E>tz%MlxF2d7<*vP{T^kt2>0NfQ(K%)yw$F$YUYa5ay%1fHvxMdugl-O6`)y8kt09T^p*h z7e*9b`^}DN=k}D-{_uvhUe&4ZZkt*sw+wHvb+T+@@ZCU18+CS+Aq9zYzglA~qD@Ps zB_3`0qv|lLTKTUWlhwrCZdR%r8!JSU8a<9xoE_KxwYl2Ti9 zVA_K9eyOYD>MyP(4u5fFec{T$N-x{^eG>6TC6iiEv;@$vRg71g+ziFEPg)BRZ(u%7D<15QJD9UnV36kGF>L|ClV#m%ko?Mw5 zvRP4Wi#%G2vUY|1u-V{pG{9^JnH04oaD-2Cak(l~^H4&*|Al_m5WdhK{LGbs5lrb^2>ug7Pl zk!Yoo`wfAwS$r+yIFx=(TE5iU;ss=Im}nXVM3aJ-Ashr?5l~>3K$||@j6E!*O~Bz` zza4^?#da91e8SjLm}s$Pew8T0RR9105OaJ4gdfE09zmc05LNF0RR9100000000000000000000 z0000QWE+`e9EDy6U;u+45ey3dJm>-ogbDxwHUcCAh!6xI1%nC)ARA{)6Yel$9DuPw z?jZRu5^VR7i3(97bm%Onk3SKPg)F3ZEygyr~kjH?c2G&JFI1|&)J7aX~;fQE;>>RN6Xo!qNv{7H)GG6H{&q2K|+qQ z&p{)TBoS;8CDNFba%nAbH+xCZP{mxOSTy9Kr-P2V3_r#Sf9*5(q2lh9MhId#Qob^| z-!H9$8rwTPD5b^#0^%q{4ozOa_HTEsU>NRSj(3Nl*x(>Yiz6sX6evj&C`Ae=T{g4}WI?hlS%tiVP)l?qx|3Ci zzQj;sHnEm?o;XQXBQ6kE$NJJ$u|j*;&xu67 z3b!D9SU-|O{>+6>m3vug_FtJg@c?BN;qbq5a+fQa&&w=}s1ECNZ*{Q>FJv*(>i#}X zW6tDF8nCc)H4FKG4v?2vk@w}zaXv_0mQq5CKao=@$XUQin90r9B8R65WMdi;4HIbX zY74SzUT5X{eTxoc*=6-YM7@U1H_uMUz5P{k*cWv~-cVbRqvoyPR!?KYNhg)Gkg&-f z5}vOFKsYobD|LrYHbm*b2W zbm0(C(Qs_A$!1$@wcQT8?Xj04B`Q=MaL^%o^cgT_%8WTH)@<2v;G{yOYBffUx#FsE z6Rx@LhMR7=?SUx|Ju+?9vK23^dh4C{KKSU9?|%5{m){_zOv6zjNEO=w!e$ABIFYsk zGs4(1xec+RaQH!qAgw&3lh<@N(1Rmj4wluevce{>*k+Z(Ci8q*m7rGElQ9-6SKum) z!vtJ2p5>Y6FbDIn0E@;_UR#D0cmb>M4&K8D_z0hj&w1qwe1&hu_pJIc0@>wKdw-i@ ztT80zI6S3HQOOe3ym272W+8C{;K{cxOmdn^5?rQPh0iYIjvda5&1Ok4l%9N9IRS@G zkUG}l$O0D}0s=sT*NS1m*kuF?c}F?HV|W5H@U*cA0w$`ZE}u;&t8@W+a0Dz#z0A{L z1*S@ZYN#=mvT7Mt;03H2KQaA+-;Jqs@`f(x!4a^8JXnHdSb-O?I(I~$0BgJ0VIeU0 zYbJE0UzKa ze40G6E~BjTo?V_p=vkqjFI?OZqn~%9@D(U&VT6H_1@zL4+(A(4k3*|Wv(|)M{;~9m z&8@(LX^@^vvT{*f?t?1B1L>oK_JkNggeL=zWe}5L*mFlV*aBypJ;;PrYuOYVzO+Tu4B*9df81ksZeXP`a7#&)T-^?`oz+AzuCbk>PHb2K?#uHV3>_e z%qGUNnL%3^o&uxT&Zu@UVY?Z$hY3<*bjplEg^5#TqV_YU1B~V%6QIQiv>B0(5^@ho zfRkoQniE4TT%xP>I6&rLYz~afQ8C;GVpvH;6_iBM;+EB_B_u$Cr>4-DYcSU*$8y7M zcn?g29(#&nc56!W%p!uNrb3pjB6(Yk^UfzIr7^OfZ6a7A3t1^aEMmggN)S;+ASsL- zF^qx|K`w>a3x?UJ82BLt$tZ*z6hJC6iG+HfBcvc^h!B@TEWx0ojK;>r zzyJ)m>0p$HKaqP3r2o%4djh$S_wjN8b_diQ1~`KTWq6m|FgO@cyqTIU=TC9l@*xTJq%}B z-1|slVL%}jPXt8dXTVg`7Hfmah(~~AL?i$p-492m_iYmD6Z*6G5`w?L^WVUZ|A74O zF2*AwA#-sz9@pX?P?XS4-&KU^SSi#Eg0+n?8P-2NoiOcag}_CB{PoX&2*76wLJWwL zgsDbz&Uq4q2ooVnth00tL6}N7xq@2^mCJ`J4%Q019DzMdDT-b_x}C&xN}tpE@nND- z42TvY)EQ?D8ZvAI1Qo-$^M~;l3WE`}2C!&^0-|Xicfoo(xX=oP>n1|V6h{F&;Y9B{ z@t50DsNP!2LPM=Er8+pwM4Mp(f(u5?twMNUy?*Tm>Oy*WevhZmG#{U(=K@y(?gF?7 z;12gN)&UU6-wpf&9=WR?KpK1tK;LrlNRx)-z*MIpNHoJ$?vJZGQiDeV94}sjZaprz z>W&rf{f9fte2k2%k>5hi^keXR6p(&Exm(z4PUrFToKNNW~C3*FnDEc@U8|NqZ_ za6D-ZPUz9=qH&X6_)t5`OxZf8N{dQMZuKr{<#|`WWr<8K6UrsPbkvl&*+%7X=^rbw^VyuTjmp$?{6=fWYqn=?H8Xc z#bZy*cxqOvG|xOYXWoKE=`!}buZc`qKKtUUZ@$a+1B4;L^52O7)c`Q|0QeVh!V7_O zZ|i`*4j6v~uvBU^TOYzhU=*VP8$_^B3zsS%arOsvZ1Y0ES}2RDq+;_yz$#dyF#B{| zWf4C|0RWpRL{aFFT|q3cMI(^ctiMIbTbe3iR{1EzCDF!Dn8d!1*#y4p7I?@nJeHPS zt&s*6CF$AKV>M2CLQazg^pyX>{E4+2@9B0#qKd92Zznn0tEsxuIs>DDt*_h`PRw}4 z3Ktl#t+`ZYhV!`Tz~oj~PT=>ORT=|7As3QYPNg)nAc@HljT9|1W%}dHIkC^DcT2+i znQ?^}%RW0xj?CSQPqfA<7>qH!;EpMPi54C`7S-z^*+j>fMJ`A#l&R@w8h&m%)yURC zFueBUgFhcTGmlJHT=JB1!BeL}rGSyv&UolzJwXRd4DLv5lIVo3Wk!nQB5f-)Wa4E` z8bjACCkbO7RI!!AEK;X|qO~rx&$^h;ik$66-k1uHXi=Ucbh%13&mCiyGo(PDmn+9S z`QgAXGcoElw!D}?$A}9a26p(AmFfMXX8MYffoHjCdTXSg238L=$NfGTk_wkSbgQZ~ zM&quQ45eN0(oQSwT!(2mbK#qh%_GyDwF(5wH?!Y8d}`E4Z%wQ=IpZ4Dcc5Ahq{PQ@ zB+t!dYdqVMb>bqmoT#Wvt=1ewxl2=_)IHUmTBdxGUX}&JOz>(D@NC=YU5gC>ik|;9A3vIKOu8bAS1PN(zR2kb_ zD*>Zj)&ChUn9Ox9el2bsrBf^g)jGW?=6mmV4O^8*ShjKko+mn6ww{9z$QN|`Y zyk?be9CIBUdUjC4rJig0b&{+MBrAhdGJLwK;^n?G(=(^cXldWs?%nx3>5*hz5NyG@ z%mhj~8cMi23=@8N>RT(clBuG`EEAREzJh^%Kk3oKng>!5EcfTRBrTzep0Y)@s$~5f z`B@j5u61aR(McRP4 zm`z?H6U1tQX1cLLbNho^;N07eR_m`)LeieaL*yVpv-*JYmq4@1KwYYX;#_a9kt8$SCk&zZW9z> zyeM|5B1M0E-WlvjNDxZ)**`ip*QBFT(?v3}3#d^W@$OyZSh$dSE8T z7?h!s{`sA@J^ErOf!&~lspF^R0`xEMHBxw8yecTZ5~H=MH|jWb7{+VRn813spr`-P z{N4ianPJXR-V@zJrHYUcWnks1GVWYsb!89H&RC6sAX#tBr)sb6H)kow4bAP1RlZQA zL|UwWP9UK@iO^9;1|!RX?RDWo)ILCJF46X*(t0s)Gld=X(`ZH1h5 z`G@gp8<0`U6`dNK`$j~Ms6_f`m2H#kzn>9wnVn0OJQA;~-0Dy#gA9-+JB;}`GQB08 z1#(Soprb#Fs(5MFK77Lzw5*BT!sWe{h#8DA!F|c0M;i%bm|1cBBMtmPPhDj<<+*b+ zI){SUIl2R`?&o3|&MIq*i<&ZLS5CB8mb-I{7Zk5;JIXc>i*4n3q?zTqArZXByXL{-PR)Z$>@VN-%rrXcr_Gd|ra*kL55}v|s%B*qM9u z>2C?XnW`zGykGVE+<<_%in6upY?|V0^Q{v_fmYtkSbn&pHT{O-$zq~@jBDoPiM+lNnmqZ)e<=eQS4-QMH2*%a84 zWuo*bqHi)!bV&}_`-*<0)N~hxF-roQO7q>Qj1uR}EF!0seo4O#!@QekYg4?k+oK(= ziBffxJc3c|n3Z#s%a8q+xWjiI+<6z#Jx71Xw_k`@R0Qg_vJ*Zem)4aRC{}x#yP9f@ z!T9bv%Giz?)W=zilC)7~i>Y@gMiDC*J}rFW)y+hn0dYSauX_n_%tIe0uRh$&Oi-Z& zCJe+`7IAa<(Fm-c6qHjdq4Gv6Hm%pQtDAvxDLIgIxVdOr{S`M2H^7#5Qc2)tl(fQj zYxdVquAQmb;U|ZSPcVAy%#bmT0>}I4xV9XY-1_%27iXlL^31Rb%yJ9lc(WHFN=_pI z0jCRi4!svWZxVa&V$^#`tC-hM@OkH!KqguIF7`2*Rdkd5;YLv{+nj<%x_Hfj%y~PV z(?PknQmPQ;n0KwK_5_WpdyqAP(FL;v&vRt;K3Kf8>*`LIv3-T%V)1PYHqiY6xXlYe zySTUE<}rZhjUf+vfG4t&wZh+1BNk5}=#U8=5ZF=OOeqyQFCk>bsQq|%SYi8+1L^>x zWdUY($AIy-4AQ$olMFEanwK10uKHD0RajcJB9i$(q5MN6n_Y3dsPg!4r4>74E$3Os zneICur+(gxcgy}tbom8#vEs>=J_&!E_4k)V(nl#x4s-1!!jU;&Bzv(*r0peTkWWbttqFtiurn1%PhE{f z`R&9+ya6Mvzath!!lEu>oD;2Jp!;w<&P3DkqXu+$r%yap}%RL_BUobh32b*KehJ)+AR5%gzjL$^PnjA>t7b@mB* zyJ`dN1jgX)qM##N4Rlh7fz;+l6HO=`p6n#Xle%u?7rXq3wM`eUJ|X_Es;lNr`;M=QyX`h^YY6WOaXoaRS^-&I+0SSCz}6Z=iC`-j ztRlY*AK<#L4=QlEhSiv^6*_}CQ!Rlgnh~_oC=d$VWmm3sRKbs3uVP!wPB@w@Gbhhdm$hd>qignG1{0HZrr!Czdv#Th@)K*Ahkc67ETM{ruxDl zSf9xX=>yEu%()RbfF_^P`$?WT9Wnb{H@S2ZLj=Y|-%p?+H2a*$>j!vlL}n05Kpj=o zL`ry4Y9h)8U~kdOG4b+I71IF~(^SFmUFgNt9rwq1NjI*6Cr{7bdnn$i!p%FTmH_+V zB^v7v`?-j~B zSxvUtQs!(0bXpGX3_Eyr=U&ktA{8UxaOwe)e`ar(lEYrxexfhq;+oZKXavp7GkPhp zRYR%DhI{p!hz|6#_{H<62iXkn#RWati7}S3VPOV!jgf>S3wT zJMi)XH5(ox_UhCRThtb?*MX>unV@RlHa8T5>z$yN`?KOs?sW!)ggt+xhaN|Z745wn zz3wJBxK3fKM1!3Bp{)|f<-m@6`IeY8|97-lp%RQ;Hv!ZtX~9k>{hUm+V*>=Ds1BB4 zw#Wk}2QsZs19tP5t323-&fcImGxFg=4&XXNF<+d0 z=@&}sPgUn^+(i+YH$drbtkKn&YdgbuEo?k*@Q~Q^$X1{#FvaTx&u7Q!eXPkZJ}w)a z&yWHbV{29x$J=eGn?dH8B1Q~7>{v<|lB;Hbgx(}Z5Y5NmFAlc`06o^^mU&I$0zMtP z7SDZ$FGQvkLuQ16PCzsPcN4t_gvDXn&IJ)Tg8L)8{l&EiC}HxgY)K#!jp&@TORw=oFi$z z{w`qG)=Sjd4(50c$XfCQzBFzbYy7TsUT%lN^|okc7cwtbFl(H zRyJLN($Kw%bOqK6ObtI;F=2pu2R>pobyE|vX(99cB@!94>@!EST?Ch&11 zfSi_7oCGuBnG|{ur}Vl(=^p*HVo8GkU35X;HB2vwCw-1%8qzew>o> z6dVBSznpxq9nWiJhw-j}a~IJ`jV_7ZpN|vw0CLO02@#FiOY2&AUBo4Mr zaRcuR*wU2JzHL?UiP?kuP?4{=dU!=|ViLGcy?Z>j`F@SP;IPvcLG$#R;AO3>L@i#t zYQKBr7m2zjV&!0S%jzK0DsxDrg3Hl48wjXhdCi;w`6fX5mKex6dNxp`Vwh=_IRd1| z2C2_aH9U-Md{_^Dl}C%0M+4dZC;2xw+yZ=m$<3u%ttcP%@rbG9F42q2BYV~!PhRr{iL6xw6*P_?-k`JnnV z(+}W9k~6Fc6>;nY43E^dYYskGIvmP8`h{Mp&aNr=`XVz2b)XwF9qj=61SLD8Tx{r( z@TDzINP`d>mI2J9IL&$FJ1MbPKXOj++QVnIf);j2Le4NML#Gx9=eP2OuzbHdFIY>6 zYPS5WT2hC6vBq?ZPv8^h8d{WL&FeE8YRU8I$yh5oH$@u2)Cg)6vr$%Y>a7%X9A%Vv z9o2Ao7yvo9xL9l5jv6{RBoG(a3L+>PU2UTIt*ivGMmIZer$)HjkSSFD6FP>5(wzl- z=S1`8D7(9Wxs(VmA9pi03L8dFS?eNOshaB~ZwvjnfjX=IZ#_YS-cQCpf&>(cE17hwfv`P>8G_LJBGm;3hb|{&3UM|0-DQXSM=9 z5Yq`%Jkj&DzbVxy170ey|HCK~V%L@Zdz+Vs z(&6O-oA0zzMq35-UGa0B0D=ZNEHcL(v%xAHy)H09iFQWR$fz85l!J}V3lD%pyF@w7 zS;QO3G1xG2i*_dSnOaYp04Fl7V8}beIFAk{oMztuY(w4Blpbn*DBhz4gsqp}E zikCjt7JKUYT~Ja?7pj2#dBO#Jj21il<~fhsIyiHzFrdK;R-&*n2abAn8Op?lAAxPC z%!1VGR!cI6?)Jc=Lq@V23lbgyg7u*P6KG-<8c%^ zK#lEh$htI#gsrxsgWGGW@IiR@h_Z2`K&%TsA4Apsz%JyNhbt_w0&Az#FYO+Hq4K{Wq@JRaQgjZYp$)u?oeeKur>AA0V{7M#uzQw{7A z-lvh2B535l(7Qm}A5pgh7i0xhvgw*Cec<2;AXK69; z8;imFlN++0omxv2yV6&(qh$8H-2ZSDG%`gwTP8NIf0stMi>c`_1`C-w*ZRX6q5|xr7IbhbmZcoWOc9+C$6Fp`|F;Sp!n!NUv)S`-+qq}(M zeXVU2nfKD;ryM*D$a!)qQlFr<6tg~U59p&8Ggr>+=Fb<364(c2} zoPo);hSp#LCoWIsqHxU5-r7uK|Dhw^$5>4#U9Bl265NHHg>NO8pVNA@ubEz71WNB=Uv; z!N(=a9UVheO#+E)e<_OBf`e)SLuu#GRg@7|o8ezjpSH$=Y{f3Kmi7t_t<8-OD(Q>j zqhXjC-dhn+)Lp#RifYX&FcEW&2rkQy-?o>R0NE7r+Oj8ecYX-Psz^4g3dN}GQ$MGqzE>z_k7To|8jD-GGXY3+Qj^F4|6ZY_ zObn!a9RM01&#=zlbMo}0wbOgn-k62c=;JcwYCphR9E?lSJPOQU$zD5Gk|x!_H$c$Z zc*DnF&TIOayPmE-v=*XYT6efY^!8kM8_g|Iuk;h+Qp#dbIvfaPcvDQA{2AujQnZlQ zgsR=G3PR;{H~syh&_qqNXSYx>Mc0uVz6H=*Z0LLIInU2^G;E{S&3_mY*giC8Z$3>k zOM3ZWYbh#3#~;yK$u69c+fQm?9;$A{m*fMyg{F%QbcFGRlK<#zf`O5Z2G&84J%3M3 z=r$spgG0#R*+4AkoY2kx@FH#m89e7l*lrNIy6EO`{SrC_B}VgX1xJOiFS;BZ9|n{G zB+`7Xfw1#P&(1Q~Cn6d-@zM1VXlMW3Jv9+!^uS6 zK#t^0qgY98XJ%V)2s)Mo_3fG(s3b8T=stl3(h|-S&d&pku`?*3p}`Y6 z!}wC@j=1$T9?%6Q7sh&;?AP6?XkmQRX`j&^MJo%iWzot-q}*Apu34=vT(mq)t+t6M z_*qV*LJpj$*5-t`ZgDlI>T$I`r~_mD*(yK@?I}%w5imOr=Ru4vkNq@S7z2btJq>|6 zwBPSxGPx^I(!Q4BULP43hvkLgoC)C->S0?^A}*jmF%^cx(is1WUFwP|YPN^mX&$*a zD*z+0)@c(sVljtVT@Ku&}OzwPL!cM)G$sfBWN+(?v3l8Av@^= z8$ctB8^rJ;nGikn{B@uykvg&Dl0Qm=;WPaR{-8E-*EaA~U8l#0VaK1Oh!`4Ey^y{JRJ@X%X(idWPhe0Wg2 ze4jSE$4Dl!-{~&cWEyRRGfoJ?8%7$sCr23L?f(G@#?i*WP_PAs8pl*ujJ)va#4Q8o z9dhB=sk8IW@z^bt7?s>ye&_#=5ONf~-Ew&TV7)q5;rKu3CuO$HE!V)S2FJ(!=E!}P zxv;B92N_Zf<#vbbDF>nRxIY^<(S?eE6rZ{}^wm;laf1k6Ot&(FD+4P8?3G&7=$^{F74iJolXYF@c zw4dRiBG}$d&LtoJd;0M_pjuMBEF*1@7cB5)SoX06%7336g#NJ6O2*(s`y~_)d*bw- zGP77==Sdm`G~dKnFJJ>}RrM71WM)Miu!A z$9Y(u+O1VPv#%^;GD+EgWny1k2d)5(UT3#6vJ-~5SUisZMCt-iTd=+^edd~o;!aQ9 z?OPW#llvcVw7-wTO|WUn#1qGsy{`wZmy%`om zxG8D3b{%2wu9KzYlwG#h2mL?RqDi(D8`G2096v3bl!HyoNDa{(!J*5doR%E&^~4x# z5V^-VllemX8v1<{lQa8K9qL}hMreZvaOOqa8ZUSpaVu;H`}1pYnb^n^u(;uPsC?ih z4Yp0QG(iP=Qs>MPtXJ5&m1V8>3F^UnY~}0tKhY&>-E7c=HV{36Wzpz@g?>z@UikWx z^nC?6vLV5coSat8T~9ro#$w^gIK3HW20N-h)`{#Fn&^ae;R^!x$7`sK zs|UjvI1(u5*g5?fp9+WbEPe=-u3d-Qw!2pM7}CIn2IsqD8MwKU%=cO32hVOY|Mf~ETMH` zjEzNbkc-6uM>z!}ZBvJR>RT0zb%DzAEHxl1&0)iB{_GA5Ov*osKs^?lV-F?feAHlr z)!INHF3fS$KD;H3f+uFD_G{KL-~*tM`Gn50M0rbeWt1!0a@j0~;>s(<2ymw9hQnXNPs7PiQ&}d;_j@qeJ zs9j*=AnL1`dp9@8LDafzJl}ZS#%R2NZW0L&xaP=-m&*Y=%I>aK(fk%bcM~6oa0_TtYI7G^B@h2zjvUqGnhC$tImVLGrQQ|Rtuyp@T5r~@-M zXox6O2k#1ii%@2sW;HFE|46b5pUJemYW?5Y=!xu(&eOYhpcq#y6_Xt0^bt_JJC=f%oM7|8;`Pit znzGefILT{Gd-dxV*pJ3N|GWA8%SmNf2cVS}mVaL)#YCm^_u*rSsVEp9(^H)cLt$Y8 z&b0)P+ykJxr72OvPECua@e-^XT}w-*{>3ckObtDtZ&)$j4S>qU7iZ-5|Yv zaJ9%D?l;*<&{lSex3aSLR@DOyyfI$SSaF|lk}U|ras zLQ;*cts?S9zKyXFFa&0XkDgOgS5!P`amdY-{{CyJrjVs)u|rW;)zLOoVVB{4aOsf2 zAzQzwJbWNNy01x2Q5CM+TrL46SQAHZre5^FZlx&b_8`hl_NmI zO_TK4bpdF92MD{SN?k*a~Kd zO$3n{0_Jhu?D&8Fg~v-J{~XqEJgDAKPJk=*FdCH?#Wzp>`E9!SIMUog+?-KKUiTjp z^R&pY8Gs0A^8jZ<$YGRr?@zYSUZVf4z7}Gl5auWcy>n;N5@Sfbo z{$%Q|&8KQ^?bIA*VP0#qQ8Dx9X#y&z)#Mul*7d7LzlP^P{lu?a=d_KSE}OEdx7d0( zH3PkK9^5#}T6hX=0Nf&<+T49^qh_oup2CqizC^hPmB}7i=$Kdu2GBm+HQoDG85JfC>_@8!|T=S3A*&)Ug|$csfMDv@dH zRwn!hkD3kXo#L47uXbQvhr-=iop&|>Gn(4Mi_5Inz2DY&*Zl2i9}drzHlvkSb8Z7f z|FF!Q87Wi%>MQF%G>mWPudVixb=6v+&swi>8CHAk27vkqVB_p&LuvyY8%oPTYre6- zj2N9QQ(1HTYO_Y`MgmzaTs9hK0)4I8<04NI?~Ofw@dW2Z`(kWrR+@(IW4SU`e@!UO zzve*3;)QW&T>}B*(o+uonAq=>+y8fx*d73U@lPxT0Qgav{pOd_-zl=eJ_Lpg15m*3 z@dp|JM`v*CpZ{3_{D9*gs!=(2j`xqxCv_YFjge-e?=ovo`fJc|&r&IOo#T{a<6H`+ zE58n8P=zTN3dDwxz4Jf{BGMc16GUJS;2{_Sp$^ommDX!=)tj36$CC!*`zK0e_G{T; zKy!)bWIw06M1(FGsvSbog4Qw@wTdY%=Cv70zew7?+HI1$ik7p8eos#=x9?Kv7Mr?D z`(pFzUz)c!M*Bq`^l9yVGOveN{!e8WwyBApx{PObl18A(*08%htZi}H?dwQyq%}r_ z`t!!MiM92{_F9VI{7IV4+a8f>v&d9N&}xr7>JWOP)7qv0g;7GIP1((x0@ibhb1`Fc zAT3G0UCS!fJ2FTncfs+of0O28>oV)yd|t)ay@p1u8-#F^$K<@93 zB(>#jUe2Vufl{}T+A46moP9^qY%b+a$y|MR8@uEs*qJ>sT>mq#vNs2Af=;C!&0R@961d~*euHXvB0f8nf9_*9i^+SSa-0{ zt@E=0V1J{F?Rkk9KW$AczqJoB!XO3PfeMOH2yT!CMbHTGBOUF@Hxvsgz;$}-2zv_S z%sPY>e*61L;V43}g;-Dq&0$y>W?}Q95Tr2MUqWF=Ay-BS`!Z+=w~8=}DLV=^0$RJY zrfE4Uug&~ush!VKL+P^-3j)=kkT5HF5Woq*fSrQ?0`@#1u*m>;Ai%B%(KrI8`>uzG z3*R_yJ-m$yC1Iow++PL@lQeJziW1C+7jL1Y?Xttpry)%TmxKB9XsjoI8wIKEf`6Nt zpbFtg4;^|47S1Vm3T}$aRUlOA(bc=~=fkaQymYIqRHQ=qKn2(X3Onz%kE(U!_f?ye zCz2m3kc#b3jF1Wo@jxyq4+^wiFfZHF9s(?vA+9u_d<|NRm@6f3f!gs8u<+&Fe7QRU G0002}iYIFT literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..b65a361a2e44d16996cb4da74d8bfd7ff19bbc6c GIT binary patch literal 11028 zcmV+vE9=yEPew8T0RR9104o##4gdfE08}Ud04lry0RR9100000000000000000000 z0000QWE+`e9EDy6U;u+45ey3PT-tIAgbDxwHUcCAh!6xI1%h-3AREC&MMmz*;H~f| zYS!M=6Z~H%aB}@v528b~2pNsWB}o*nJ;)U!H)cch>d41=(=YVY(0Y%TFUMqDNV%HT zcTV~dlFSm+`^SGh2NxgQ4IxKH2%++IPDfx)WPl>_%>m8re#M9yVHBWX5-F7uQqmzc zYE(#$!GMuzK+B*vR4P;~Flk9U{qOf{cK*IAwqjDDC8jfk3dQ5aJ4s&d3sj+0(3+L8 zsJ9Ic@bxqRj&xcxvSgUiN)JRew|CV8t#)Pm?h-cWfCbY?Nhc*m^8`hE-+xD?YzO}N z{^zvdk_cT_S);p6e;ASQsP_Dvno$IIJPP~&ud{4*hrL0Ea1?f#qTRD)xK2@}sH7)p zwEus3j0^TGkw#1M%$%$}i*mpV*ae6x9D9M#U63o}lA%kPlcGu6Wy=u5Kecq0&C62y zr`uBH35js)r1tmjSqQ8Ox4tNr0@=PAmhLV|o7MYc2siA6g8NFuZ(SHmdv&O3N)_8x`9M{L4Id(#c z3z{8YwcEC0vlXzvg8bqL0_S?)r7j1T7=d!hgCLtjg+6M6A3#Kh zpCCF%&NA_QtHgS*UWZ%28iY5ltr+*4b~#@?m?V$uM=|ElJ!Af4XnM`=Q7msz>cweWb83^3quL3f!KN5LMx*6%ltBZT*i@~(q=Qg!5vl1 zQ)EAEqh2>IUwvJtM?k*NIa1o#d0llxZ_&-FC-abLK60?1`tAY}&GI$6N2b_rXV>eD}jo zzx;+!%%?Dv@l!#dM$i&L2)+~|g(n3Oc8e#PHY65)fFgc+Ez|Ec1A!sV!xGl{ZQ5er zD-P{&7M7E-@`fr_qw;v#n7|~aFpU{`IhUC_>OL-$-+r$>Ov4eMbj}Q2WPx9w{ zSbD>Lh1aN?(hx9qHQ#|PjB2VM&<6zQ9AB=Q|4i)VO_7g!A31BVB@ z?$b@6-wp#{i1VrrFfJnDo`nJ{jVH-R0Pdt9%cOX0c-Y|e6&chlx*uW;X zu#KJBqZ#35M}{L_IF=cE2j1fYKH^g#7Eh)jpd3}Gp;++-Z}0|h@J1n!oiQP1FwbvU z65H}PV)rg$@4*Lr#HYnaJDOwcde5;HXq>r4t1sLW8^x%1x%~U;!ImUIXsoDfVl3O}4_6j&?-k5CBzK@)Wn z#u;*0DN;wEN8dh%qJxa1hg@LgFdK<*h#uv{#W7jY<4RRIq2{j=#_W*v)+g4!`^^!G z0tWW5hXdw7j8Me1&vEfOA;d{xNr;W4*hxu{tPpbIrzlQJVxz46RJ50>c&Leky13~H z=bTvRR|H}lfH#<93mBFN&8or@?*Kl-8Y2Q{v2qcYEYGrIZR}A_<-pFBiBzR3A;TPq zTNE*F2FmR3c-=M!Yu;0cXBM$pk|>8|FX3!N1#H@Z_x3i%JD;HUHL?0x-$N(7@NV$q z)rugg1Nc2oY@nQ0k0R3VA#VdkUWIbD!bRZ#HdqmW4{q4uNyM=s#Ci1yZJ@zypjjh? ztvJ|MuoOD*z;AF$MJU-q$+?XvRzi?ec;SZ^{tbSkctHT?QFMZW6?Vgt?2rkOpktl? z>>DijI`5x4)`K8|2>P0Y?bP#w1A+X1>%4;ObNzhWp+upobJMv&5rIHIH`tR1eYXxt zaO1+B*65|;`)O?Ql&RB%Zon|t?|W(%(1B&oqxFOk!M!c43@pGTqY# zSsZRMYIW54)q+64->z_2uzoWr-_)Eg519!TfE9FNWni`k2GqO6TEtG<Q~N6n~jxVQoQ zTuQpEY7;mZ>lVZQ-)8!t3G(j)|G?>=iULBAy8&(YPA4>jXjiCW4H8N9VeOp@-LNV5ZTk??Vc~J#)k1rP4j#3PkW#TCzqLU)M+xKzP(l6$ z>5%fP@pt$n1w@AwBC5hrhn_9idnZ(NXl`EDDkyh6sWYzAf_HkIAZ`2a^ z!pX)wDsSKX6sewh?uA85(xh9qV%3^;FOg-Gy$=bBOrL%6)i>W|`2m4~hsyu391snF zG6DDtEd36wc_cvF9+a;Ex=NJ#m?N;zkX)1sRChE~s@X%8h1O<+a#WilK#in~hS(i1 zF9cqQ1PWt0##;olqXCc_r4*fuL}gS+9Sr*rqBqGfEv+8Ri#G3$=7aP4eNN%C0%sF| zyKaS7xCORs-C&T$5Ja@uRk0bn?nD(`P=C;iPt73J40D7We~~}PrlNy4UL6B z4cJQRrgTD+g$}?jj?JK~v^1`hese3CV?F~P4y&93U&Xx2TuCo$!Z0;VuNbOi^O#G0 z+Kf5)`Bd5jL?*q9+?jVSOP>iDQSJT&i@C?UPgZIU?DvyMnu_JnF1;l6XDb#3gJb|RRe z4Qa5BSNPt$FhSK5sA^mLd^;3Q#lAEn(~=fHXc9)Yi)%<2$e~Vv!kO}3TU!euh@X?R zsZdRZ7ei)3b$CyJTF^!_8W8u#t#dVKa2%Fw^t=o2mQjtV7&*N>n-0xJ6w|19^-&^O zdy+<2kOO<&Iw7xkvtf(#otj*N0tH&`h8f~I=8)lJwGUYewpj6?pxa5DYfdXvr$9-& z@+Xtgxt7E{r-NVrAL&;A4U->6zt8m4PR6JHKR5Mp))Jk3aQy4n#~;KboYQS}fkh>> zJI!6S?X_QRDxwPb(*D!I(80=GzdoWRUFrp(RIlV@HS6ODO8G|@eQq4FG9!T-!d-GV z1Wp)P)Tl2cT-65mN2L%xsd`zQ@oC4$P{^}!u^W19Uc9g>^$&Z>9(CdQxB%cU9NTOT@fB>1y3R? zoG(ZlHTt8LCE@9e=2J@MoE{5hE_nrS-3|93e=?4GMTbyld-N%AXG&RgbDMrb~C02IQt%DIUi z=QN^ayHPZE8g}V_WiAF0EWf$hsJ*U1hqxr}5%OZH+thcQ_F|y!J!n}FH+E~I06A7R zlT~@RGtpfVRy5$zQc3OaRrMDB=z}T$ zyN50fN*=*tgSD7?_5fv4jEz^9dK%%9^O~G1oNNsR( z8@9IK)wKjD0p1PQmV{Up*i3OXb5of?85R>bjyvz!eGjX=vfzHQ3yh#Fp`NS_A(hS# zp<_v1oPEAwT+33L2bv~>Q`#}-7-Hqe;3&L$1Cyu>p}q(CC$?w^c|=Qcs378QNgGSJ z%1)b01+Mo?1*a%+(HtUF^L8EeRp7%J#n4WF&chyed*rc{VZnyUj8ZG`fTj?}`p&5( zL3nYwX0;E+TO-y={?%?h&PN)Sz3SKVt-^2D4EBlYO?WUFge^?*G*3~KfYO!id zn51Q#se83cuhJ{WnJedY*CEWCy=d$6|1d>g*N!$gplbcEG=a7V+=MBwW zRlasnh^eRiaN}Vruf`_iY24!1&3@TQ=(N3x>&N=y+)_vfDIdG#ID#X0je__vTC!mX z!TGRI7siuayEBQlcl7S|p+R{i5udm8P2&2Utc-HzrRcm$+2Z)oGJ*ONjLENi=TeoXzqm0swbr_{;YQ^y zH1#K@Q+chO^TR>lhFOybWt|q#c*6=5(O#8h6E)v;C?KN=$Gno1sdTaaye{d(Mvu!o zMg5+>_`?FVi1rmF5pwuoCRqD;7jfR=P!_=v_bt%Xct5Z11=`0+xa&tYY=XdX= z0oxevv>@i7;Uv$Byt-E@rFYT%{g?ES9$J8ifX|&-VaFj{;Fel`){T?c!c67nbc{f$ z6JWCbm+uAx0ikaa-sa9rPJm_MP0@>d&mQ%%9*sCt5N9+vR5Zf8z$iztr8too?+{D$2VU#wL*BvgHk&h} z865tU@;ct3Zr|&;mic>Cx4dc*{CJe&K|VRkDJh{$ zW?pmje*M*34;uJh6fZUkGGE^v$VtCOib{wLx|kL%<u2hS-$IvK-XWO}7YI zgoTczw2iusr=78dYY=cREkQwdCA{o|eX4<2NO=VF10o^x(AKx=kh_^!NUFg*>&Qyrzw$)fUc5v+7;jt7 z>U1Jdyi~?vf-BCMain{1yaSwk$yw4-a))`x{SV#DgmhtFediQ(R%36zx5o@{9NsD2 z0h*f>jnp9}(N4+%dVH-IPP_&*F9+%^sl3@;kweRT*IGLJ_Vv;kl+pml>(s}z+~fsh z>BJk#Dm63h5$Yv8V?GF{H1SRz0$FDIcgf&Hs~T%kW`0;!SyeV;2KD{f?bq|2Pk2wH zH@twoo-))Fq&S@f|Fc|5D5L$)#@O8Mvr*UBPQTMpqA4Ah#{c&fu++y4E6z+L=TK8G zRb~_*R8Vx^oh_ZUU|N(0o*4T$as2bt#H=mceP+1us@3Flw!b=MY8SV<_6hZT8jOk-@8vIh3hLu>fuv@4$xx}Z!Kj=6R_;Ii zvw9;k>1L>un`Ce^ap3ink>NK_Si@XnE6RVBl>R8lNlhut<@MShNG68|r%{&ED9f2t zkX=tw(yg;}OJv4*uTlzvc5lZ~p8n9@qtI+dw!j>#I=+Gay2bm`xhnLirBPq?%b3_g zW_fY$FtDVC{u!4Qjw_HAjvWWJD-zoE+M3#R+92JPRfM`F?;cwq?;bY{Ugb!nbf&Ro z3fa;n&@V93?_yklBLk^lpX|H&aJI9fzL^+cU|u$?x{iPL5bM9Oe|)m1cTlcT-YUz& zC^vtbaEI$^H0oBN--S!3%+zI161ECMsVmrSLfW}f)0wlA-BD~`*}v0>V#5y{dQNv8 zBR#$&?f1)PwX1=BKRaQmFYev@pPno2*EH8cICIQP?No!jkGkN+zr|}tl)VMj2k{=1 zxJi)-dXvZkeWGjM`|nNA3|RW&+jnEb7sIMNPelk(29n1AuIwl_aj20ivSL{dYm|#5 zmLw3PsYKdAFiD=uB zj;4C14g;1>u9^Jg2`0lshJJWodKX_qi7YaE$xy~ma6@3{@WQaXkjTg+7eLh46`>(w zy`+Kug(@B}PlA#9<$6aAhe^w%5r}%UmLSzjA7Od$>-B?YAD5a> z;`1IJBUZPm_!l3aAuum!eoRwmX{5KYHWer$cl{pbYq7Pob+9$jG#73m=zIKwefRlM zUju$WJj`I;=0g1eUnOO)9~t}JbA6tf$8UVMsj{!Ql9!osr7{=g1?Gh2N9j`0*67egJA?=9?W>7f2=JwvmI6 znCL5?ibZXCzGT~0+KcEf=UYwLhPi__iucFMGsAa-^YHO4fCGkFa8}mpN%R2bX8zsG zezWFztLC2c!n>fB;#nBQV&8#rifA173|hj7!I7GzlMNQBQzySlS8On^Q!{UL& z1cx|c0Py!H_bVPylP>x$r>?1OIY>BsCP-ePY3K-yFJaN~)>E(dh&1q|Uy)&@OM%<{IgRjb32PhWn8cd@^F$eCC)FZ?^liD+C$Jz}KUU&4{a< zM)p6fGB}9U#{XT;q%HAC|KqHQ{3xwm8+*w3waQ_zbkxdB3lT zk4%KbvoZktycr)ALY)~~7sU;r`zs$&nk9*BL2Ojv-gw7#OE4BFQh&3id{5 z;$~^HwOaC;T0(Ip27G$)3B_5p6SN5&$Rq^>BtB^GnTGLU#^AT(1BgRe)qgeOdn2Q62^cU5_S)AAJe*r{UpcKv>BJh=TL;ZTA;&O47gjxK=?JQiDO;d z?y>B-uzP#|eQi+^UAl7>1|Ghj&!7K1d!uLVx-^)6X02g9%`~_q*HmbD^pvTkze^ob z*MFC4Ox5V9`#ECl66OlctxYh`Kgv;ToPi$>!xXQ=XcoH;Y{JAeZQm~ARhRJ8fyJZq zGY9EH>x`9R!J$Xk;-x56Jlci>Szc7AIV?dHzS<;OIt6jXvn*b#uEV3JzPz2jwe+ZS zC?GK|*e|&}0gu+G2Hg)KHK`Bo)g-59B$KnUeJW??f-e`8Bxe*9S4WMF*F+bUrcz4E z125km_pZsMrDiCj;^Ih;#$wjTVnZIr*}=x6Lqf-*?yUj{ckh!eSqQp^P0+oj8?UQ9 zqOBgUeoZ}rMIPf%p@4G_bI&yM8x!>NJ8m+pbfxq&yqeIH8zIwY^%S#0?lO>+?vg6X zwQx849N+tDy^=#gP8Gq-URy1xa~WO@Y*WiS=(W3ygvJVLZXL-(@2nYF^RQWyeu$e= z(%}~SJx2S@2u5Cd=j6@Ov<_ULoA6nB>Dgrw0cY)arJ=-jXg`(WRn_}sUEWq#Q+?xM zUl9G)!^*nWE5!w#E>?~%0hw{3(TiERI5}B*|4VJFJw~{u$$M?{oj_YlwJ@QfzK-u| z%~4YGEYsd-GRbg~X+JyBZEJLYa>8h?*B1PSJFU-KCq*U4`2;sawGrhq;`L1BW$V~| zT9Y%=%X7)9?)%IgV^7;2XXb`jfStOm3#hC`G4bj38esp_dyF)RW_oq?d`(rtZLL*8 zeDzPDp)VFW7x>GYQWD}WX~sxHxta}@C;t&ch})Hf?zmK?kJxG{7@DYhWr575U>&Uv z@W+OIiz@wn3o88l3yOXHii`gVC>WkoQZ_VFIBR4|G%|z}g*L=eVohUBa%pmPBR~IV zoiZJ0sjwxU-beJ-lm4T6{@i(`YEnZXzC1C=*WcgLv?GrOJVh6+jPzBd#COjr8OfZi z_P87ypII60dsfduYj4pBntyXVCGA>5K#jPmiq1I$71_{A#18l-VU=C97zE^$W8m_| z%J3<*QX!^tBc9|$ZYeZ3SlG^%2FQ4;E&Sid3#|XPH~~wCf~S9)JXR&IlXBruciH{| z_u3E|&fm;NR`SeGcl?obcvn$v|3op#Bb)#%S3PS6M=L4^hZ~G)nIm#HN3LDQdbx#K zS-OzCO+DR0EibqRB5rWL5&TXhx<>R5vw83bhLHlj;zJx6NZsn~{_%zB?)KX2#1Ji$ zf??HMii)49ix?3CVO(x7siIU-(9jB#yFdy(B0x0ZV7x5E00&Es2h+Ey)1T zW!T=Id&TS-@2X9>G^;0TZ>?d-eIbK3D#1vmM$d_ah^g`A=5jRKp@3-(!a zRxUpNcF#q@bd?{Q(XDB{=A6?w*j8G--oCVA9S|7n>qiZ|&`+R!>=_K}u#mP;H*L4^ zd$#k=bG?8PiW+f7fI18!~+1bwu4LpWYQXTrF6l>neU(dRcWZ;QQ z<=n%OW#E)wf2%ROVJs=3Y;6FvAKGmVY`H4sN6&Ur4obr$ekgQ^exYOktY*=IoKG4Q z#(UoxE!V7x`@2HP^R*T+EQy;C%xFzOa$)4O7j)%eW2r_UzHvcp%K+VGqK+N6W^ znzPg~6hcx*+m^T^ObS(ji>;_1WM}H zj61>Vo@ySGA>>6C$$ta*{@N$h%-Y9ueRWT>GU^w!??3h|zATW*wLgJU3{qb2*vgBW zi<-+hzH*0vNJNrtT)3lCY(!gZ%s_06k+r0@j$ZjqYW7C~ZcDt#y z9Xweh9fu2uraB)Db5#;Pa#~SG9C)_){Pdj?Q3aHN@QZF!z*;2etM8PIqUH6cfT!Ce zWbgMia7aYuM>4#;J!T;LjIX`}1y#miTqSxuT-4BRLgv)~xBGyc5)0QI*Zx{ z2D&&01=+zNQ6xJ@ER|0zEeE*5dY9@hGZ)E0a^Z5I&%a$HpZl;p;ZPEKwEMxeaBpG0 z+NeX(KMo$lvUkOIWp*WWv0@J%{_Iaa%vVno3A#$3#SUIdNXkqCwM}7arW}=$>98+^ zmP^YG+2`v1?*Esi8@-IV~OPQBf2cpmS1zJ@>&ZR%7Z;d z7&*M=AQiO87Al|bbvNzUJ0T~v&!JYfLT&Dqigs#FX)97yg&WRFM|XFR zQq#~qfS=v?e+bM@1*8NtS2ssty`!=9al0$R>=2wHoxhysEYPfZ&?qUF5))sWM~-Po zz7#kV3fJo}$R9<#O@VUM*DUzHQ6<$-GMs2uODtmwFpRdGco3JZE|MiRaBu`RW_g7 zrIJ+l*lL%P=Tt3CLyMWJ%6Us2EkhGf+sNRUr~z}sZtq8BrBk;JmkwY0_d@lFTmSr> z>B$Q}j;j}I^@~3M8zcMyFe2pl6Xv+bN)H^KB_{sbfBxCEp_~6gf8A2B>%t#AVYlat zUDoXS*bATg>E*E+`@A7DJPwL=qOBeth|*bll>t9>kS>+Zx%L4V|7)f>x$5GtW_XoO zFk2crpucR%QCVof-D-e$D;V&1tahM`KnLY^Z?2nLEZuh6F57K;QoYyU?EeR5|3NbX zj{vHd*Ve{FgI($_sZh|m5o^fJHM5*&B9uS+`)M*u3-i$8_-xF2nBO^hsq1%WgB!83 z++0QD{>Bk^b!&7Z$h*0zIqqLbkipCEARDJFLea{$uL(ET>%~0Vp_*ZR9WV(>-u6z1 zLghv*rkiVg+~1d=W&x$DCyp!tk%PJyd>Z7Q-;C#-jmi0Kud$t_`HDU0(~X8T^b;Z& zLd{B>1Zg|oVBB9W)IHt5)D1*@<%wPwOXR`ZXsZ@DQzr$>;M}v8xTGz^nYzT5Q}akD z3-+Fvvi8`d?fr>W-kQANY|a6kd;Nb72VkdwqYOdzu(xYpvNl*F3;l;^F#gC-)jQK} zxWTafx`1AIEN{LK@?Vo*S76h1a$z~Fec(l<)vI>TuB=AaUe=&r+uNB7UPExp-}gaR z3bo}_5&7clGsW^9=`uL*QEh^SJOJE~UuVt(3Z=3Pb~^K&Q>yzwj52>aN7e{z?AG2# zImb1avD&(AxbsV~9z3x(BiK8IypwQY$Jv5%P46dKjucK*pM#*UH7eZ7L^=(>!OJIK z)T@i9eOxnW`;FS*X8FGg;_|p39h4*S z(U_J|A#M1L8?+~y6nHMqs{vrE{w6q4<#Xip>VCdyrkn+zvxD;7EOHXW8T~)p1j;V> z{@=rv7;Jf;J}w*7&-xpVoQshg0BX#3=@TfvvzQ%JWWj~=pL7k>xZY=k{T1CCp&V6t z+a?(L>BoV#Lm%hzJo^cgkE@U9bQO^i2W7HU@07+wYPMJZ(LZ1ru*2N)2v9ay#l7&l z>A6*Z$M2f}@ZwLr5&*mt7Qg*E@ONRBn!(BJ&gP}H z{%vp7vK;CP4W+#mHHm`mBER{`dwKKOH>8(oVwL1z%VfF=94hie%K>@S7~we<23p_@ z7s#UmX)r-ZvAxy@+?xWT*pw#AYw^=s(h=OY1 zgydtbb~H~FOo^!#&q3fM$Zk@cCY9@`ao$r@TLQQ7l^q}D#BL4^7wI2WjcA}Y|L5xR zINICUTz9WRXmP8tHb0cQN_arS>H6KtIzv#HUDeiHpLJmK^-!r%K5BF0Hw_$b534VW zJ6SwB>M+7|=n^NN{!lnhmE!oNa;)e3 z(dB-|HJ5fVXHwkogSZa~dwS%1Vh9mi*5Z?%B{nEOoIq_bf?gC}4L7Ioxosj_n(SSyf6)Xf`87NR2!a;z^ zMQBK41#mpj?T_H#vOfwJ|6Fu`E(Z3;5)-{Y&OtS+%f$+ljyu62F(f}9-*6!rDQQzJ zq#vxRpXeQE800Czv=R_Q7S|qg3MsA-7qI(fGGAYbY1cipg zAlb7jNJc;FXH4RE3hoXMQI<5NQB0!1Laf`<*IS}7(u8Ef&vPP(u;!OEHq_BGwRA!p ON3B$ub4ks;IsgFgYn-P5 literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..741d0638b1db4c0e4c855a0d889876745efd29d6 GIT binary patch literal 12672 zcmV-`F@Mf?Pew8T0RR9105O074gdfE09$|n05K;30RR9100000000000000000000 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 literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/google-fetch-error/next.config.js b/test/e2e/next-font/app-old/next.config.js similarity index 75% rename from test/e2e/next-font/google-fetch-error/next.config.js rename to test/e2e/next-font/app-old/next.config.js index 16e3ab6f546a2..3f4a776b7f409 100644 --- a/test/e2e/next-font/google-fetch-error/next.config.js +++ b/test/e2e/next-font/app-old/next.config.js @@ -3,6 +3,7 @@ module.exports = { fontLoaders: [ { loader: '@next/font/google', + options: { subsets: ['latin'] }, }, ], }, diff --git a/test/e2e/next-font/app-old/pages/_app.js b/test/e2e/next-font/app-old/pages/_app.js new file mode 100644 index 0000000000000..87fd0d1ed9b67 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/_app.js @@ -0,0 +1,16 @@ +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ variable: '--open-sans' }) + +function MyApp({ Component, pageProps }) { + return ( + <> +
+ {JSON.stringify(openSans)} +
+ + + ) +} + +export { openSans } +export default MyApp diff --git a/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js b/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js new file mode 100644 index 0000000000000..62ac7af99f5c1 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js @@ -0,0 +1,7 @@ +import { Single_Day } from '@next/font/google' + +const singleDay = Single_Day({ weight: '400' }) + +export default function FontWithoutPreloadableSubsets() { + return

{JSON.stringify(singleDay)}

+} diff --git a/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js b/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js new file mode 100644 index 0000000000000..bb78339d8d405 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js @@ -0,0 +1,11 @@ +import { Nabla } from '@next/font/google' + +const nabla = Nabla() + +export default function VariableFontWithoutWeightRange() { + return ( +

+ {JSON.stringify(nabla)} +

+ ) +} diff --git a/test/e2e/next-font/app-old/pages/variables.js b/test/e2e/next-font/app-old/pages/variables.js new file mode 100644 index 0000000000000..e4b19c560a37a --- /dev/null +++ b/test/e2e/next-font/app-old/pages/variables.js @@ -0,0 +1,67 @@ +import { Fira_Code, Roboto } from '@next/font/google' +import localFont from '@next/font/local' + +const firaCode = Fira_Code({ variable: '--fira-code' }) +const roboto = Roboto({ + weight: '100', + style: 'italic', + display: 'swap', + preload: true, + variable: '--roboto-100-italic', +}) +const myFont = localFont({ + src: '../fonts/my-font.woff2', + preload: false, + variable: '--my-font', +}) + +export default function WithFonts() { + return ( + <> + {/* Fira Code Variable */} +
+ With variables +
+
+ Without variables +
+ + {/* Roboto 100 Italic */} +
+ With variables +
+
+ Without variables +
+ + {/* Local font */} +
+ With variables +
+
+ Without variables +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-fallback.js b/test/e2e/next-font/app-old/pages/with-fallback.js new file mode 100644 index 0000000000000..eeebf33ccecd6 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-fallback.js @@ -0,0 +1,36 @@ +import localFont from '@next/font/local' +import { Open_Sans } from '@next/font/google' +const openSans = Open_Sans({ + fallback: ['system-ui', 'Arial'], + variable: '--open-sans', + adjustFontFallback: false, +}) + +const myFont = localFont({ + fallback: ['system-ui', 'Arial'], + src: '../fonts/my-font.woff2', + adjustFontFallback: false, +}) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(openSans)} +
+
+ {JSON.stringify(myFont)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-fonts.js b/test/e2e/next-font/app-old/pages/with-fonts.js new file mode 100644 index 0000000000000..13dbe3e46bf9f --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-fonts.js @@ -0,0 +1,14 @@ +import CompWithFonts from '../components/CompWithFonts' +import { openSans } from './_app' + +export default function WithFonts() { + return ( + <> + +
+ {JSON.stringify(openSans)} +
+
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-google-fonts.js b/test/e2e/next-font/app-old/pages/with-google-fonts.js new file mode 100644 index 0000000000000..acf3309a9ebfb --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-google-fonts.js @@ -0,0 +1,40 @@ +import { Fraunces, Indie_Flower, Roboto } from '@next/font/google' + +const indieFlower = Indie_Flower({ weight: '400', preload: false }) +const fraunces = Fraunces({ weight: '400', preload: false }) + +const robotoMultiple = Roboto({ + weight: ['900', '100'], + style: ['normal', 'italic'], +}) +const frauncesMultiple = Fraunces({ + style: ['italic', 'normal'], + axes: ['SOFT', 'WONK', 'opsz'], +}) + +const frauncesMultipleWeights = Fraunces({ weight: ['100', '400', '900'] }) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(indieFlower)} +
+
+ {JSON.stringify(fraunces)} +
+
+ {JSON.stringify(robotoMultiple)} +
+
+ {JSON.stringify(frauncesMultiple)} +
+
+ {JSON.stringify(frauncesMultipleWeights)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/with-local-fonts.js b/test/e2e/next-font/app-old/pages/with-local-fonts.js new file mode 100644 index 0000000000000..37f218859d243 --- /dev/null +++ b/test/e2e/next-font/app-old/pages/with-local-fonts.js @@ -0,0 +1,153 @@ +import localFont from '@next/font/local' + +const myFont1 = localFont({ + src: '../fonts/my-font.woff2', + style: 'italic', + weight: '100', + fallback: ['system-ui'], + adjustFontFallback: 'Times New Roman', +}) +const myFont2 = localFont({ + src: '../fonts/my-other-font.woff2', + preload: false, + variable: '--my-font', +}) + +const roboto = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-100-italic.woff2', + weight: '100', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '400', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '400', + }, + { + path: '../fonts/my-font.woff2', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '900', + style: 'normal', + }, + ], +}) + +const robotoVar1 = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '100 300', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '100 300', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '500 900', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '500 900', + style: 'normal', + }, + ], +}) + +const robotoVar2 = localFont({ + preload: false, + src: [ + { + path: '../fonts/roboto/roboto-900.woff2', + weight: '100 900', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-400.woff2', + weight: '100 900', + style: 'normal', + }, + { + path: '../fonts/my-font.woff2', + weight: '300 399', + style: 'italic', + }, + { + path: '../fonts/my-font.woff2', + weight: '401 500', + style: 'normal', + }, + ], +}) + +const robotoWithPreload = localFont({ + src: [ + { + path: '../fonts/roboto/roboto-100.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/roboto/roboto-900-italic.woff2', + weight: '900', + style: 'italic', + }, + { + path: '../fonts/roboto/roboto-100.woff2', + weight: '100', + style: 'normal', + }, + { + path: '../fonts/roboto/roboto-100-italic.woff2', + weight: '900', + style: 'italic', + }, + ], +}) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(myFont1)} +
+
+ {JSON.stringify(myFont2)} +
+
+ {JSON.stringify(roboto)} +
+
+ {JSON.stringify(robotoVar1)} +
+
+ {JSON.stringify(robotoVar2)} +
+
+ {JSON.stringify(robotoWithPreload)} +
+ + ) +} diff --git a/test/e2e/next-font/app-old/pages/without-fonts.js b/test/e2e/next-font/app-old/pages/without-fonts.js new file mode 100644 index 0000000000000..0f649722e671d --- /dev/null +++ b/test/e2e/next-font/app-old/pages/without-fonts.js @@ -0,0 +1,3 @@ +export default function WithoutFonts() { + return

Hello world

+} diff --git a/test/e2e/next-font/app/components/CompWithFonts.js b/test/e2e/next-font/app/components/CompWithFonts.js index 104526effb17d..50a98f1cff35a 100644 --- a/test/e2e/next-font/app/components/CompWithFonts.js +++ b/test/e2e/next-font/app/components/CompWithFonts.js @@ -1,4 +1,4 @@ -import { Inter, Roboto } from '@next/font/google' +import { Inter, Roboto } from 'next/font/google' const inter = Inter({ weight: '900', display: 'swap', preload: false }) const roboto = Roboto({ weight: '100', diff --git a/test/e2e/next-font/app/next.config.js b/test/e2e/next-font/app/next.config.js index 6a94ea94ad864..3f4a776b7f409 100644 --- a/test/e2e/next-font/app/next.config.js +++ b/test/e2e/next-font/app/next.config.js @@ -5,9 +5,6 @@ module.exports = { loader: '@next/font/google', options: { subsets: ['latin'] }, }, - { - loader: '@next/font/local', - }, ], }, } diff --git a/test/e2e/next-font/app/pages/_app.js b/test/e2e/next-font/app/pages/_app.js index 87fd0d1ed9b67..5d957229dc906 100644 --- a/test/e2e/next-font/app/pages/_app.js +++ b/test/e2e/next-font/app/pages/_app.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ variable: '--open-sans' }) function MyApp({ Component, pageProps }) { diff --git a/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js b/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js index 62ac7af99f5c1..b79674311253d 100644 --- a/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js +++ b/test/e2e/next-font/app/pages/font-without-preloadable-subsets.js @@ -1,4 +1,4 @@ -import { Single_Day } from '@next/font/google' +import { Single_Day } from 'next/font/google' const singleDay = Single_Day({ weight: '400' }) diff --git a/test/e2e/next-font/app/pages/variable-font-without-weight-range.js b/test/e2e/next-font/app/pages/variable-font-without-weight-range.js index bb78339d8d405..64ee22e9b955f 100644 --- a/test/e2e/next-font/app/pages/variable-font-without-weight-range.js +++ b/test/e2e/next-font/app/pages/variable-font-without-weight-range.js @@ -1,4 +1,4 @@ -import { Nabla } from '@next/font/google' +import { Nabla } from 'next/font/google' const nabla = Nabla() diff --git a/test/e2e/next-font/app/pages/variables.js b/test/e2e/next-font/app/pages/variables.js index e4b19c560a37a..e03b2be3856db 100644 --- a/test/e2e/next-font/app/pages/variables.js +++ b/test/e2e/next-font/app/pages/variables.js @@ -1,5 +1,5 @@ -import { Fira_Code, Roboto } from '@next/font/google' -import localFont from '@next/font/local' +import { Fira_Code, Roboto } from 'next/font/google' +import localFont from 'next/font/local' const firaCode = Fira_Code({ variable: '--fira-code' }) const roboto = Roboto({ diff --git a/test/e2e/next-font/app/pages/with-fallback.js b/test/e2e/next-font/app/pages/with-fallback.js index eeebf33ccecd6..9338f23d27278 100644 --- a/test/e2e/next-font/app/pages/with-fallback.js +++ b/test/e2e/next-font/app/pages/with-fallback.js @@ -1,5 +1,5 @@ -import localFont from '@next/font/local' -import { Open_Sans } from '@next/font/google' +import localFont from 'next/font/local' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ fallback: ['system-ui', 'Arial'], variable: '--open-sans', diff --git a/test/e2e/next-font/app/pages/with-google-fonts.js b/test/e2e/next-font/app/pages/with-google-fonts.js index acf3309a9ebfb..1332c4a761a65 100644 --- a/test/e2e/next-font/app/pages/with-google-fonts.js +++ b/test/e2e/next-font/app/pages/with-google-fonts.js @@ -1,4 +1,4 @@ -import { Fraunces, Indie_Flower, Roboto } from '@next/font/google' +import { Fraunces, Indie_Flower, Roboto } from 'next/font/google' const indieFlower = Indie_Flower({ weight: '400', preload: false }) const fraunces = Fraunces({ weight: '400', preload: false }) diff --git a/test/e2e/next-font/app/pages/with-local-fonts.js b/test/e2e/next-font/app/pages/with-local-fonts.js index 37f218859d243..645253ea14a8d 100644 --- a/test/e2e/next-font/app/pages/with-local-fonts.js +++ b/test/e2e/next-font/app/pages/with-local-fonts.js @@ -1,4 +1,4 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' const myFont1 = localFont({ src: '../fonts/my-font.woff2', diff --git a/test/e2e/next-font/basepath.test.ts b/test/e2e/next-font/basepath.test.ts index 5573ba99ba9fd..47964a90ab167 100644 --- a/test/e2e/next-font/basepath.test.ts +++ b/test/e2e/next-font/basepath.test.ts @@ -8,7 +8,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google basepath', () => { +describe('next/font/google basepath', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -24,9 +24,6 @@ describe('@next/font/google basepath', () => { join(__dirname, 'basepath/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/basepath/next.config.js b/test/e2e/next-font/basepath/next.config.js index 1be9432475a2c..4f15a0286194e 100644 --- a/test/e2e/next-font/basepath/next.config.js +++ b/test/e2e/next-font/basepath/next.config.js @@ -1,10 +1,3 @@ module.exports = { basePath: '/dashboard', - experimental: { - fontLoaders: [ - { - loader: '@next/font/local', - }, - ], - }, } diff --git a/test/e2e/next-font/basepath/pages/index.js b/test/e2e/next-font/basepath/pages/index.js index 3d0967e56b323..78c7d10857616 100644 --- a/test/e2e/next-font/basepath/pages/index.js +++ b/test/e2e/next-font/basepath/pages/index.js @@ -1,4 +1,4 @@ -import { Open_Sans } from '@next/font/google' +import { Open_Sans } from 'next/font/google' const openSans = Open_Sans({ subsets: ['latin'] }) export default function Inter() { diff --git a/test/e2e/next-font/google-fetch-error.test.ts b/test/e2e/next-font/google-fetch-error.test.ts index 582b4bf87a790..435da8570a572 100644 --- a/test/e2e/next-font/google-fetch-error.test.ts +++ b/test/e2e/next-font/google-fetch-error.test.ts @@ -7,7 +7,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google fetch error', () => { +describe('next/font/google fetch error', () => { const isDev = (global as any).isNextDev let next: NextInstance @@ -20,12 +20,6 @@ describe('@next/font/google fetch error', () => { next = await createNext({ files: { pages: new FileRef(join(__dirname, 'google-fetch-error/pages')), - 'next.config.js': new FileRef( - join(__dirname, 'google-fetch-error/next.config.js') - ), - }, - dependencies: { - '@next/font': 'canary', }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, diff --git a/test/e2e/next-font/google-fetch-error/pages/index.js b/test/e2e/next-font/google-fetch-error/pages/index.js index 229c3d6631c43..2653808616d3e 100644 --- a/test/e2e/next-font/google-fetch-error/pages/index.js +++ b/test/e2e/next-font/google-fetch-error/pages/index.js @@ -1,4 +1,4 @@ -import { Inter } from '@next/font/google' +import { Inter } from 'next/font/google' const inter = Inter({ weight: '400', subsets: ['latin'] }) export default function Page() { diff --git a/test/e2e/next-font/index.test.ts b/test/e2e/next-font/index.test.ts index 986a9ba443f10..e78db2e229a38 100644 --- a/test/e2e/next-font/index.test.ts +++ b/test/e2e/next-font/index.test.ts @@ -9,601 +9,605 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google', () => { - let next: NextInstance - - if ((global as any).isNextDeploy) { - it('should skip next deploy for now', () => {}) - return - } - - beforeAll(async () => { - next = await createNext({ - files: { - pages: new FileRef(join(__dirname, 'app/pages')), - components: new FileRef(join(__dirname, 'app/components')), - fonts: new FileRef(join(__dirname, 'app/fonts')), - 'next.config.js': new FileRef(join(__dirname, 'app/next.config.js')), - }, - dependencies: { - '@next/font': 'canary', - }, - env: { - NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, - }, - }) - }) - afterAll(() => next.destroy()) - - describe('import values', () => { - test('page with font', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ +describe('next/font', () => { + describe.each([['app'], ['app-old']])('%s', (fixture: string) => { + let next: NextInstance + + if ((global as any).isNextDeploy) { + it('should skip next deploy for now', () => {}) + return + } + + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, `${fixture}/pages`)), + components: new FileRef(join(__dirname, `${fixture}/components`)), + fonts: new FileRef(join(__dirname, `${fixture}/fonts`)), + 'next.config.js': new FileRef( + join(__dirname, `${fixture}/next.config.js`) ), - fontStyle: 'normal', }, - }) - - // with-fonts.js - expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', + dependencies: { + '@next/font': 'canary', }, - }) - - // CompWithFonts.js - expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ - ), - fontWeight: 900, - fontStyle: 'normal', - }, - }) - expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ - ), - fontStyle: 'italic', - fontWeight: 100, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, }) }) - - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - variable: expect.stringMatching(/__variable_.{6}/), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, + afterAll(() => next.destroy()) + + describe('import values', () => { + test('page with font', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // with-fonts.js + expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // CompWithFonts.js + expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ + ), + fontWeight: 900, + fontStyle: 'normal', + }, + }) + expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) }) - // with-local-fonts.js - expect(JSON.parse($('#first-local-font').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - style: { - fontFamily: expect.stringMatching( - /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ - ), - fontStyle: 'italic', - fontWeight: 100, - }, + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + variable: expect.stringMatching(/__variable_.{6}/), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // with-local-fonts.js + expect(JSON.parse($('#first-local-font').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + style: { + fontFamily: expect.stringMatching( + /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) + expect(JSON.parse($('#second-local-font').text())).toEqual({ + className: expect.stringMatching(/^__className_.{6}$/), + variable: expect.stringMatching(/^__variable_.{6}$/), + style: { + fontFamily: expect.stringMatching( + /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ + ), + }, + }) }) - expect(JSON.parse($('#second-local-font').text())).toEqual({ - className: expect.stringMatching(/^__className_.{6}$/), - variable: expect.stringMatching(/^__variable_.{6}$/), - style: { - fontFamily: expect.stringMatching( - /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ - ), - }, - }) - }) - - test('Variable font without weight range', async () => { - const html = await renderViaHTTP( - next.url, - '/variable-font-without-weight-range' - ) - const $ = cheerio.load(html) - - expect(JSON.parse($('#nabla').text())).toEqual({ - className: expect.stringMatching(/__className_.{6}/), - style: { - fontFamily: expect.stringMatching(/^'__Nabla_.{6}'$/), - fontStyle: 'normal', - }, - }) - }) - }) - describe('computed styles', () => { - test('page with fonts', async () => { - const browser = await webdriver(next.url, '/with-fonts') - - // _app.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' + test('Variable font without weight range', async () => { + const html = await renderViaHTTP( + next.url, + '/variable-font-without-weight-range' ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' - ) - ).toBe('normal') + const $ = cheerio.load(html) - // with-fonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' - ) - ).toBe('normal') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' - ) - ).toBe('normal') - - // CompWithFonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' - ) - ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' - ) - ).toBe('900') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' - ) - ).toBe('normal') - - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' - ) - ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' - ) - ).toBe('100') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' - ) - ).toBe('italic') - }) - - test('page using variables', async () => { - const browser = await webdriver(next.url, '/variables') - - // Fira Code Variable - const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' - ) - ).toMatch(firaCodeRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' - ) - ).not.toMatch(firaCodeRegex) - - // Roboto 100 Italic - const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' - ) - ).toMatch(roboto100ItalicRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' - ) - ).not.toMatch(roboto100ItalicRegex) - - // Local font - const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' - ) - ).toMatch(localFontRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' - ) - ).not.toMatch(localFontRegex) - }) - - test('page using fallback fonts', async () => { - const browser = await webdriver(next.url, '/with-fallback') - - // .className - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .style - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .variable - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - }) - }) - - describe('preload', () => { - test('page with fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - expect($('link[as="font"]').length).toBe(2) - // From /_app - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }) - expect($('link[as="font"]').get(1).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/675c25f648fd6a30-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + expect(JSON.parse($('#nabla').text())).toEqual({ + className: expect.stringMatching(/__className_.{6}/), + style: { + fontFamily: expect.stringMatching(/^'__Nabla_.{6}'$/), + fontStyle: 'normal', + }, + }) }) }) - test('page without fonts', async () => { - const html = await renderViaHTTP(next.url, '/without-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From _app - expect($('link[as="font"]').length).toBe(1) - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', + describe('computed styles', () => { + test('page with fonts', async () => { + const browser = await webdriver(next.url, '/with-fonts') + + // _app.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' + ) + ).toBe('normal') + + // with-fonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' + ) + ).toBe('normal') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' + ) + ).toBe('normal') + + // CompWithFonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' + ) + ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' + ) + ).toBe('900') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' + ) + ).toBe('normal') + + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' + ) + ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' + ) + ).toBe('100') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' + ) + ).toBe('italic') }) - }) - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // Preload - expect($('link[as="font"]').length).toBe(5) - expect( - Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() - ).toEqual([ - '/_next/static/media/02205c9944024f15-s.p.woff2', - '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - '/_next/static/media/1deec1af325840fd-s.p.woff2', - '/_next/static/media/ab6fdae82d1a8d92-s.p.woff2', - '/_next/static/media/d55edb6f37902ebf-s.p.woff2', - ]) - }) - - test('google fonts with multiple weights/styles', async () => { - const html = await renderViaHTTP(next.url, '/with-google-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // Preload - expect($('link[as="font"]').length).toBe(8) - - expect( - Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() - ).toEqual([ - '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - '/_next/static/media/4f3dcdf40b3ca86d-s.p.woff2', - '/_next/static/media/560a6db6ac485cb1-s.p.woff2', - '/_next/static/media/686d1702f12625fe-s.p.woff2', - '/_next/static/media/86d92167ff02c708-s.p.woff2', - '/_next/static/media/9ac01b894b856187-s.p.woff2', - '/_next/static/media/c9baea324111137d-s.p.woff2', - '/_next/static/media/fb68b4558e2a718e-s.p.woff2', - ]) - }) - - test('font without preloadable subsets', async () => { - const html = await renderViaHTTP( - next.url, - '/font-without-preloadable-subsets' - ) - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From _app - expect($('link[as="font"]').length).toBe(1) - expect($('link[as="font"]').get(0).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': 'size-adjust', - }) - }) - - test('font without size adjust', async () => { - const html = await renderViaHTTP(next.url, '/with-fallback') - const $ = cheerio.load(html) - - expect($('link[as="font"]').get(1).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/0812efcfaefec5ea.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': '', + test('page using variables', async () => { + const browser = await webdriver(next.url, '/variables') + + // Fira Code Variable + const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' + ) + ).toMatch(firaCodeRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' + ) + ).not.toMatch(firaCodeRegex) + + // Roboto 100 Italic + const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' + ) + ).toMatch(roboto100ItalicRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' + ) + ).not.toMatch(roboto100ItalicRegex) + + // Local font + const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' + ) + ).toMatch(localFontRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' + ) + ).not.toMatch(localFontRegex) }) - expect($('link[as="font"]').get(2).attribs).toEqual({ - as: 'font', - crossorigin: 'anonymous', - href: '/_next/static/media/ab6fdae82d1a8d92.p.woff2', - rel: 'preload', - type: 'font/woff2', - 'data-next-font': '', + test('page using fallback fonts', async () => { + const browser = await webdriver(next.url, '/with-fallback') + + // .className + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .style + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .variable + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) }) }) - }) - describe('Fallback fontfaces', () => { - describe('local', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.26%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.94%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94%') + describe('preload', () => { + test('page with fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + expect($('link[as="font"]').length).toBe(2) + // From /_app + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/675c25f648fd6a30-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) }) - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') + test('page without fonts', async () => { + const html = await renderViaHTTP(next.url, '/without-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) }) - test('Roboto multiple weights and styles', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(5) + expect( + Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + ).toEqual([ + '/_next/static/media/02205c9944024f15-s.p.woff2', + '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + '/_next/static/media/1deec1af325840fd-s.p.woff2', + '/_next/static/media/ab6fdae82d1a8d92-s.p.woff2', + '/_next/static/media/d55edb6f37902ebf-s.p.woff2', + ]) }) - test('Roboto multiple weights and styles - variable 1', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('google fonts with multiple weights/styles', async () => { + const html = await renderViaHTTP(next.url, '/with-google-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(8) + + expect( + Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + ).toEqual([ + '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + '/_next/static/media/4f3dcdf40b3ca86d-s.p.woff2', + '/_next/static/media/560a6db6ac485cb1-s.p.woff2', + '/_next/static/media/686d1702f12625fe-s.p.woff2', + '/_next/static/media/86d92167ff02c708-s.p.woff2', + '/_next/static/media/9ac01b894b856187-s.p.woff2', + '/_next/static/media/c9baea324111137d-s.p.woff2', + '/_next/static/media/fb68b4558e2a718e-s.p.woff2', + ]) }) - test('Roboto multiple weights and styles - variable 2', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') + test('font without preloadable subsets', async () => { + const html = await renderViaHTTP( + next.url, + '/font-without-preloadable-subsets' + ) + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + expect($('link[as="font"]').get(0).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea-s.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': 'size-adjust', + }) + }) - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') + test('font without size adjust', async () => { + const html = await renderViaHTTP(next.url, '/with-fallback') + const $ = cheerio.load(html) + + expect($('link[as="font"]').get(1).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/0812efcfaefec5ea.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': '', + }) + + expect($('link[as="font"]').get(2).attribs).toEqual({ + as: 'font', + crossorigin: 'anonymous', + href: '/_next/static/media/ab6fdae82d1a8d92.p.woff2', + rel: 'preload', + type: 'font/woff2', + 'data-next-font': '', + }) }) }) - describe('google', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.26%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.94%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94%') + describe('Fallback fontfaces', () => { + describe('local', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.26%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.94%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94%') + }) + + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') + }) + + test('Roboto multiple weights and styles', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) + + test('Roboto multiple weights and styles - variable 1', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) + + test('Roboto multiple weights and styles - variable 2', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) }) - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') + describe('google', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.26%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.94%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94%') + }) + + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') + }) }) }) }) diff --git a/test/e2e/next-font/with-font-declarations-file.test.ts b/test/e2e/next-font/with-font-declarations-file.test.ts index fcfb44beb75b1..383f69d433b14 100644 --- a/test/e2e/next-font/with-font-declarations-file.test.ts +++ b/test/e2e/next-font/with-font-declarations-file.test.ts @@ -10,7 +10,7 @@ const mockedGoogleFontResponses = require.resolve( const isDev = (global as any).isNextDev -describe('@next/font/google with-font-declarations-file', () => { +describe('next/font/google with-font-declarations-file', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -37,9 +37,6 @@ describe('@next/font/google with-font-declarations-file', () => { join(__dirname, 'with-font-declarations-file/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/with-font-declarations-file/fonts.js b/test/e2e/next-font/with-font-declarations-file/fonts.js index f6c1c4071f5a6..8fb3a2914330f 100644 --- a/test/e2e/next-font/with-font-declarations-file/fonts.js +++ b/test/e2e/next-font/with-font-declarations-file/fonts.js @@ -1,11 +1,11 @@ -import localFont from '@next/font/local' +import localFont from 'next/font/local' import { Open_Sans, Source_Code_Pro, Abel, Inter, Roboto, -} from '@next/font/google' +} from 'next/font/google' const openSans = Open_Sans() const sourceCodePro = Source_Code_Pro({ display: 'swap', preload: false }) diff --git a/test/e2e/next-font/without-preloaded-fonts.test.ts b/test/e2e/next-font/without-preloaded-fonts.test.ts index a2d71bf730807..b71000c7d645c 100644 --- a/test/e2e/next-font/without-preloaded-fonts.test.ts +++ b/test/e2e/next-font/without-preloaded-fonts.test.ts @@ -8,7 +8,7 @@ const mockedGoogleFontResponses = require.resolve( './google-font-mocked-responses.js' ) -describe('@next/font/google without-preloaded-fonts without _app', () => { +describe('next/font/google without-preloaded-fonts without _app', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -29,9 +29,6 @@ describe('@next/font/google without-preloaded-fonts without _app', () => { join(__dirname, 'without-preloaded-fonts/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, @@ -65,7 +62,7 @@ describe('@next/font/google without-preloaded-fonts without _app', () => { }) }) -describe('@next/font/google no preloads with _app', () => { +describe('next/font/google no preloads with _app', () => { let next: NextInstance if ((global as any).isNextDeploy) { @@ -89,9 +86,6 @@ describe('@next/font/google no preloads with _app', () => { join(__dirname, 'without-preloaded-fonts/next.config.js') ), }, - dependencies: { - '@next/font': 'canary', - }, env: { NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, }, diff --git a/test/e2e/next-font/without-preloaded-fonts/pages/_app.js b/test/e2e/next-font/without-preloaded-fonts/pages/_app.js index a19d81c7a1c8a..723151757dd3a 100644 --- a/test/e2e/next-font/without-preloaded-fonts/pages/_app.js +++ b/test/e2e/next-font/without-preloaded-fonts/pages/_app.js @@ -1,4 +1,4 @@ -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' const abel = Abel({ weight: '400', display: 'optional', preload: false }) function MyApp({ Component, pageProps }) { diff --git a/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js b/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js index 4ebfef35a2ed8..9213aafe9f842 100644 --- a/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js +++ b/test/e2e/next-font/without-preloaded-fonts/pages/no-preload.js @@ -1,4 +1,4 @@ -import { Abel } from '@next/font/google' +import { Abel } from 'next/font/google' const abel = Abel({ weight: '400', display: 'optional', preload: false }) export default function NoPreload() { From f6d48f4b6c778760e3785a503a6c68e2593c4331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 8 Feb 2023 16:00:25 +0100 Subject: [PATCH 13/14] Fix lint --- packages/next/src/build/webpack/config/blocks/css/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/next/src/build/webpack/config/blocks/css/index.ts b/packages/next/src/build/webpack/config/blocks/css/index.ts index 23af18b6bcdba..1cf252f86d116 100644 --- a/packages/next/src/build/webpack/config/blocks/css/index.ts +++ b/packages/next/src/build/webpack/config/blocks/css/index.ts @@ -1,4 +1,3 @@ -import path from 'path' import curry from 'next/dist/compiled/lodash.curry' import { webpack } from 'next/dist/compiled/webpack/webpack' import { loader, plugin } from '../../helpers' From 782fd89c0d15762ff187d3ffeba2cfa78b4dff08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Thu, 9 Feb 2023 14:53:17 +0100 Subject: [PATCH 14/14] Update next.config.js option --- packages/next/src/build/webpack/config/blocks/css/index.ts | 4 +++- test/e2e/next-font/app/next.config.js | 2 +- test/e2e/next-font/with-font-declarations-file/next.config.js | 2 +- test/e2e/next-font/without-preloaded-fonts/next.config.js | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/next/src/build/webpack/config/blocks/css/index.ts b/packages/next/src/build/webpack/config/blocks/css/index.ts index 1c21332d7f9e4..81cd33f4c1064 100644 --- a/packages/next/src/build/webpack/config/blocks/css/index.ts +++ b/packages/next/src/build/webpack/config/blocks/css/index.ts @@ -182,7 +182,9 @@ export const css = curry(async function css( const googleLoaderOptions = ctx.experimental?.fontLoaders?.find( - (loaderConfig) => loaderConfig.loader === '@next/font/google' + (loaderConfig) => + loaderConfig.loader === 'next/font/google' || + loaderConfig.loader === '@next/font/google' )?.options ?? {} const fontLoaders: Array<[string | RegExp, string, any?]> = [ [ diff --git a/test/e2e/next-font/app/next.config.js b/test/e2e/next-font/app/next.config.js index 3f4a776b7f409..51b19fbc18002 100644 --- a/test/e2e/next-font/app/next.config.js +++ b/test/e2e/next-font/app/next.config.js @@ -2,7 +2,7 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, ], diff --git a/test/e2e/next-font/with-font-declarations-file/next.config.js b/test/e2e/next-font/with-font-declarations-file/next.config.js index 3f4a776b7f409..51b19fbc18002 100644 --- a/test/e2e/next-font/with-font-declarations-file/next.config.js +++ b/test/e2e/next-font/with-font-declarations-file/next.config.js @@ -2,7 +2,7 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, ], diff --git a/test/e2e/next-font/without-preloaded-fonts/next.config.js b/test/e2e/next-font/without-preloaded-fonts/next.config.js index 3f4a776b7f409..51b19fbc18002 100644 --- a/test/e2e/next-font/without-preloaded-fonts/next.config.js +++ b/test/e2e/next-font/without-preloaded-fonts/next.config.js @@ -2,7 +2,7 @@ module.exports = { experimental: { fontLoaders: [ { - loader: '@next/font/google', + loader: 'next/font/google', options: { subsets: ['latin'] }, }, ],