Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
better handling of font listener
  • Loading branch information
Himanshu Patil committed Aug 8, 2022
commit b3facd1ba8b23605ee44cc225266d18afa02b46a
36 changes: 36 additions & 0 deletions consts/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
export const MODE_DEFAULT = "async";
export const SCOPE_DEFAULT = "body";
export const TIMEOUT_DEFAULT = 30000;
export const INTERVAL_DEFAULT = 300;

export const WEIGHTS = {
1: "100",
2: "200",
3: "300",
4: "400",
5: "500",
6: "600",
7: "700",
8: "800",
9: "900",
100: "1",
200: "2",
300: "3",
400: "4",
500: "5",
600: "6",
700: "7",
800: "8",
900: "9",
normal: "4",
bold: "7",
}

export const STYLES = {
n: "normal",
i: "italic",
o: "oblique",
normal: "n",
italic: "i",
oblique: "o",
}

export const VARIATION_MATCH = new RegExp("^(n|i)([1-9])$")
28 changes: 16 additions & 12 deletions gatsby-browser.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import React from "react";
import { AsyncFonts } from "./components";
import { MODE_DEFAULT, SCOPE_DEFAULT } from "./consts";
import { getFontFiles, getFontNames } from "./utils";
import { fontListener } from "./utils/fontListener";
import React from 'react';
import { AsyncFonts } from './components';
import { MODE_DEFAULT, SCOPE_DEFAULT, TIMEOUT_DEFAULT, INTERVAL_DEFAULT } from './consts';
import { getFontFiles, getFontNames } from './utils';
import { fontListener } from './utils/fontListener';

export const onClientEntry = (
_,
{ custom = [], web = [], enableListener = false, scope = SCOPE_DEFAULT }
{
custom = [],
web = [],
enableListener = false,
scope = SCOPE_DEFAULT,
timeout = TIMEOUT_DEFAULT,
interval = INTERVAL_DEFAULT,
}
) => {
if (!enableListener) {
return;
}

const allFonts = [...custom, ...web];
const fontNames = getFontNames(allFonts);
const listenerProps = { fontNames, scope };
const listenerProps = { fontNames, scope, timeout, interval };

fontListener(listenerProps);
};

export const wrapRootElement = (
{ element },
{ custom = [], web = [], mode = MODE_DEFAULT }
) => {
if (mode !== "async") {
export const wrapRootElement = ({ element }, { custom = [], web = [], mode = MODE_DEFAULT }) => {
if (mode !== 'async') {
return element;
}

Expand Down
55 changes: 29 additions & 26 deletions utils/fontListener.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { info, warn } from './logger';
import { convertToFVD, parseFontInfo } from './parseFontInfo';

export type FontInfo = { fontName: string; fontStyle: string; fontWeight: string }
const fontLoadConst = {
interval: 10,
timeout: 5000,
}
export const fontListener = ({ fontNames, scope }) => {

export const fontListener = ({ fontNames, scope, timeout, interval }) => {

const hasFonts = fontNames && Boolean(fontNames.length);
const targetElement = scope === "html" ? "documentElement" : "body";
Expand All @@ -24,26 +22,31 @@ export const fontListener = ({ fontNames, scope }) => {

function fontMapper(fontDetail: FontInfo) {
const fontFace = [fontDetail.fontStyle, fontDetail.fontWeight, '1rem', fontDetail.fontName].join(' ')
// refer https://stackoverflow.com/a/64192936/9740955
const startTime = Date.now();

return new Promise((resolve, reject) => {
const poller = setInterval(async () => {
try {
await document.fonts.load(fontFace);
} catch (err) {
clearTimeout(timeOut)
clearInterval(poller);
errorFallback(err)
reject(err)
}
if (document.fonts.check(fontFace)) {
clearTimeout(timeOut)
clearInterval(poller);
handleFontLoad(fontDetail)
resolve(true);
const recursiveFn = () => {
const currTime = Date.now();

if ((currTime - startTime) >= timeout) {
reject('font listener timeout ' + fontFace);
} else {
document.fonts.load(fontFace).then((fonts) => {
if (fonts.length >= 1) {
handleFontLoad(fontDetail);
resolve(true);
} else {
setTimeout(recursiveFn, interval);
}
}).catch((err) => {
errorFallback(err);
reject(err);
});
}
}, fontLoadConst.interval);
const timeOut = setTimeout(() => clearInterval(poller), fontLoadConst.timeout);
})
};
recursiveFn()
});

}

function loadFonts() {
Expand All @@ -52,13 +55,13 @@ export const fontListener = ({ fontNames, scope }) => {
}

function errorFallback(e) {
console.warn('error in omni font loader', e)
warn('error in omni font loader', e)
parsedFont.forEach((fontInfo) => addClassName(convertToFVD(fontInfo)));
}

function handleApiError(error) {
console.info(`document.fonts API error: ${error}`);
console.info(`Replacing fonts instantly. FOUT handling failed.`);
info(`document.fonts API error: ${error}`);
info(`Replacing fonts instantly. FOUT handling failed.`);
errorFallback(error);
}

Expand Down
20 changes: 20 additions & 0 deletions utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

const warn = (function (environment) {
if (environment === "production") {
return () => { }
}
return (...args) => {
console.warn(...args)
}
})(process.env.NODE_ENV);

const info = (function (environment) {
if (environment === "production") {
return () => { }
}
return (...args) => {
console.info(...args)
}
})(process.env.NODE_ENV);

export { warn, info }
51 changes: 7 additions & 44 deletions utils/parseFontInfo.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,6 @@
import { kebabCase } from "../utils";
import { FontInfo } from './fontListener';


const weights = {
1: "100",
2: "200",
3: "300",
4: "400",
5: "500",
6: "600",
7: "700",
8: "800",
9: "900",
100: "1",
200: "2",
300: "3",
400: "4",
500: "5",
600: "6",
700: "7",
800: "8",
900: "9",
normal: "4",
bold: "7",
}


const styles = {
n: "normal",
i: "italic",
o: "oblique",
normal: "n",
italic: "i",
oblique: "o",
}

const VARIATION_MATCH = new RegExp("^(n|i)([1-9])$")

import { VARIATION_MATCH, WEIGHTS, STYLES } from '../consts';

export const parseFontInfo = (fontFamilies: string[]) => {
const length = fontFamilies.length
Expand Down Expand Up @@ -82,14 +46,14 @@ export const normalizeStyle = (parsedStyle: string): string => {
if (!parsedStyle) {
return ""
}
return styles[parsedStyle]
return STYLES[parsedStyle]
}

export const normalizeWeight = (parsedWeight: string | number): string => {
if (!parsedWeight) {
return ""
}
return weights[parsedWeight]
return WEIGHTS[parsedWeight]

}

Expand All @@ -114,11 +78,10 @@ const parseVariations = (variations: string) => {
}


export const convertToFVD = (fontInfo: FontInfo) => {
const weightVal = normalizeWeight(fontInfo.fontWeight)
const styleVal = normalizeStyle(fontInfo.fontStyle)
export const convertToFVD = ({fontName, fontStyle, fontWeight}: FontInfo) => {
const weightVal = normalizeWeight(fontWeight)
const styleVal = normalizeStyle(fontStyle)
const styleWeight = styleVal + weightVal
const fontNameVal = kebabCase(fontInfo.fontName)
const fontNameVal = kebabCase(fontName)
return styleWeight ? [fontNameVal, styleWeight].join('-') : fontNameVal

}