From 86191439c94df941606b99d17d77f3e857f48d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:02:00 +0200 Subject: [PATCH 1/8] Use size-adjust in google fonts --- packages/font/src/google/loader.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/font/src/google/loader.ts b/packages/font/src/google/loader.ts index a3583d19ccbc7..8618fdcc6fac5 100644 --- a/packages/font/src/google/loader.ts +++ b/packages/font/src/google/loader.ts @@ -2,7 +2,7 @@ import type { AdjustFontFallback, FontLoader } from 'next/font' // @ts-ignore import fetch from 'next/dist/compiled/node-fetch' // @ts-ignore -import { calculateOverrideValues } from 'next/dist/server/font-utils' +import { calculateSizeAdjustValues } from 'next/dist/server/font-utils' import { fetchCSSFromGoogleFonts, getFontAxes, @@ -101,16 +101,17 @@ const downloadGoogleFonts: FontLoader = async ({ let adjustFontFallbackMetrics: AdjustFontFallback | undefined if (adjustFontFallback) { try { - const { ascent, descent, lineGap, fallbackFont } = - calculateOverrideValues( + const { ascent, descent, lineGap, fallbackFont, sizeAdjust } = + calculateSizeAdjustValues( fontFamily, require('next/dist/server/google-font-metrics.json') ) adjustFontFallbackMetrics = { fallbackFont, - ascentOverride: ascent, - descentOverride: descent, - lineGapOverride: lineGap, + ascentOverride: `${ascent}%`, + descentOverride: `${descent}%`, + lineGapOverride: `${lineGap}%`, + sizeAdjust: `${sizeAdjust}%`, } } catch { console.error( From 1db32a85ec386f88ab07a2c89516c1bdea59799a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:02:34 +0200 Subject: [PATCH 2/8] Add fontkit as a dep, needed for reading font file metadata --- packages/font/package.json | 6 +++ pnpm-lock.yaml | 106 +++++++++++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 5 deletions(-) diff --git a/packages/font/package.json b/packages/font/package.json index 3d454280cd30c..41621b0bb88bc 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -16,5 +16,11 @@ "prepublishOnly": "cd ../../ && turbo run build", "dev": "tsc -d -w -p tsconfig.json", "typescript": "tsec --noEmit -p tsconfig.json" + }, + "dependencies": { + "fontkit": "2.0.2" + }, + "devDependencies": { + "@types/fontkit": "2.0.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0d95082e8b090..7e511d7558c47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -429,7 +429,13 @@ importers: eslint: 7.24.0 packages/font: - specifiers: {} + specifiers: + '@types/fontkit': 2.0.0 + fontkit: 2.0.2 + dependencies: + fontkit: 2.0.2 + devDependencies: + '@types/fontkit': 2.0.0 packages/next: specifiers: @@ -596,8 +602,8 @@ importers: source-map: 0.6.1 stream-browserify: 3.0.0 stream-http: 3.1.1 - string_decoder: 1.3.0 string-hash: 1.1.3 + string_decoder: 1.3.0 strip-ansi: 6.0.0 styled-jsx: 5.0.7 tar: 6.1.11 @@ -786,8 +792,8 @@ importers: source-map: 0.6.1 stream-browserify: 3.0.0 stream-http: 3.1.1 - string_decoder: 1.3.0 string-hash: 1.1.3 + string_decoder: 1.3.0 strip-ansi: 6.0.0 tar: 6.1.11 taskr: 1.1.0 @@ -7343,6 +7349,15 @@ packages: } dev: true + /@types/fontkit/2.0.0: + resolution: + { + integrity: sha512-Qe+6szpPLTNsqkDFs2MScJyB51d5Hpobyg/T0QoUWO53WuNOTNLsV8fkE4QQPOJbhOMN5wlwmNeDdsh/e6Uqdg==, + } + dependencies: + '@types/node': 17.0.21 + dev: true + /@types/fresh/0.5.0: resolution: { @@ -9801,7 +9816,6 @@ packages: { integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, } - dev: true /bcrypt-pbkdf/1.0.2: resolution: @@ -10029,6 +10043,15 @@ packages: duplexer: 0.1.1 dev: true + /brotli/1.3.3: + resolution: + { + integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==, + } + dependencies: + base64-js: 1.5.1 + dev: false + /browser-process-hrtime/1.0.0: resolution: { @@ -11089,6 +11112,14 @@ packages: engines: { node: '>=0.8' } dev: true + /clone/2.1.2: + resolution: + { + integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==, + } + engines: { node: '>=0.8' } + dev: false + /clor/5.2.0: resolution: { @@ -11620,8 +11651,8 @@ packages: engines: { node: '>=10' } hasBin: true dependencies: - is-text-path: 1.0.1 JSONStream: 1.3.5 + is-text-path: 1.0.1 lodash: 4.17.21 meow: 8.1.2 split2: 2.2.0 @@ -12995,6 +13026,13 @@ packages: wrappy: 1.0.2 dev: true + /dfa/1.2.0: + resolution: + { + integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==, + } + dev: false + /diagnostics_channel/1.1.0: resolution: { @@ -15208,6 +15246,23 @@ packages: - supports-color dev: true + /fontkit/2.0.2: + resolution: + { + integrity: sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==, + } + dependencies: + '@swc/helpers': 0.4.11 + brotli: 1.3.3 + clone: 2.1.2 + dfa: 1.2.0 + fast-deep-equal: 3.1.3 + restructure: 3.0.0 + tiny-inflate: 1.0.3 + unicode-properties: 1.4.1 + unicode-trie: 2.0.0 + dev: false + /for-in/1.0.2: resolution: { @@ -22838,6 +22893,13 @@ packages: - supports-color dev: true + /pako/0.2.9: + resolution: + { + integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==, + } + dev: false + /pako/1.0.11: resolution: { @@ -26353,6 +26415,13 @@ packages: signal-exit: 3.0.3 dev: true + /restructure/3.0.0: + resolution: + { + integrity: sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==, + } + dev: false + /ret/0.1.15: resolution: { @@ -28610,6 +28679,13 @@ packages: globrex: 0.1.2 dev: true + /tiny-inflate/1.0.3: + resolution: + { + integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==, + } + dev: false + /tinydate/1.2.0: resolution: { @@ -29293,6 +29369,16 @@ packages: } engines: { node: '>=4' } + /unicode-properties/1.4.1: + resolution: + { + integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==, + } + dependencies: + base64-js: 1.5.1 + unicode-trie: 2.0.0 + dev: false + /unicode-property-aliases-ecmascript/1.0.5: resolution: { @@ -29308,6 +29394,16 @@ packages: } engines: { node: '>=4' } + /unicode-trie/2.0.0: + resolution: + { + integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==, + } + dependencies: + pako: 0.2.9 + tiny-inflate: 1.0.3 + dev: false + /unified-diff/3.1.0: resolution: { From 2e05e829eaae049b6a5107ceef5a058d202b9ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:22:49 +0200 Subject: [PATCH 3/8] Generated fallback font for local files --- packages/font/src/local/index.ts | 6 +- packages/font/src/local/loader.ts | 91 +++++++++++++++++++++--------- packages/font/src/local/utils.ts | 50 +++++----------- packages/next/server/font-utils.ts | 4 +- 4 files changed, 83 insertions(+), 68 deletions(-) diff --git a/packages/font/src/local/index.ts b/packages/font/src/local/index.ts index c029157ce069d..805e1c382cebe 100644 --- a/packages/font/src/local/index.ts +++ b/packages/font/src/local/index.ts @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -import type { AdjustFontFallback, FontModule } from 'next/font' +import type { FontModule } from 'next/font' type Display = 'auto' | 'block' | 'swap' | 'fallback' | 'optional' type CssVariable = `--${string}` type LocalFont = { - src: string | Array<{ file: string; unicodeRange: string }> + src: string display?: Display weight?: number style?: string @@ -20,7 +20,7 @@ type LocalFont = { lineGapOverride?: string sizeAdjust?: string - adjustFontFallback?: AdjustFontFallback + adjustFontFallback?: 'Arial' | 'Times New Roman' | false } export default function localFont(options: LocalFont): FontModule { diff --git a/packages/font/src/local/loader.ts b/packages/font/src/local/loader.ts index 78fdd6e5af2ec..41c14d3a7a559 100644 --- a/packages/font/src/local/loader.ts +++ b/packages/font/src/local/loader.ts @@ -1,4 +1,7 @@ -import type { FontLoader } from 'next/font' +// @ts-ignore +import { calculateSizeAdjustValues } from 'next/dist/server/font-utils' +import fontkit from 'fontkit' +import type { AdjustFontFallback, FontLoader } from 'next/font' import { promisify } from 'util' import { validateData } from './utils' @@ -12,7 +15,9 @@ const fetchFonts: FontLoader = async ({ }) => { const { family, - files, + src, + ext, + format, display, weight, style, @@ -28,45 +33,75 @@ const fetchFonts: FontLoader = async ({ adjustFontFallback, } = validateData(functionName, data) - const fontFaces = await Promise.all( - files.map(async ({ file, ext, format, unicodeRange }) => { - const resolved = await resolve(file) - const fileBuffer = await promisify(fs.readFile)(resolved) + const resolved = await resolve(src) + const fileBuffer = await promisify(fs.readFile)(resolved) + const fontUrl = emitFontFile(fileBuffer, ext, preload) - const fontUrl = emitFontFile(fileBuffer, ext, preload) + let fontMetadata: fontkit.Font | undefined + try { + fontMetadata = fontkit.create(fileBuffer) + } catch (e) { + console.error(`Failed to load font file: ${resolved}\n${e}`) + } + + // Add fallback font + let adjustFontFallbackMetrics: AdjustFontFallback | undefined + if (fontMetadata && adjustFontFallback !== false) { + const { + ascent, + descent, + lineGap, + fallbackFont, + sizeAdjust: fallbackSizeAdjust, + } = calculateSizeAdjustValues('local', { + local: { + category: + adjustFontFallback === 'Times New Roman' ? 'serif' : 'sans-serif', + ascent: fontMetadata.ascent, + descent: fontMetadata.descent, + lineGap: fontMetadata.lineGap, + unitsPerEm: fontMetadata.unitsPerEm, + xAvgCharWidth: (fontMetadata as any)['OS/2']?.xAvgCharWidth, + }, + }) + adjustFontFallbackMetrics = { + fallbackFont, + ascentOverride: `${ascent}%`, + descentOverride: `${descent}%`, + lineGapOverride: `${lineGap}%`, + sizeAdjust: `${fallbackSizeAdjust}%`, + } + } - const fontFaceProperties = [ - ['font-family', `'${family}'`], - ['src', `url(${fontUrl}) format('${format}')`], - ['font-display', display], - ...(weight ? [['font-weight', weight]] : []), - ...(style ? [['font-style', style]] : []), - ...(ascentOverride ? [['ascent-override', ascentOverride]] : []), - ...(descentOverride ? [['descent-override', descentOverride]] : []), - ...(lineGapOverride ? [['line-gap-override', lineGapOverride]] : []), - ...(fontStretch ? [['font-stretch', fontStretch]] : []), - ...(fontFeatureSettings - ? [['font-feature-settings', fontFeatureSettings]] - : []), - ...(sizeAdjust ? [['size-adjust', sizeAdjust]] : []), - ...(unicodeRange ? [['unicode-range', unicodeRange]] : ''), - ] + const fontFaceProperties = [ + ['font-family', `'${fontMetadata?.familyName ?? family}'`], + ['src', `url(${fontUrl}) format('${format}')`], + ['font-display', display], + ...(weight ? [['font-weight', weight]] : []), + ...(style ? [['font-style', style]] : []), + ...(ascentOverride ? [['ascent-override', ascentOverride]] : []), + ...(descentOverride ? [['descent-override', descentOverride]] : []), + ...(lineGapOverride ? [['line-gap-override', lineGapOverride]] : []), + ...(fontStretch ? [['font-stretch', fontStretch]] : []), + ...(fontFeatureSettings + ? [['font-feature-settings', fontFeatureSettings]] + : []), + ...(sizeAdjust ? [['size-adjust', sizeAdjust]] : []), + ] - return `@font-face { + const css = `@font-face { ${fontFaceProperties .map(([property, value]) => `${property}: ${value};`) .join('\n')} }` - }) - ) return { - css: fontFaces.join('\n'), + css, fallbackFonts: fallback, weight, style, variable, - adjustFontFallback, + adjustFontFallback: adjustFontFallbackMetrics, } } diff --git a/packages/font/src/local/utils.ts b/packages/font/src/local/utils.ts index 5741a40c296dd..1ca7edffd016b 100644 --- a/packages/font/src/local/utils.ts +++ b/packages/font/src/local/utils.ts @@ -1,5 +1,3 @@ -import { AdjustFontFallback } from 'next/font' - const allowedDisplayValues = ['auto', 'block', 'swap', 'fallback', 'optional'] const formatValues = (values: string[]) => @@ -15,12 +13,9 @@ const extToFormat = { type FontOptions = { family: string - files: Array<{ - file: string - ext: string - format: string - unicodeRange?: string - }> + src: string + ext: string + format: string display: string weight?: number style?: string @@ -35,7 +30,7 @@ type FontOptions = { fontVariationSettings?: string lineGapOverride?: string sizeAdjust?: string - adjustFontFallback?: AdjustFontFallback + adjustFontFallback?: string | false } export function validateData(functionName: string, data: any): FontOptions { if (functionName) { @@ -68,39 +63,22 @@ export function validateData(functionName: string, data: any): FontOptions { ) } - const srcArray = Array.isArray(src) ? src : [{ file: src }] - - if (srcArray.length === 0) { - throw new Error('Src must contain one or more files') + if (!src) { + throw new Error('Missing required `src` property') } - const files = srcArray.map(({ file, unicodeRange }) => { - if (!file) { - throw new Error('Src array objects must have a `file` property') - } - if (srcArray.length > 1 && !unicodeRange) { - throw new Error( - "Files must have a unicode-range if there's more than one" - ) - } - - const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(file)?.[1] - if (!ext) { - throw new Error(`Unexpected file \`${file}\``) - } - return { - file, - unicodeRange, - ext, - format: extToFormat[ext as 'woff' | 'woff2' | 'eot' | 'ttf' | 'otf'], - } - }) + const ext = /\.(woff|woff2|eot|ttf|otf)$/.exec(src)?.[1] + if (!ext) { + throw new Error(`Unexpected file \`${src}\``) + } - const family = /.+\/(.+?)\./.exec(files[0].file)![1] + const family = /.+\/(.+?)\./.exec(src)![1] return { family, - files, + src, + ext, + format: extToFormat[ext as 'woff' | 'woff2' | 'eot' | 'ttf' | 'otf'], display, weight, style, diff --git a/packages/next/server/font-utils.ts b/packages/next/server/font-utils.ts index f37978575670f..de3f48a341836 100644 --- a/packages/next/server/font-utils.ts +++ b/packages/next/server/font-utils.ts @@ -126,7 +126,9 @@ export function calculateSizeAdjustValues(font: string, fontMetrics: any) { const fallbackFont = category === 'serif' ? DEFAULT_SERIF_FONT : DEFAULT_SANS_SERIF_FONT - let sizeAdjust = xAvgCharWidth / fallbackFont.xAvgCharWidth + let sizeAdjust = xAvgCharWidth + ? xAvgCharWidth / fallbackFont.xAvgCharWidth + : 1 ascent = formatOverrideValue(ascent / (unitsPerEm * sizeAdjust)) descent = formatOverrideValue(descent / (unitsPerEm * sizeAdjust)) From 94d3ee5ed9365ab3681975a866f36c9f54b3e8f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:23:14 +0200 Subject: [PATCH 4/8] Update unit tests --- test/unit/google-font-loader.test.ts | 21 ++-- test/unit/local-font-loader.test.ts | 178 +-------------------------- 2 files changed, 13 insertions(+), 186 deletions(-) diff --git a/test/unit/google-font-loader.test.ts b/test/unit/google-font-loader.test.ts index f51772c7ea446..3bb967e7342ac 100644 --- a/test/unit/google-font-loader.test.ts +++ b/test/unit/google-font-loader.test.ts @@ -102,10 +102,11 @@ describe('@next/font/google loader', () => { fs: {} as any, }) expect(adjustFontFallback).toEqual({ - ascentOverride: '96.88', - descentOverride: '24.15', + ascentOverride: '47.65%', + descentOverride: '11.88%', fallbackFont: 'Arial', - lineGapOverride: '0.00', + lineGapOverride: '0.00%', + sizeAdjust: '203.32%', }) expect(fallbackFonts).toBeUndefined() }) @@ -124,10 +125,11 @@ describe('@next/font/google loader', () => { fs: {} as any, }) expect(adjustFontFallback).toEqual({ - ascentOverride: '98.40', - descentOverride: '27.30', + ascentOverride: '148.26%', + descentOverride: '41.13%', fallbackFont: 'Arial', - lineGapOverride: '0.00', + lineGapOverride: '0.00%', + sizeAdjust: '66.37%', }) expect(fallbackFonts).toBeUndefined() }) @@ -146,10 +148,11 @@ describe('@next/font/google loader', () => { fs: {} as any, }) expect(adjustFontFallback).toEqual({ - ascentOverride: '97.80', - descentOverride: '25.50', + ascentOverride: '63.47%', + descentOverride: '16.55%', fallbackFont: 'Times New Roman', - lineGapOverride: '0.00', + lineGapOverride: '0.00%', + sizeAdjust: '154.08%', }) expect(fallbackFonts).toEqual(['Abc', 'Def']) }) diff --git a/test/unit/local-font-loader.test.ts b/test/unit/local-font-loader.test.ts index b314024d8de38..f174ceb21d61d 100644 --- a/test/unit/local-font-loader.test.ts +++ b/test/unit/local-font-loader.test.ts @@ -1,4 +1,5 @@ import loader from '@next/font/local/loader' +import { calculateSizeAdjustValues } from '@next/font/dist/local/utils' describe('@next/font/local', () => { describe('generated CSS', () => { @@ -23,51 +24,6 @@ font-display: optional; `) }) - test('Default CSS - src array with unicodeRange', async () => { - const { css } = await loader({ - functionName: '', - data: [ - { src: [{ file: './my-font.woff2', unicodeRange: 'unicode-range' }] }, - ], - config: {}, - emitFontFile: () => '/_next/static/media/my-font.woff2', - resolve: jest.fn(), - fs: { - readFile: (_, cb) => cb(null, 'fontdata'), - }, - }) - - expect(css).toMatchInlineSnapshot(` -"@font-face { -font-family: 'my-font'; -src: url(/_next/static/media/my-font.woff2) format('woff2'); -font-display: optional; -unicode-range: unicode-range; -}" -`) - }) - - test('Default CSS - src array without unicodeRange', async () => { - const { css } = await loader({ - functionName: '', - data: [{ src: [{ file: './my-font.woff2' }] }], - config: {}, - emitFontFile: () => '/_next/static/media/my-font.woff2', - resolve: jest.fn(), - fs: { - readFile: (_, cb) => cb(null, 'fontdata'), - }, - }) - - expect(css).toMatchInlineSnapshot(` -"@font-face { -font-family: 'my-font'; -src: url(/_next/static/media/my-font.woff2) format('woff2'); -font-display: optional; -}" -`) - }) - test('Weight and style', async () => { const { css } = await loader({ functionName: '', @@ -129,62 +85,6 @@ font-stretch: fontStretch; font-feature-settings: fontFeatureSettings; size-adjust: sizeAdjust; }" -`) - }) - - test('Multiple files', async () => { - const { css } = await loader({ - functionName: '', - data: [ - { - src: [ - { file: './my-font1.woff', unicodeRange: '1' }, - { file: './my-font2.woff2', unicodeRange: '2' }, - { file: './my-font3.eot', unicodeRange: '3' }, - { file: './my-font4.ttf', unicodeRange: '4' }, - { file: './my-font5.otf', unicodeRange: '5' }, - ], - }, - ], - config: {}, - emitFontFile: () => `/_next/static/media/font-file`, - resolve: jest.fn(), - fs: { - readFile: (_, cb) => cb(null, 'fontdata'), - }, - }) - - expect(css).toMatchInlineSnapshot(` -"@font-face { -font-family: 'my-font1'; -src: url(/_next/static/media/font-file) format('woff'); -font-display: optional; -unicode-range: 1; -} -@font-face { -font-family: 'my-font1'; -src: url(/_next/static/media/font-file) format('woff2'); -font-display: optional; -unicode-range: 2; -} -@font-face { -font-family: 'my-font1'; -src: url(/_next/static/media/font-file) format('embedded-opentype'); -font-display: optional; -unicode-range: 3; -} -@font-face { -font-family: 'my-font1'; -src: url(/_next/static/media/font-file) format('truetype'); -font-display: optional; -unicode-range: 4; -} -@font-face { -font-family: 'my-font1'; -src: url(/_next/static/media/font-file) format('opentype'); -font-display: optional; -unicode-range: 5; -}" `) }) }) @@ -235,81 +135,5 @@ unicode-range: 5; Available display values: \`auto\`, \`block\`, \`swap\`, \`fallback\`, \`optional\`" `) }) - - test('Empty src array', async () => { - await expect( - loader({ - functionName: '', - data: [{ src: [] }], - config: {}, - emitFontFile: jest.fn(), - resolve: jest.fn(), - fs: {}, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Src must contain one or more files"` - ) - }) - - test('Src array must have one or more elements', async () => { - await expect( - loader({ - functionName: '', - data: [{ src: [] }], - config: {}, - emitFontFile: jest.fn(), - resolve: jest.fn(), - fs: {}, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Src must contain one or more files"` - ) - }) - - test('Src array elements must have file property', async () => { - await expect( - loader({ - functionName: '', - data: [ - { - src: [ - { file: './my-font1.woff2', unicodeRange: '1' }, - { unicodeRange: '2' }, - ], - }, - ], - - config: {}, - emitFontFile: jest.fn(), - resolve: jest.fn(), - fs: {}, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Src array objects must have a \`file\` property"` - ) - }) - - test("Src array files must have unicodeRange if there's many files", async () => { - await expect( - loader({ - functionName: '', - data: [ - { - src: [ - { file: './my-font1.woff2', unicodeRange: '1' }, - { file: './my-font2.woff2' }, - ], - }, - ], - - config: {}, - emitFontFile: jest.fn(), - resolve: jest.fn(), - fs: {}, - }) - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Files must have a unicode-range if there's more than one"` - ) - }) }) }) From bdcde3de235c824fcb8f4c3efd680336e3fa63d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:23:41 +0200 Subject: [PATCH 5/8] Add e2e tests for generated fallback fonts --- test/e2e/next-font/app/fonts/my-font.woff2 | Bin 9 -> 17508 bytes .../next-font/app/fonts/my-other-font.woff | 1 - .../next-font/app/fonts/my-other-font.woff2 | Bin 0 -> 19100 bytes .../next-font/app/pages/with-google-fonts.js | 17 +++ .../next-font/app/pages/with-local-fonts.js | 7 +- .../next-font/google-font-mocked-responses.js | 36 ++++++ test/e2e/next-font/index.test.ts | 112 +++++++++++++++++- 7 files changed, 163 insertions(+), 10 deletions(-) delete mode 100644 test/e2e/next-font/app/fonts/my-other-font.woff create mode 100644 test/e2e/next-font/app/fonts/my-other-font.woff2 create mode 100644 test/e2e/next-font/app/pages/with-google-fonts.js diff --git a/test/e2e/next-font/app/fonts/my-font.woff2 b/test/e2e/next-font/app/fonts/my-font.woff2 index 7f7c21b8917a664dbbe73603df6879c41e6ac76a..a6b3c3a9d69faa7447699b148f39a2205119ac31 100644 GIT binary patch literal 17508 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 literal 9 QcmYdG%uZEE%g-wT01(FmZvX%Q diff --git a/test/e2e/next-font/app/fonts/my-other-font.woff b/test/e2e/next-font/app/fonts/my-other-font.woff deleted file mode 100644 index bf8c513058c62..0000000000000 --- a/test/e2e/next-font/app/fonts/my-other-font.woff +++ /dev/null @@ -1 +0,0 @@ -my other fake font \ No newline at end of file diff --git a/test/e2e/next-font/app/fonts/my-other-font.woff2 b/test/e2e/next-font/app/fonts/my-other-font.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..ac8adf10ed94280cababe8fd87d0a4971b6d2e8f GIT binary patch literal 19100 zcmV)CK*GOwPew8T0RR9107{$y3;+NC0EMIg07^#y0RR9100000000000000000000 z0000Q76xDdfiw{a3W4-|fyp}ygE9aCHUcCAhF}CB1%oyRgI^n4Z6gE0#sL5Y@-U;K zMo>~<_E!nqVRauoKtwnJ(HJwUwYH-T9cm(c&(&|fBwnqEfpd`hE;_?|x92Xd*Hu z!cs{&9A8;sDpaPLS+*+hewx!y?8Od{G9U#ckv@XSCy z?~w0WiPdVzcWa87cBZww1j6oK1i5qI+)HV2P4Cb1+4OCuoqg$MW(7ZN4suZ)RA=k* zRruvOP+kcrwNkqTlDt5YEMD;k6D84V|6bLy1;phYJ z-Xpmm{{s^AA?|`7(i#h1fXEFbxOYcFcN@4#OQ)PjP#dL7)I~a`&euDHRJruH=-j$* z?8@$4H7<(YrQwm~{6Z4a`I|Wv=C^;-otah=J#MEvL~$?UX~G2MGEUmZx7%yq_%6eX z`G1kyDj*<=n(dokfr`(+_*20eV3QoX0tf(nt^kAP`Yl`@$({6K0r2Nt0f5iB4E-r6 zKgu~WE6T=vA}4DtU>?@(q>-m@_yDMq_Z;+x$3bs537GJE8POSJ&@zQuqw8ZjT74mA z7=r?m)o**Z_qQ`zg;t~0X${&)t$q9UN}Y}#8%v|F5hOFu7inc$)x{$IIxxS?$?2P> z*JJNp&5g~!0kckQ|W=?`AGLaD#-a4LN9X+p3AJq z4})64-bADep^t3*K$J=NsfG60REI|U!eDI7!YmBA!=-wJ4_M}Qctv4s;;>Dvp+F1h z>Y*Wz3xoDv=4>>rrHK}kJvq32x!yg32MPSELAkgx`xVpWj6&fek%*akiPYCPE5lXA zs3h_jXZE=9A+#+>Cf161j9eJWXao6S^K%%BX}+saT(bt1j3psQPrqX=3l z_konX5)p^Q>SI|bHYyNBc!f_o4vf2ERVuNt3Wdr%h|`p*XDBK|4Cp1IHp36vii$$J zs#J!njAjXw2#-f1s5;{oQK9rdL98JbmW`;>w5>8cvV8z3A%`_lLRKFOf)EEl2XF)p z_--i%Cst^82)rzl5wc!}C>Vt=M(G%(BhfVJF;SD+^E*lfSj}rG^51xr za3oy;{Fk@UJWhQk9D*dv#M`E6<`B}wL^zOY zQt1G$OYf{Atg9+Sh`(ydlB5Erff^AFFn~QPoEAA*akJpOy%x}Hx0h3f$IT{ylV>49 z!@yup;ZLXeJTdVOqFGb}Q2H5rOK|Zk?P2n)^JLQc1IRK@bTkc34yG+{Jysqu3y;Bk zcV(M#GaCTZqLZEcoLFy?maD3%mZ7_@&G3@(u+kW!sWv_XKmaty6G1|U$sl=7jA$Gc zkOhJA2apeYqo>O@M5EQB;zcK#c8FzBWYyOZ05E2Wp+@-s(KEhH9;YU%isG}i@3HjO;Th-JayIc+d6<1EcRScB(6|=@jPkM3?tPmLsZE_ z0&YN!br(dm&$O6@I|~42u`P61iGitT3wZF7Podj;@Vq$2cW~R@O}qs__K6a)P-3rD zrXkueNIM1U!x5E^C$c_5Vcjg#iN{{j5?mGv(|T^u=~RQWT;^@Qq^6T-yFgmigj1u4 zJ3tfcl3)lS7x8rsfL5z%-f3;NDQD5p$tj}*!|AAU8yOa>h0>{Z=!&mTNnY@Sz<3>8 z9{Zh}D6CR0auDbZ@E{%9I6t39RF!t?44WHw=2sHCEXleWst~)2YeMntq_8CqP4jr7 zeI8tbFP;}I0_W7+8M&I@uBr_4631%mNWWu+BU%v}PFgur^B@M}0pB0%JqfJboD3T4o9Lm+zWB2xet_$YMdbmC4BIkMEM^ocC0G7Z1d+Terpi`&4(*eOPM&yZ zuC>KMmN-m~q7*!k2WUNG46;gz5Oj$>TwbcP9ko+jqi6nC01??rZFtTJo)mV3B6B1S z1|`1e7|On}s|P_iqEmoHa-fecIHD9w;8+W>!ZWQ8{6!k$uUX%!&m-YCiULG->pl5C zxrXB^gCKbxmf0=DUg8eO&xofVJjGsE6XI`#Hp+}yB5bqVk-Jy)Hvg3k%G-lYUNce& zsZ&0M;FUWVi%4=LP7vvIqwZrwoY_Wc%Q!(m(^-5;=vwbWiCEcLSOehUtTh=TTA3h# z?vHC!U(T9RHdWTEvaCxIP}#TH<|X&R-Rof2U1WHggdvI3Q7L$rF!T=1aS$81^1MW- z(%-1%1Ki^EdNzPaoK|DaiUrr`su*gT1E(p>-Z+M^03}JvNHXi5vM8!~TytMmg3v95 zgx|~w0uA6Iy-igL+ZYuKlP!*7oZj%@Gs9>8Fm#p33&wYtMhTw9zVDE8bG9Fa|F{dN;WCF?aD*x`f3^UB=g6HK%?sNAXb7Opyt4|b0iLv4 z?%wdF(Y=`r7BEN>K(e597%_qw^V=hmz{q736{FEG=%`q;vf?$f{Il+Nas&-5*qe$U zHtP&)6BQu;Qrn6JN6>kmj)x^yB~EqK%4PU%Za*z33{-2Rqxi_~hxJ@q2TrJMHP)_U zm~9)k2Tgap>h*fomoIH&x~Xi^%k0r?m}T}RIB@JMwPlHO3WO^7@_89Vk(a_#dSeDE z1F$y8vMPwyiMt~+8V6a{R7IgjSA-6T<7Du)8ciz{AtZ2$^|pIwK4#W8M$crOcwdxZ z0jOP4rK|G^ro4O#(SUJ%^qJNq3Ff3B_pLjKPC#@LY)=v?YBdXUl2ih4t!^17?crjP zW`~Y^@kDE3t3>pyJ~fe3OXKs1%%h8_(uTx|vfj-`Ig7McV#A7Tgs3usYrL#(@?6|R z4LhN+1|g^4$0AW=?^LK#T&Iof*1dK4RN&-AkO&}g+!3L+pa_&)j60$;TZq6YcD$j8 z>Y#5jt4tP)$5NapXgWWXR-QSp; zyEjU*nw``Nlf;urHzXmBx$>fKoU^E%5>?e@Ai?oV<4qb=az3Pg`l|&k1LE?AOFTI9zczt5PB0m6 z(5dqRVE%lbrVYIo%9(GpUToYAz5*K7EPc~Rd-6{!_lO`s3R1d%zJ~Tu4qaKo`GrTd zqj9-PleQQajnoLIrs&s`l8~M9Xt!~N`YaNY?jyQqbPFzX%}$5t%J1mJL9K9~pNCBKlP>MEiIjFh*z_h=n^{5sdgppZ>#TTMVD{pS)~oxSOHoO_QpV2l6)KXS91T-bTjOzWO zF#gS6WLU<^v)~#9&wu^KXsJ20R%qNu=v<;|%t(S! zXqlJTMato977ugFY1n>U9Mwd8OfoP4*Th;@(n{o|VVimknc4vi%hthuJJb<)2E$f- z`N^IsqFu<_%Lk6r2)n%#$|9tM2m!jEdFv#NSUPz^=8Ap4C7virT^vUM=2!kmFAQX{ z%2ydb%=@S50%C}wVOE7`JwZ=4usq5gjTf(Y20eFMde>1~;`hg$JLJvF*Ri#@ZmUYO z0;bt=)e_{IBD+X04V>0XwR|5>d&-v8?^hPmdJpoXe-&?>mPgUto+kl}IEpQfo&qp? zjKMbkH^wF>^`_5on&qBAyKqD1|5nJA)>kgTeij1_>S~@S&jv;?*;o}ppQYNoI~*US zmmz2IML%&yz5cov5=yUj*a@hS7SISHL^VT3o?)}KkquwPsgO|6=fDfDEE=diNR~|% zU0%+>{0_0U8umbs4Jzg;h_Jq~#pUZH&`RG5qZr_@Icp7c|CZvzJuEm7i-Nz)UjT9o zKLi$BB-v_STLNMsF91|21BMLP5p zMaF&iqE3lp^n1n>RVYkVf@UY7@nRSE}g@Z#P02cvx_SBP79RX;eh8xElkKJtQ z190@}B5L%GyXzTR#mom`yU$L*=R|aP4;>?A%Y`ycaeTiYdmvI>mw_fBlnZaA}Q_;|Tk7H3eigfqT|MFaz)pwU=^&L2W&{@U(nJ0I4$K``uAxU?@tv#6*uVOA1W z-b|}Cu>pbVNd__;o~kFizd zpxj}Uzbj|67}0gJR3+~8LO-M6-FTklno-WScX0jJmlbsjot$cjfHC^~pNTGeUq zd1Kxq^g-kD5}uH{HxW%@iM=}uEZDr=k+_ni%`bs%pay5#@IbHEJG+CwXAq=1MIr?ls%A8Um`ro z|BP?+m2H)WT<)p!(CL>7*jqlF5hi!s=*!hyhF&mLWK)~JBcD!}`OQ624S(9B2toa7 zm4Xsz&aWuern1lADkn3AC^W|drgbEh!0Qu2t80rbc~Tb^X@^rRAhOk35G5b!yh_3s z7@*qwB_MOoL~Ez&&6ZlHNiL$%?Y3HUu~^LdZB*=Ph#k48mVGumXX`RmyUIg|E!ZEc zv$j+vGezgK+xZjWhYryyj9pf9*ya+Yml3}?Z~A2Z{5I(*dj3=nCzGw(({xGL%gk`Q zVVt+eyZx{y!q1d6hi4wQb>Gz7*9%H|ZGByXg(}Ljj;q1g*Hq_4?_}ncjNee3U8nW$ zh$=s=Aq5Xb!*-fko`*bV6%DI_h*s>Tg`OJ+0imWZn8HR!-@zL zViVS5PplN{kQLL1-7l?VJNDwFcCzzSb>R;emcoW;#cAv(c~md&CC_3}G+I92a-y1#5*esIFy`TEgnV3R+Fjt64+C~ud@8^eD8vA0kVinkHI z3j!_H-ty~@6Q)PTFKII@DaKP_L_mz@QB3$&VLBVf`T4=#f8oJSpBdmE$6 zEON(D&TPF_Tl2Svy>hd?+%^v#-%4RQeL?!P^}~PJ@D!W}d1XdqehWg7PF@oB0hc8- zeJYsm!WuYcx?9w~zSkEt=p}1Qlm@_nST1iU8d^SREwPVe!H}5*NCc?^E)w=G@ESJ> zYh1qN)P?Wh)K|yuPDwKj!*BO0j{sXdcyHiTY6y+a>e)SFYB>mTGW(`UmMy1!rb0C) zS1iHnfdBFB29_H_Ov2oS_WsZBL`i4Rc}m@(*jBMv#P+iMPrOQ+Jr0v_B+=}$XLJ3Q zvt0k}?~-My42K7+1Wg$nb)8R7)3*LrcD#|JL>gCs+vf|^XShnk~)xBY?h?De(JX8M{f{TtiU z(c6J2pnLYBtIcCz_h}B<;tVK$_lBG`y7-A14!#4Q(X@!FP}?HQlKzfLPp_`3>W+>F z0wx&%6i*kpMw9GNB4VrF`t39C_2rOvIL?40UU^@+xa|yaN#o0lqi_BE0dl`(Gvl*H zYpncqfl&Gdsmgx@d!w{R{NhG@BW!Fb!%j=3D8E%Y{`Vl0nt5lB z@10(YT;Y~W(=Q97a_K4+g0GF-Vh@X-3*IA>?$xgxd^*h>Saqz9QXPzwf%)cl-3?BB zw+^*dTm3J}A*>YX;KOeb@S851D*2`~zuLYzLx-KF1oy>XPd`&40Mfy8d4iziTVIp? zi|DxyQTz$pp(DYAEpH>dbV`n~4N_}E%u^vk49dFG#0Rd!0&~#3M{KK-={x&VX+3V% z=_Gs}!+`=VZ8I+luLhtbtP}Ch(XL>5f6u|Y#Rqu@B+D7K826C&`w+X?TdYMOA|dkm zX$uXC(vTJj>VB(tR)9h{-rF45wdDhBFQ+L&YB{hQ-lF1c7CXoa%z-_s2}QB7*e7?8 zx77Zkl4qe%b(7T;_FO!ZptPT;Ak8QV8OSII%{zJRHrp2O zr#nXxNXK9n)vwf1BO*qNfBNJ7a{REK4O*G8-H3RDBxsMu+(35R^*ZJO~4z`R)QUQiJKQH**KqGY6zhH1mIX0qqIL#qtf+cAMx2V%OiA5R(9bxk>u5A;sEM&N2=7{FMupLk z+5iR76aqnzK)jD-jr2rybZw2R7H040EB*YHaS+4*eR%fl_Y;fu@rW|$$P_=YU?3N6 z2d*z+{;D{+ei9CsL;ly>_O_j7Vfa-Z%z_lfG~55=&Th!M5Gv<#VOI*)*>V5Gi+-N!iRAl4qYw&uS$tPNOPRuCnBV;AfJqmc7Z~~G!1ch zI0AEcIQ%UvfQKN0TeE7FWSQaBhjSQukQ34vCX6$}0s#+kCOzhw#!qUjX31sM|MB59 zu$M8YJ6TD+AW`l8`!^NgLC){Lg}=!WNhAa!goLszx(e@xLWLGGj%Q=;i{OUOxz5!^ zu(XB4a_?)s6Rcb*^-E1!%1@@dX?-vZ0;D$NTJ{ zS0&Oo0t&6QaW!!z;f@s;n$JN|xFf_IVh(V`6fAYK852{UUFYzt?xxc_k`HUE#ge+y zd`5lb4CA`;mi6D;|zXaT*Ah%qfbg%SJVOm7NxSOYrho(;2mfj)?um#cD zX3Z=<%!0|;*QhShlAE6fXyjO&8%1IKCFu`Dc>Qtn$m0?7{jcYL`yPQIl*qquqacFQ z)R$ca!w}Cua^hWo8O*;j1h)l<_I%1JUwyaf>f!2hgz#!$P}=ZkQv?5-4Mb-#ZfHl& z2EoSCXcnK4$w+}5xo|mj^ma_wvdp|_4t{4^UR~qR zscnZa7WKvctZYiGEQC0Q5thJ~`6t^mLb=UL3vVvDhF^@iJRHynWMjhqW1KV9Ym% z+ypv9(k=CK_9MA#%FLDSio2efV6O<~;y8qh#|4dJco^R!*wz#j+I3}XA6F*FC`W!g zwf9)Zs>;koPk30L0mgA0LhYP1UNuoGs1PPS#PD-Ks@7X^cV@GFjZt$laWPkVdF@e| zIOP4ul)oU(gx*H38#^Ymbe*iHVLhzmB({qsIs{>qJHr9{Ncv-p1NPLIC=?X7KW1oy+#EDT?mXxp4u&_rWbgR)d={QEL`BG_F}E zm|?j*T`E(!=bF^w!SPXYUHNftMOhjw>!>4`?p@7dS=r1|DKm``tg%Ewjezb|zSo`g z!+WRw^~GD%)yA7d8$9obN9}wY`*dD32S$*v`Wg9Qz#tQeQ5Ga+@-=&h(+Oteecx3G zhS2)9B?wIGU>IKWM$2VO%1P+9R_1(3zzAAj>z)zgS7;9L{o1L7q$hql`TO^PzHXG| zd*#HWC5%fq_4h8B1_?0l;`wa&HeS^dz+zB4(cH+e93P&MBxAJ5|5ut#z8+?)F@y5( zHS52mlaR~tQCX_aI~R5Ic+ossZ{tUt1AA3B#T8+$4whzJb*KL<_g#R7JxsJM3sZ1i zElmMln{K$8SxImT7(vBS2KDA~sLWwU+ zdB<1JoA_=zq=jL;{_UXKm`~EJ53j0%vZlz`%RgE8{5T_A?hUx7TqBDMbSiySlWIO* z$|-{jom3bNlFJN@K+$J;;VW5iF{&< zFdh8CiRE#5LlJTr{2+*g5YEL}0f1QL`gfeOR89n}-k-csOlIvjO}t04Yvf#=E6-ld z4QTPGIFLc8m&!r%UUK)tj-DW|W#1e-yqlUgzXO7r^1oa7%&nCF<~k!<9yTv-9eN@x zc040f;EsfdzNVI(SGS9OPaFcGZE!uj){G1vH;^r}pR{F75(K=Q(S1lFPQ;qwe1zXg zPXF}V1Skch0KL!{*&~5}3j`!d;vSwRFf8-c|9rrCU9A?AiR%xl)hQ4L3l_KV$%%p0 zKLkxNEPEfw4>*#)ahvVxWxM~DMJQDb_PEp86nUTEy%aL~`UZ`0&*)ycHn=&6DJU3B zck;L}8Tx=t7(S~U=W38;7*ahG)S`kg$1_$(A`3&g-v(+iVe7aBU{;3f-0G6V|1~~#_XpAxqip~5Mg`M7;qmXE!!oVt)6NB|cU?h3BT8Kf zC~Df*A~%1}NZkse9cjVYhD^!(>uuwTN<-Vng}6)(AD>!W8eeA&caImw(Q!h3Z&zL_ zRmd#|;D&_CY|f%pvD5dg-Ly}`HFiTILCYZw=OXHbo05`L`0FXUZ!t5l`B8_D=7x$O zm|e5DUk`D(C;~^IrTjug)|k^h+&kVQG~QIKtfR+s%aAmMNaO7nJax8EFhLrD%*xNA z)OeyeO_%h~Go!~;ot@5M=YS*`2vU(dPUXlWIqV}svR%1XGc8RC0T^!G`t$ACuoi|j zctE*@I6umvrIQm@pE@a1B&|*4!<8rE0xlWjO`eY4c*3ePtiWfUS|$GX4~FU0EZM!x zEg;aG>{FmgQK-ed2_92}Co3gQj%^~=Qk7R=$<6@^qYcIP0kT1NqV)K90I3E5Su(;lsL5`{M1t@s72D~RclVo@~w*wbIpsgqt;i%S$?s2@au$=tAZCMlo{NEt5lr&*6C!MwHgtW}T;gBdJ79kM_-d=fw>1>!4 zvtl}oY?|X50F!|MuxR=JNmv{l$TnS`_2nv01D<3gmkKcIE9wC`c>|P7^UaHL!5@#o669vYqpQ{HEod;D!%)1y(l8pvnDt^a4&e_AIY>qz@8XC%Tv+?vC+5JAw-_)|@%PGl(gD)}h z_+1k4QTiP150W!!EznuyVZgiNcCWz|9gqhsIQz#1p^25kPGhAS5ke?{jq5O0MFz*1 z3Qs0cmVev+@qqLQNoQv`oLRn4Zf}ttYiXBc(`950uYes#V|>N@?u>&+CICC=iTAz` zVIAyzceYDJKRlAY!4ML`Qf%KgWktP&|MT*69!X*>F)W0F+mF@+(%HgtUL}?)Wm7`9 z;KGa)uz>q7*|sll>9D`Hs>!sBAf&4hrxoJ3aN=+WJ5B?e^5>%5MP^bI8)dbbF8eHf z_0QjpwUyF=hY83#r{m1tcxy`3z>3aYF0;Y;#eg29(R_A3H}gSb@6xLsu!Wa}=dp7| zc&@Qn32| zwJdV0s@ICov@&Cw-$Y_Yt{!ON?$9nBy6W2Cj%)-q;C5q>po*?0sscF?EjT8K z1DE_*C7fa(Uth&Hau&IEIKu+tEs84lx}aKHdX~Sx%kv+eXp9lxzbIF@TRrE3sGA`pODmIeeVzer0CfG9}0 zqNWR+c`$)aTt<>2@qzc0lgt$4anh_g`%UXq0tFJ6pCh_j`>&PC^J8EbIkwD9J6IkX z3z!^X;@<1cWE1;?8uyH{cOO@&ZjXF&Zi%Zp>R5s}fgJr15@4?=%dy0n4&~+jv_ow+ zIinpGb1V=IBi8|o&IKUcojj2%Z0B@gMZ%j-%T4nzZB2Y5WD5V{8^G) zXCA#16%e|U*9W#U?p$_j6?2F*si71 zOxXQt)A;yNg1n(<)e+@A-=xvf*UJjb1 zK->!&dr5Xq5-SDE;HM-%m(a+ei3>_>EQptKch^u#nmonRdf!9xB&}0skUG@y(s=ia zKR!{Wiqr9UU~sY3#Jd(wT+~2K z$OMtwyZ8Wm_&*coe=WQ_zWG-Fjpci*SyETklJQQkr@oTEm2(e?l*~VbV&s5@WHtf;z|xS3CWb+)e8LETaS`kE{Wsx!#n%dAjvrYw! zCJ_zuKzizj~25USQA+dtRln#)10lh z-mwLWyWm)-@#}ilv;#B0@o14A$B6r%734Q0|$L2s&{ns*E0auhdyE|lXhZhy;#Apocvh(1609NCg!y6ls#$xSM8K)pl$ z=F|x7;cLP<2aX%f5?Ok72c^n!geYKq4Hs@!V%Vo$#Q9o|XNe$1A7}xpM@bLZ2QR#n z=V9@jFYy!-*4lTbNcmx7TK2tTsx8&f;Db!D*gY<-!~@k|0;)mKK2_ zh*$PkmQ{sC7R$|{ZrOl->P}~v;(qm&{pV5nJWP-+&X6Pwv<0s-Bq+!T~||#7N3u~p(6 zj8j@fOIrDIj|IU%*F7F#hl!mIJNfbdvLhj%o8|q=%yD7iUhQt`hszj9AJTo6WLl zgf3}h0h+~$SKI{S3Q!4Kf{v5mcM9Bya=Mf(3nqA!z*}JFW}(TdKoc3}&BHmGsQB6Ca(hx|I|Gohda z^l;Zt z)xYGv9r*xhA&9=)c<7o$m-N-$ai1!1Fgujywny-RYA*LQ2aA)2vWT{y;uN~s=Up7) zL~gu->sIwQAMRaTg>sUqdB&PAU0t%;YRpG}JEm2YNF4kEG&cp%7sLEAQo_m=0g98e z{+@VL5@bxXh32Sye3MmkT#_-D`UO+85WzoprTSxw{}R`DdT9ZmXUBTwBm|X9L%hQLqcw%F85*1ev(S z7lvT~!E|jKh2hzgBpKp7Do5a~0f>sEf=1u~yZ#81<{79dk4nn+31R;0+^0|%cw@Qj zTrAH^DCg1SxIP!i;*#+jap8(uBA>oeE4dk+3dggYJm*QuV^~TWj(FN6$zW2RONqFQ zU&ydYC@lwuAP9nBm>i|V>61D|gvH+ezU{(}EOKP?Yx&hE=U)?~yY=XG1)dAYDQzb? zT-mQ}ZF5$Bdx(38h8ZS)hOzMNW4@Hm+_!p@sBh+t>GEXLRea}ek_ zc9=2y-^Rp{6V8I-A!OnZX~uFvHsk;^dnce|k5>QHX|0us$L*@N;>Ych^Giv z#=ch3*JhofaY3+vTW}ZWkM%`}WfGgK<|Zy=3CQ2;V?O5rZWSCpzLo_+Fx+svDssMf z$)~dMuY)>I9c=rq-6FLqoQF3ZCp?WdW4b;~V+93eZRwr~sM*igp(=z*6!~vQi>PFf=?uUu~{Fw=s0E78(EdKM{XVTEhUgTZ!5h4k5#@co^ z+KU3mgZV)lufNwkCMrwy!dn?yT6Hb?CJ8~1@W6LQ@dl}*wHKLx_R9s4fpk&y{;T<{ zjWb10%2(LtOntpIVizAS2R>nJL3m&W=kfDli@R=U>LKZtI5&A}f=}QOpURrw&lr9S zFj^H3zC+9Q3%Dah(<*TbWs_Sn({z%zJ802jR4q}<1gPq6l(>#wh_8dz(*qvuHYdeQ z>a5zb1LW8!=a28V%|XyO83*FZTGBC2?`Rv^cU`sFNpsvke$DUV`8{dxz^Dw0tV!R$ z$BL_jnkY5hwW^DPDu=SUFa#m`Cr|^o>&msJs8*507&GG0HjE4R4wpDi@rj;E1Hj^N zfB#SRpJQ5>%i+LOOBIYUf#ZML3$r1?M|>DV;hR4k^tZNOTE!&jeFD=`ql$H&1bdBw z=H%em@47N#UA(5!U|r@iy*VOIUzE86|BrTKJok9fI_~a%*{5c;I`r{#uD z&lZ_M5|_=6k#p1_6;5WQeA={OgC67Ja6ODvRlCaLHJ_7x=n~io8BH=+vTqr~BHO{W zmpg6j+jX@yNaXmrD88*cG%xGp-+ym_>yqg0daH@LY#uzibftKxYLQm7Oo(SxWZ|OZ zhwIh`r2!$Pxpp;ME~u_<9!l0THwYohcVDI>1GpLHs~Af@#3#`CpFDF>YOh_2KXXgQ z|MEq~nsQfnZTXEsaq=y%#`2y}7wC(D5D_`m{3v~zf4 zFBI@YSVzMQ4~3Xq(^2)-Gh;Mh7xewmStmDe!^H=BNDH0>qHIvhs-4(qQYHJ^Ol`hW zc1Y=!_m7&qTpN&7NfvT5Oc7xnm=j9n;RqxaL1yTQ`HxNXgI6C{dbaf*#4xh<3(8d6 zwq@Xj5aEc37>%bNq6<&~ZZ1u4c`RVSh^SI2Q&>r>3}0T^#35*RV+f5<6Jaj>8&zTG z46DHVeLpee?%MpyN8P->U(5H3k;f*4io%k!uFo#?OV`pe7njdv zsRpg|NfgFABb`TN!{c`f2WtWykU3#R1spNHmIWXP zZrF-m^nBU>=?cD|Ptg0kRlRQ7jJ9)gTRCuhdmu?dIamtiwt4fusH!-CZ;FG-Z7Gl- zBn=3x~w%kr884 zK-$(0ZrurOM5<5Zg3GE>|I{p;)HDwCGODhbyNSag@ zu4%j7+BNly|6F7F*Hx^#I`G3_D$8*3YD2&-q-&d;xOXtW1^3Vp`o0c0CdJ~3WK)qew%WX-glPcpr-nx3$F*3{tI0fiROoYVMYz+dNF%z*t&?1!(VEn zYhRu(@;k8=_?6h#4_V>a=@3i@m9e}*99L>^V})dPiIfhd1gWWy0=@g!HL}9{qZ0$g zgGI{WIlJOz7umSG#?>jtl)e}Dw{hRjyVG6-y!LjjAkO&uFxtAzAR5AfBIq(3VO{~Idb&F z+5C@h@yQfpZCr9uaFMdF@6gYjjSX3i>;;7m?#jz~BW7q|sJYwEcjoYiPH$#Ix0omomD z^lv0W0tkWwYv;SqT>wKjS#OZX$UY32urfFsUj8Y%25`2DM^DTs{l}RUHw=UWU}o=% zELZQU%^fj)t10MW9JD_1|Brb}a)SX*A`#92g>Z3dRAhU=EnNz$7|u)eF*3Ybk~d!i zB?z5OEl<`39=q=98d>7h>7VJM8>jNpuwtkZDr6@yy-wtjN=0on+Fwg94xO)oh60F9(e7I<;&x;DHb4Z`zi1;?nOwz-?&~e^!H- zToX}J#%Emawzcl+(uX?qm8Szw!I@BsHy=Ukt#>~R%#%M=X}(xBZ{@d?<&M-B>@N?m zAU;ms4ML(&Z8*Bu;cvkb`9Ei7Q3&Kp2@oDTgVmvJ~EN5Edz^B2w z(Mt`fEjVb`MJr3)Rt_I+E_mQH+-(S z#HV2Sn^WDL-UKG3Q%60$>Ia?t`gh~qDb~ll;s`!$n!~K$(pFh!)j02&MJ*ZgFFX^N z($v|j+pM!E!1nKBYo#2DL9Aj3Vs(B$dBvZ{R`4#@h>su|wM-T!4=1fl(9RcdU_NEixuMVChXrd;Ob?gGjQFc8~BrQu=ef^|NQM9;_4>zB%%Z@iw6}mNnNMHj}!nxYX zwlizYFSWl)M`t7}d>(3{{x=K;trGvyX$(0WeptYed&Cy=jcZLp_bps zC)E$O5}6a*80L&h=^baMy3(s%-6cs=UsTPc;o*NOYNhX3U%A}P^6m6@`{HNWSAMh= zq5d!T6-BKEv%b$BWRp)f3<}BPj`yqdsC#boejbE)sy6)NmK6ow{_GKqPhJE^Zr9$u zmvj9WZ&`ot&y2e4;%qRkK*(d`B-Ht1$NYcb;?|t%1Jp!>xlOIkEX9?p{q~)!XkZmz$r%D=xg$ zi>~avX<#wEVeZzk1BR`OB8PQVDK?}x+8DX^-&?5`HhlKC1J(-Cw)u8I4Ebo zA=E7^7Kb&9UYWS7Kae81LZ7vsy_eGX_8y@f^UtQpIWV!<%u8n3fkGRSKpA@n zr9?ZyGc10>a);ZxoLvW>t{canu%66@y5It^IF!2shXVuP|IU6%xPPk|?sFNe{(_$C z^e!5*@mN1s)-A$cH^D!4l%ihDxSrz~hVcIUL7?9Pfd`ChoV;>k4v|?hZ>2Xs4Y24| zH-Ft}3YXTh6!9=xf2nfCHm6m}>-MO1uef0SP@&||=5-}9)cFs8_J8Y>2B7xZ-ztbO zNCcZoehYch_U{1f@e&zS&*it35$P#ERR}-s;tY6&hvJBl{WL8RNs^@M_&?&+ZeMLS zucPC^r*?wcoF}ON!Ag`eYvYh4Ry?v(B;9T&GFfSmoq|A1=Tk@?Z7e16$jRY&#Q3}ER5(p)+O-2%D?s;SRu679PV`y}NMv<)Y44Bg z3Lc!>`~8f*S^@_z`LDo4Fiu`!?TZ zuRDCD+M&;#55BGQv#<^^B=JoiAjAChZ93lj^lBBH9#8tsgGN~>x`q$SUh>aGrtw>8 zhwNalO7c%!NRr-HF-?t&=hyUpU6X^u=U2b`cms!b!W3Ie;y>anc=5@#Fowd-i<==9 z{`MKoS6riFRJ?OM`5!Wt0yhW9>br`&i4#|wp0(|18@bvD9S|A>W|xmVOqoOmok19x zEdt(B3zaTR#?34;D#0*7Sr^O$mPV!_q7zT9i9NKz7ANwEtP)Xk{7$a$V3K&>OF?^q z&PLmX0Rc`4`e8VN1z{p~cQSnZ3g#f%3sZ9CwCpIicTN7v3A8;eTg^c-AU3}Em;H^s1IZOPaO zBy_!OZ2I8L*emeR>zLjWn1&_LJ{JO9DitkjL1czPU!f_|7o`}x>T-}#n{DXPN(ZK(Ck_P16C z`NIDlx_Is~Z8#2r9w0XZo0FNo9BVf(3&+kFXLRhWs5GY=IP!7AG-k8ayRmjFjgFm> zZbiC**`EpTG27gBbF6(HIyH7?R$7s6m~?|?fDP6bHUn!mf29meUIMZyY~HEcopJVR zOV$FLEHJ~>iMz@0g$J(AJ)<5piDENal-eGRX;1K^AiHy|QEqP|=Rjk_2|(@x zYTej)*R5^O%tGFeB=To$Po^QJatF*Mgw3~6s$qMsSuAiD>mm&Hvuhk=-|*qSvH6LN zh5r8LVS8i8ei-}z>b0?vVW`Gutd_NpKUe?fc)um`G7H-T2cVzpO$5M4x|V3hvZ=My zv-FbcQHAOz#z^w~Mx}7xj9o)MhXT+S*+>OqX>MzZ)h}Gz`R8_Wor8_83@PdSy1NMh zu%e+PR2b?NDF2_c&F3>Rt1lLVn^W|Yoi`W&e$v|cV{SFHGcogb>snXW>PFPZ&(hM? zyTYI4fAqY`!Y*!${z>fQOpaRJ@R|CC4|QbYyoJ%eUd3O+n%2+fZ)DG#GykV3v{LNd zvLXFmA84)XTzD1?n+QU&hSwGBB%2y>J2|AIsFf4R_BYg7#Ndh^EyqM<>{&y z@qEzJO+<4lJ8PgNZ&J0$`8xyspLE{IYa%@WZ-O^)n}55q;b=ekGh+Y+;1~IkE&zI* zFS#T7RTFWd@UWpU4}!ry^G^tHsYSTyx2b`IbKLUvG4nig${Ty*fqk8WbX6J3zDW}kDBPOCEzb& z>?MwLbiPYJUp=!#tnA^EyQDcigZW;=RhRCvgm>*%jk^VlPDPSYUw&;aFAeh=t-6$7 zJ!tGMktJ7#z$wqqoy>JQnm847faVvRJk#nmBo@#9*Da9zKKa_6hb*n7E6L_vR#r_t z|K@aOw|(|z!!bD_xi0B-bp?0H@lE0NbZ(bmzPm8FFZtSNf}?bZYRm=jRuTnbEznrr z0j-?8FUjUpwjX5v-%!|Q5C9-n_LtMQgwg+VTs8oA+4=XI%P@_)qJ`@z061VkY=Aep zSm-+)%5=X75OQ z3_J%y+u{-V4?r?iC$m$it7Q(AU{U0C@bQe~9klXU<0`61ah6RgnXk|fn362ZtA%3^ z>f}o8NZSc>k|d9-!BpvPm~NzQqdcc}F-0@x4`0ZFXdG3BWVl!0>h(xgp$k-gB6`3g z+OH1m8Y;tb9Rsi~UBY^G5yxpd6`(2j^XD_Q0t^0_!I|CyV51zbu^Wn>{P5+Js3KA?ts4(FoM2ZqE#yGLeEUawo;>2@E;FKsyvJ|P( zq|1;gOST-j^5iQ}s7SFArOK46u-!Tzo9l=#{AixfEV9ZL>jQ&@?wX_DTkm{onfXq6 zXv9~x8ui{E*4p8`v%XfTO0Q}c)i~#Z?_F})cYadqx+|{wMx8hM-1LJR>iy!i1saU^ zk%=alWR1z1G#1?#woR*c9ey^&RGp^jGTnZIW}0D^Zom4?LAMMUo_L?fJ9gS-uYFG2 fZI3g0Y;)8xhl7Am{Jy#Vy~g^QNoDB2h5`Tpe?$`s literal 0 HcmV?d00001 diff --git a/test/e2e/next-font/app/pages/with-google-fonts.js b/test/e2e/next-font/app/pages/with-google-fonts.js new file mode 100644 index 0000000000000..67cd042eb1b5d --- /dev/null +++ b/test/e2e/next-font/app/pages/with-google-fonts.js @@ -0,0 +1,17 @@ +import { Fraunces, Indie_Flower } from '@next/font/google' + +const indieFlower = Indie_Flower({ variant: '400' }) +const fraunces = Fraunces({ variant: '400' }) + +export default function WithFonts() { + return ( + <> +
+ {JSON.stringify(indieFlower)} +
+
+ {JSON.stringify(fraunces)} +
+ + ) +} 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 eb7eee392f7a1..a6438d69e8140 100644 --- a/test/e2e/next-font/app/pages/with-local-fonts.js +++ b/test/e2e/next-font/app/pages/with-local-fonts.js @@ -5,15 +5,12 @@ const myFont1 = localFont({ style: 'italic', weight: 100, fallback: ['system-ui'], + adjustFontFallback: 'Times New Roman', }) const myFont2 = localFont({ - src: '../fonts/my-other-font.woff', + src: '../fonts/my-other-font.woff2', preload: false, variable: '--my-font', - adjustFontFallback: { - fallbackFont: 'Arial', - sizeAdjust: '120%', - }, }) export default function WithFonts() { diff --git a/test/e2e/next-font/google-font-mocked-responses.js b/test/e2e/next-font/google-font-mocked-responses.js index 732813f2401c2..ad932d5e13ea2 100644 --- a/test/e2e/next-font/google-font-mocked-responses.js +++ b/test/e2e/next-font/google-font-mocked-responses.js @@ -493,4 +493,40 @@ module.exports = { unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } `, + 'https://fonts.googleapis.com/css2?family=Fraunces:wght@400&display=optional': `/* vietnamese */ + @font-face { + font-family: 'Fraunces'; + font-style: normal; + font-weight: 400; + font-display: optional; + src: url(https://fonts.gstatic.com/s/fraunces/v24/6NUh8FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0K7iN7hzFUPJH58nib1603gg7S2nfgRYIctxuTBv7Tp05GNyXkb24.woff2) format('woff2'); + unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; + } + /* latin-ext */ + @font-face { + font-family: 'Fraunces'; + font-style: normal; + font-weight: 400; + font-display: optional; + src: url(https://fonts.gstatic.com/s/fraunces/v24/6NUh8FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0K7iN7hzFUPJH58nib1603gg7S2nfgRYIctxuTB_7Tp05GNyXkb24.woff2) format('woff2'); + unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; + } + /* latin */ + @font-face { + font-family: 'Fraunces'; + font-style: normal; + font-weight: 400; + font-display: optional; + src: url(https://fonts.gstatic.com/s/fraunces/v24/6NUh8FyLNQOQZAnv9bYEvDiIdE9Ea92uemAk_WBq8U_9v0c2Wa0K7iN7hzFUPJH58nib1603gg7S2nfgRYIctxuTCf7Tp05GNyXk.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + }`, + 'https://fonts.googleapis.com/css2?family=Indie+Flower:wght@400&display=optional': `/* latin */ + @font-face { + font-family: 'Indie Flower'; + font-style: normal; + font-weight: 400; + font-display: optional; + src: url(https://fonts.gstatic.com/s/indieflower/v17/m8JVjfNVeKWVnh3QMuKkFcZVaUuH99GUDg.woff2) format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; + }`, } diff --git a/test/e2e/next-font/index.test.ts b/test/e2e/next-font/index.test.ts index d53509586672a..5cee69bc642e0 100644 --- a/test/e2e/next-font/index.test.ts +++ b/test/e2e/next-font/index.test.ts @@ -103,7 +103,9 @@ describe('@next/font/google', () => { expect(JSON.parse($('#first-local-font').text())).toEqual({ className: expect.stringMatching(/__className_.{6}/), style: { - fontFamily: expect.stringMatching(/^'__my-font_.{6}', system-ui$/), + fontFamily: expect.stringMatching( + /^'__Fraunces_.{6}', system-ui, '__Fraunces_Fallback_.{6}'$/ + ), fontStyle: 'italic', fontWeight: 100, }, @@ -113,7 +115,7 @@ describe('@next/font/google', () => { variable: expect.stringMatching(/^__variable_.{6}$/), style: { fontFamily: expect.stringMatching( - /^'__my-other-font_.{6}', '__my-other-font_Fallback_.{6}'$/ + /^'__Indie_Flower_.{6}', '__Indie_Flower_Fallback_.{6}'$/ ), }, }) @@ -232,7 +234,7 @@ describe('@next/font/google', () => { ).not.toMatch(roboto100ItalicRegex) // Local font - const localFontRegex = /^__my-font_.{6}$/ + const localFontRegex = /^__Fraunces_.{6}, __Fraunces_Fallback_.{6}$/ expect( await browser.eval( 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' @@ -342,10 +344,112 @@ describe('@next/font/google', () => { expect($('link[as="font"]').get(1).attribs).toEqual({ as: 'font', crossorigin: 'anonymous', - href: '/_next/static/media/7be88d77534e80fd.p.woff2', + href: '/_next/static/media/ab6fdae82d1a8d92.p.woff2', rel: 'preload', type: 'font/woff2', }) }) }) + + 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("Indie_Flower_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('185.52%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('93.32%') + + 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('52.32%') + }) + + 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("Fraunces_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('63.47%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('16.55%') + + 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('154.08%') + }) + }) + + 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('185.52%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('93.32%') + + 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('52.32%') + }) + + 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('63.47%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('16.55%') + + 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('154.08%') + }) + }) + }) }) From 1a3ff75070c2ea41a9f94822f165494a0932e8eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:30:52 +0200 Subject: [PATCH 6/8] Update function args --- packages/font/src/google/loader.ts | 3 +-- packages/font/src/local/loader.ts | 18 ++++++++---------- packages/next/server/font-utils.ts | 15 ++++++--------- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/packages/font/src/google/loader.ts b/packages/font/src/google/loader.ts index 8618fdcc6fac5..63c9359ad81a5 100644 --- a/packages/font/src/google/loader.ts +++ b/packages/font/src/google/loader.ts @@ -103,8 +103,7 @@ const downloadGoogleFonts: FontLoader = async ({ try { const { ascent, descent, lineGap, fallbackFont, sizeAdjust } = calculateSizeAdjustValues( - fontFamily, - require('next/dist/server/google-font-metrics.json') + require('next/dist/server/google-font-metrics.json')[fontFamily] ) adjustFontFallbackMetrics = { fallbackFont, diff --git a/packages/font/src/local/loader.ts b/packages/font/src/local/loader.ts index 41c14d3a7a559..6d061034e47fd 100644 --- a/packages/font/src/local/loader.ts +++ b/packages/font/src/local/loader.ts @@ -53,16 +53,14 @@ const fetchFonts: FontLoader = async ({ lineGap, fallbackFont, sizeAdjust: fallbackSizeAdjust, - } = calculateSizeAdjustValues('local', { - local: { - category: - adjustFontFallback === 'Times New Roman' ? 'serif' : 'sans-serif', - ascent: fontMetadata.ascent, - descent: fontMetadata.descent, - lineGap: fontMetadata.lineGap, - unitsPerEm: fontMetadata.unitsPerEm, - xAvgCharWidth: (fontMetadata as any)['OS/2']?.xAvgCharWidth, - }, + } = calculateSizeAdjustValues({ + category: + adjustFontFallback === 'Times New Roman' ? 'serif' : 'sans-serif', + ascent: fontMetadata.ascent, + descent: fontMetadata.descent, + lineGap: fontMetadata.lineGap, + unitsPerEm: fontMetadata.unitsPerEm, + xAvgCharWidth: (fontMetadata as any)['OS/2']?.xAvgCharWidth, }) adjustFontFallbackMetrics = { fallbackFont, diff --git a/packages/next/server/font-utils.ts b/packages/next/server/font-utils.ts index de3f48a341836..5d672e2e3c95f 100644 --- a/packages/next/server/font-utils.ts +++ b/packages/next/server/font-utils.ts @@ -102,9 +102,8 @@ function formatOverrideValue(val: number) { return Math.abs(val * 100).toFixed(2) } -export function calculateOverrideValues(font: string, fontMetrics: any) { - const fontKey = font.trim() - let { category, ascent, descent, lineGap, unitsPerEm } = fontMetrics[fontKey] +export function calculateOverrideValues(fontMetrics: any) { + let { category, ascent, descent, lineGap, unitsPerEm } = fontMetrics const fallbackFont = category === 'serif' ? DEFAULT_SERIF_FONT : DEFAULT_SANS_SERIF_FONT ascent = formatOverrideValue(ascent / unitsPerEm) @@ -119,10 +118,9 @@ export function calculateOverrideValues(font: string, fontMetrics: any) { } } -export function calculateSizeAdjustValues(font: string, fontMetrics: any) { - const fontKey = font.trim() +export function calculateSizeAdjustValues(fontMetrics: any) { let { category, ascent, descent, lineGap, unitsPerEm, xAvgCharWidth } = - fontMetrics[fontKey] + fontMetrics const fallbackFont = category === 'serif' ? DEFAULT_SERIF_FONT : DEFAULT_SANS_SERIF_FONT @@ -147,8 +145,7 @@ function calculateOverrideCSS(font: string, fontMetrics: any) { const fontName = font.trim() const { ascent, descent, lineGap, fallbackFont } = calculateOverrideValues( - font, - fontMetrics + fontMetrics[fontName] ) return ` @@ -166,7 +163,7 @@ function calculateSizeAdjustCSS(font: string, fontMetrics: any) { const fontName = font.trim() const { ascent, descent, lineGap, fallbackFont, sizeAdjust } = - calculateSizeAdjustValues(font, fontMetrics) + calculateSizeAdjustValues(fontMetrics[fontName]) return ` @font-face { From 813444ba7f7eafc1dac21f394a43fe4944777309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Wed, 5 Oct 2022 14:38:15 +0200 Subject: [PATCH 7/8] fix lint --- test/unit/local-font-loader.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/local-font-loader.test.ts b/test/unit/local-font-loader.test.ts index f174ceb21d61d..72096968818e7 100644 --- a/test/unit/local-font-loader.test.ts +++ b/test/unit/local-font-loader.test.ts @@ -1,5 +1,4 @@ import loader from '@next/font/local/loader' -import { calculateSizeAdjustValues } from '@next/font/dist/local/utils' describe('@next/font/local', () => { describe('generated CSS', () => { From a3478ec43d5861d6b3ded8164a847a14a335ff28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Born=C3=B6?= Date: Fri, 7 Oct 2022 10:38:32 +0200 Subject: [PATCH 8/8] ncc fontkit --- packages/font/fontkit.js | 3 +++ packages/font/package.json | 14 +++++++------- packages/font/src/local/loader.ts | 8 +++++--- pnpm-lock.yaml | 24 +++++++++++++----------- 4 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 packages/font/fontkit.js diff --git a/packages/font/fontkit.js b/packages/font/fontkit.js new file mode 100644 index 0000000000000..a5e696245d572 --- /dev/null +++ b/packages/font/fontkit.js @@ -0,0 +1,3 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { create } from 'fontkit' +export default create diff --git a/packages/font/package.json b/packages/font/package.json index 41621b0bb88bc..7c1d0a89c1407 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -12,15 +12,15 @@ ], "license": "MIT", "scripts": { - "build": "rm -rf dist && tsc -d -p tsconfig.json", + "build": "rm -rf dist && pnpm ncc-fontkit && tsc -d -p tsconfig.json", "prepublishOnly": "cd ../../ && turbo run build", - "dev": "tsc -d -w -p tsconfig.json", - "typescript": "tsec --noEmit -p tsconfig.json" - }, - "dependencies": { - "fontkit": "2.0.2" + "dev": "pnpm ncc-fontkit && tsc -d -w -p tsconfig.json", + "typescript": "tsec --noEmit -p tsconfig.json", + "ncc-fontkit": "ncc build ./fontkit.js -o dist/fontkit" }, "devDependencies": { - "@types/fontkit": "2.0.0" + "@types/fontkit": "2.0.0", + "@vercel/ncc": "0.34.0", + "fontkit": "2.0.2" } } diff --git a/packages/font/src/local/loader.ts b/packages/font/src/local/loader.ts index 6d061034e47fd..eb897aa082e89 100644 --- a/packages/font/src/local/loader.ts +++ b/packages/font/src/local/loader.ts @@ -1,6 +1,8 @@ // @ts-ignore import { calculateSizeAdjustValues } from 'next/dist/server/font-utils' -import fontkit from 'fontkit' +// @ts-ignore +// eslint-disable-next-line import/no-extraneous-dependencies +import fontFromBuffer from '@next/font/dist/fontkit' import type { AdjustFontFallback, FontLoader } from 'next/font' import { promisify } from 'util' @@ -37,9 +39,9 @@ const fetchFonts: FontLoader = async ({ const fileBuffer = await promisify(fs.readFile)(resolved) const fontUrl = emitFontFile(fileBuffer, ext, preload) - let fontMetadata: fontkit.Font | undefined + let fontMetadata: any try { - fontMetadata = fontkit.create(fileBuffer) + fontMetadata = fontFromBuffer(fileBuffer) } catch (e) { console.error(`Failed to load font file: ${resolved}\n${e}`) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7e511d7558c47..9dd20f3325df8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -431,11 +431,12 @@ importers: packages/font: specifiers: '@types/fontkit': 2.0.0 - fontkit: 2.0.2 - dependencies: + '@vercel/ncc': 0.34.0 fontkit: 2.0.2 devDependencies: '@types/fontkit': 2.0.0 + '@vercel/ncc': 0.34.0 + fontkit: 2.0.2 packages/next: specifiers: @@ -9816,6 +9817,7 @@ packages: { integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, } + dev: true /bcrypt-pbkdf/1.0.2: resolution: @@ -10050,7 +10052,7 @@ packages: } dependencies: base64-js: 1.5.1 - dev: false + dev: true /browser-process-hrtime/1.0.0: resolution: @@ -11118,7 +11120,7 @@ packages: integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==, } engines: { node: '>=0.8' } - dev: false + dev: true /clor/5.2.0: resolution: @@ -13031,7 +13033,7 @@ packages: { integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==, } - dev: false + dev: true /diagnostics_channel/1.1.0: resolution: @@ -15261,7 +15263,7 @@ packages: tiny-inflate: 1.0.3 unicode-properties: 1.4.1 unicode-trie: 2.0.0 - dev: false + dev: true /for-in/1.0.2: resolution: @@ -22898,7 +22900,7 @@ packages: { integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==, } - dev: false + dev: true /pako/1.0.11: resolution: @@ -26420,7 +26422,7 @@ packages: { integrity: sha512-Xj8/MEIhhfj9X2rmD9iJ4Gga9EFqVlpMj3vfLnV2r/Mh5jRMryNV+6lWh9GdJtDBcBSPIqzRdfBQ3wDtNFv/uw==, } - dev: false + dev: true /ret/0.1.15: resolution: @@ -28684,7 +28686,7 @@ packages: { integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==, } - dev: false + dev: true /tinydate/1.2.0: resolution: @@ -29377,7 +29379,7 @@ packages: dependencies: base64-js: 1.5.1 unicode-trie: 2.0.0 - dev: false + dev: true /unicode-property-aliases-ecmascript/1.0.5: resolution: @@ -29402,7 +29404,7 @@ packages: dependencies: pako: 0.2.9 tiny-inflate: 1.0.3 - dev: false + dev: true /unified-diff/3.1.0: resolution: