@next/font
Version:
`@next/font` includes built-in automatic self-hosting for any font file. This means you can optimally load web fonts with zero layout shift, thanks to the underlying CSS size-adjust property used.
76 lines (75 loc) • 3.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-ignore
// eslint-disable-next-line import/no-extraneous-dependencies
let fontFromBuffer;
try {
const mod = require('../fontkit').default;
fontFromBuffer = mod.default || mod;
}
catch { }
const util_1 = require("util");
const pick_font_file_for_fallback_generation_1 = require("./pick-font-file-for-fallback-generation");
const get_fallback_metrics_from_font_file_1 = require("./get-fallback-metrics-from-font-file");
const validate_local_font_function_call_1 = require("./validate-local-font-function-call");
const nextFontLocalFontLoader = async ({ functionName, variableName, data, emitFontFile, resolve, loaderContext, }) => {
const { src, display, fallback, preload, variable, adjustFontFallback, declarations, weight: defaultWeight, style: defaultStyle, } = (0, validate_local_font_function_call_1.validateLocalFontFunctionCall)(functionName, data[0]);
// Load all font files and emit them to the .next output directory
// Also generate a @font-face CSS for each font file
const fontFiles = await Promise.all(src.map(async ({ path, style, weight, ext, format }) => {
const resolved = await resolve(path);
const fileBuffer = await (0, util_1.promisify)(loaderContext.fs.readFile)(resolved);
const fontUrl = emitFontFile(fileBuffer, ext, preload, typeof adjustFontFallback === 'undefined' || !!adjustFontFallback);
// Try to load font metadata from the font file using fontkit.
// The data is used to calculate the fallback font override values.
let fontMetadata;
try {
fontMetadata = fontFromBuffer === null || fontFromBuffer === void 0 ? void 0 : fontFromBuffer(fileBuffer);
}
catch (e) {
console.error(`Failed to load font file: ${resolved}\n${e}`);
}
// Get all values that should be added to the @font-face declaration
const fontFaceProperties = [
...(declarations
? declarations.map(({ prop, value }) => [prop, value])
: []),
['font-family', variableName],
['src', `url(${fontUrl}) format('${format}')`],
['font-display', display],
...((weight !== null && weight !== void 0 ? weight : defaultWeight)
? [['font-weight', weight !== null && weight !== void 0 ? weight : defaultWeight]]
: []),
...((style !== null && style !== void 0 ? style : defaultStyle)
? [['font-style', style !== null && style !== void 0 ? style : defaultStyle]]
: []),
];
// Generate the @font-face CSS from the font-face properties
const css = `@font-face {\n${fontFaceProperties
.map(([property, value]) => `${property}: ${value};`)
.join('\n')}\n}\n`;
return {
css,
fontMetadata,
weight,
style,
};
}));
// Calculate the fallback font override values using the font file metadata
let adjustFontFallbackMetrics;
if (adjustFontFallback !== false) {
const fallbackFontFile = (0, pick_font_file_for_fallback_generation_1.pickFontFileForFallbackGeneration)(fontFiles);
if (fallbackFontFile.fontMetadata) {
adjustFontFallbackMetrics = (0, get_fallback_metrics_from_font_file_1.getFallbackMetricsFromFontFile)(fallbackFontFile.fontMetadata, adjustFontFallback === 'Times New Roman' ? 'serif' : 'sans-serif');
}
}
return {
css: fontFiles.map(({ css }) => css).join('\n'),
fallbackFonts: fallback,
weight: src.length === 1 ? src[0].weight : undefined,
style: src.length === 1 ? src[0].style : undefined,
variable,
adjustFontFallback: adjustFontFallbackMetrics,
};
};
exports.default = nextFontLocalFontLoader;
;