228 lines
7.7 KiB
JavaScript
228 lines
7.7 KiB
JavaScript
|
"use strict";
|
|||
|
Object.defineProperty(exports, "__esModule", {
|
|||
|
value: true
|
|||
|
});
|
|||
|
0 && (module.exports = {
|
|||
|
getFontDefinitionFromNetwork: null,
|
|||
|
getFontDefinitionFromManifest: null,
|
|||
|
calculateOverrideValues: null,
|
|||
|
calculateSizeAdjustValues: null,
|
|||
|
getFontOverrideCss: null
|
|||
|
});
|
|||
|
function _export(target, all) {
|
|||
|
for(var name in all)Object.defineProperty(target, name, {
|
|||
|
enumerable: true,
|
|||
|
get: all[name]
|
|||
|
});
|
|||
|
}
|
|||
|
_export(exports, {
|
|||
|
getFontDefinitionFromNetwork: function() {
|
|||
|
return getFontDefinitionFromNetwork;
|
|||
|
},
|
|||
|
getFontDefinitionFromManifest: function() {
|
|||
|
return getFontDefinitionFromManifest;
|
|||
|
},
|
|||
|
calculateOverrideValues: function() {
|
|||
|
return calculateOverrideValues;
|
|||
|
},
|
|||
|
calculateSizeAdjustValues: function() {
|
|||
|
return calculateSizeAdjustValues;
|
|||
|
},
|
|||
|
getFontOverrideCss: function() {
|
|||
|
return getFontOverrideCss;
|
|||
|
}
|
|||
|
});
|
|||
|
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../build/output/log"));
|
|||
|
const _constants = require("../shared/lib/constants");
|
|||
|
function _getRequireWildcardCache(nodeInterop) {
|
|||
|
if (typeof WeakMap !== "function") return null;
|
|||
|
var cacheBabelInterop = new WeakMap();
|
|||
|
var cacheNodeInterop = new WeakMap();
|
|||
|
return (_getRequireWildcardCache = function(nodeInterop) {
|
|||
|
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|||
|
})(nodeInterop);
|
|||
|
}
|
|||
|
function _interop_require_wildcard(obj, nodeInterop) {
|
|||
|
if (!nodeInterop && obj && obj.__esModule) {
|
|||
|
return obj;
|
|||
|
}
|
|||
|
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|||
|
return {
|
|||
|
default: obj
|
|||
|
};
|
|||
|
}
|
|||
|
var cache = _getRequireWildcardCache(nodeInterop);
|
|||
|
if (cache && cache.has(obj)) {
|
|||
|
return cache.get(obj);
|
|||
|
}
|
|||
|
var newObj = {};
|
|||
|
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|||
|
for(var key in obj){
|
|||
|
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|||
|
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|||
|
if (desc && (desc.get || desc.set)) {
|
|||
|
Object.defineProperty(newObj, key, desc);
|
|||
|
} else {
|
|||
|
newObj[key] = obj[key];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
newObj.default = obj;
|
|||
|
if (cache) {
|
|||
|
cache.set(obj, newObj);
|
|||
|
}
|
|||
|
return newObj;
|
|||
|
}
|
|||
|
const capsizeFontsMetrics = require("next/dist/server/capsize-font-metrics.json");
|
|||
|
const https = require("https");
|
|||
|
const CHROME_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36";
|
|||
|
const IE_UA = "Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko";
|
|||
|
function isGoogleFont(url) {
|
|||
|
return url.startsWith(_constants.GOOGLE_FONT_PROVIDER);
|
|||
|
}
|
|||
|
function getFontForUA(url, UA) {
|
|||
|
return new Promise((resolve, reject)=>{
|
|||
|
let rawData = "";
|
|||
|
https.get(url, {
|
|||
|
headers: {
|
|||
|
"user-agent": UA
|
|||
|
}
|
|||
|
}, (res)=>{
|
|||
|
res.on("data", (chunk)=>{
|
|||
|
rawData += chunk;
|
|||
|
});
|
|||
|
res.on("end", ()=>{
|
|||
|
resolve(rawData.toString("utf8"));
|
|||
|
});
|
|||
|
}).on("error", (e)=>{
|
|||
|
reject(e);
|
|||
|
});
|
|||
|
});
|
|||
|
}
|
|||
|
async function getFontDefinitionFromNetwork(url) {
|
|||
|
let result = "";
|
|||
|
/**
|
|||
|
* The order of IE -> Chrome is important, other wise chrome starts loading woff1.
|
|||
|
* CSS cascading 🤷♂️.
|
|||
|
*/ try {
|
|||
|
if (isGoogleFont(url)) {
|
|||
|
result += await getFontForUA(url, IE_UA);
|
|||
|
}
|
|||
|
result += await getFontForUA(url, CHROME_UA);
|
|||
|
} catch (e) {
|
|||
|
_log.warn(`Failed to download the stylesheet for ${url}. Skipped optimizing this font.`);
|
|||
|
return "";
|
|||
|
}
|
|||
|
return result;
|
|||
|
}
|
|||
|
function getFontDefinitionFromManifest(url, manifest) {
|
|||
|
var _manifest_find;
|
|||
|
return ((_manifest_find = manifest.find((font)=>{
|
|||
|
if (font && font.url === url) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
})) == null ? void 0 : _manifest_find.content) || "";
|
|||
|
}
|
|||
|
function parseGoogleFontName(css) {
|
|||
|
const regex = /font-family: ([^;]*)/g;
|
|||
|
const matches = css.matchAll(regex);
|
|||
|
const fontNames = new Set();
|
|||
|
for (let font of matches){
|
|||
|
const fontFamily = font[1].replace(/^['"]|['"]$/g, "");
|
|||
|
fontNames.add(fontFamily);
|
|||
|
}
|
|||
|
return [
|
|||
|
...fontNames
|
|||
|
];
|
|||
|
}
|
|||
|
function formatName(str) {
|
|||
|
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(word, index) {
|
|||
|
return index === 0 ? word.toLowerCase() : word.toUpperCase();
|
|||
|
}).replace(/\s+/g, "");
|
|||
|
}
|
|||
|
function formatOverrideValue(val) {
|
|||
|
return Math.abs(val * 100).toFixed(2);
|
|||
|
}
|
|||
|
function calculateOverrideValues(fontName) {
|
|||
|
const fontKey = formatName(fontName);
|
|||
|
const fontMetrics = capsizeFontsMetrics[fontKey];
|
|||
|
let { category, ascent, descent, lineGap, unitsPerEm } = fontMetrics;
|
|||
|
const fallbackFont = category === "serif" ? _constants.DEFAULT_SERIF_FONT : _constants.DEFAULT_SANS_SERIF_FONT;
|
|||
|
ascent = formatOverrideValue(ascent / unitsPerEm);
|
|||
|
descent = formatOverrideValue(descent / unitsPerEm);
|
|||
|
lineGap = formatOverrideValue(lineGap / unitsPerEm);
|
|||
|
return {
|
|||
|
ascent,
|
|||
|
descent,
|
|||
|
lineGap,
|
|||
|
fallbackFont: fallbackFont.name
|
|||
|
};
|
|||
|
}
|
|||
|
function calculateSizeAdjustValues(fontName) {
|
|||
|
const fontKey = formatName(fontName);
|
|||
|
const fontMetrics = capsizeFontsMetrics[fontKey];
|
|||
|
let { category, ascent, descent, lineGap, unitsPerEm, xWidthAvg } = fontMetrics;
|
|||
|
const mainFontAvgWidth = xWidthAvg / unitsPerEm;
|
|||
|
const fallbackFont = category === "serif" ? _constants.DEFAULT_SERIF_FONT : _constants.DEFAULT_SANS_SERIF_FONT;
|
|||
|
const fallbackFontName = formatName(fallbackFont.name);
|
|||
|
const fallbackFontMetrics = capsizeFontsMetrics[fallbackFontName];
|
|||
|
const fallbackFontAvgWidth = fallbackFontMetrics.xWidthAvg / fallbackFontMetrics.unitsPerEm;
|
|||
|
let sizeAdjust = xWidthAvg ? mainFontAvgWidth / fallbackFontAvgWidth : 1;
|
|||
|
ascent = formatOverrideValue(ascent / (unitsPerEm * sizeAdjust));
|
|||
|
descent = formatOverrideValue(descent / (unitsPerEm * sizeAdjust));
|
|||
|
lineGap = formatOverrideValue(lineGap / (unitsPerEm * sizeAdjust));
|
|||
|
return {
|
|||
|
ascent,
|
|||
|
descent,
|
|||
|
lineGap,
|
|||
|
fallbackFont: fallbackFont.name,
|
|||
|
sizeAdjust: formatOverrideValue(sizeAdjust)
|
|||
|
};
|
|||
|
}
|
|||
|
function calculateOverrideCSS(font) {
|
|||
|
const fontName = font.trim();
|
|||
|
const { ascent, descent, lineGap, fallbackFont } = calculateOverrideValues(fontName);
|
|||
|
return `
|
|||
|
@font-face {
|
|||
|
font-family: "${fontName} Fallback";
|
|||
|
ascent-override: ${ascent}%;
|
|||
|
descent-override: ${descent}%;
|
|||
|
line-gap-override: ${lineGap}%;
|
|||
|
src: local("${fallbackFont}");
|
|||
|
}
|
|||
|
`;
|
|||
|
}
|
|||
|
function calculateSizeAdjustCSS(font) {
|
|||
|
const fontName = font.trim();
|
|||
|
const { ascent, descent, lineGap, fallbackFont, sizeAdjust } = calculateSizeAdjustValues(fontName);
|
|||
|
return `
|
|||
|
@font-face {
|
|||
|
font-family: "${fontName} Fallback";
|
|||
|
ascent-override: ${ascent}%;
|
|||
|
descent-override: ${descent}%;
|
|||
|
line-gap-override: ${lineGap}%;
|
|||
|
size-adjust: ${sizeAdjust}%;
|
|||
|
src: local("${fallbackFont}");
|
|||
|
}
|
|||
|
`;
|
|||
|
}
|
|||
|
function getFontOverrideCss(url, css, useSizeAdjust = false) {
|
|||
|
if (!isGoogleFont(url)) {
|
|||
|
return "";
|
|||
|
}
|
|||
|
const calcFn = useSizeAdjust ? calculateSizeAdjustCSS : calculateOverrideCSS;
|
|||
|
try {
|
|||
|
const fontNames = parseGoogleFontName(css);
|
|||
|
const fontCss = fontNames.reduce((cssStr, fontName)=>{
|
|||
|
cssStr += calcFn(fontName);
|
|||
|
return cssStr;
|
|||
|
}, "");
|
|||
|
return fontCss;
|
|||
|
} catch (e) {
|
|||
|
console.log("Error getting font override values - ", e);
|
|||
|
return "";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//# sourceMappingURL=font-utils.js.map
|