UNPKG

react-static-plugin-favicons

Version:

Favicons plugin for React-Static

90 lines (80 loc) 2.64 kB
import * as React from 'react'; import ReactStaticFavicons from '@kuroku/react-static-favicons'; import { Configuration as FaviconsConfiguration } from 'favicons'; interface Options { /** * The source image */ inputFile: string; /** * Directory where the image files will be written */ outputDir?: string; /** * Configuration for `favicons`, see https://www.npmjs.com/package/favicons#nodejs */ configuration?: FaviconsConfiguration; }; interface HookOptions { meta: { faviconsElements?: JSX.Element[]; }; }; interface ReactStaticConfig { paths: { ASSETS: string; }; }; interface ReactStaticConfigData { config: ReactStaticConfig; }; export default (options: Options) => { if (typeof options.inputFile === 'undefined') { console.error('[react-static-plugin-favicons] Please specify a source image for your favicon through the `inputFile` parameter.'); return; } let reactStaticFavicons: ReactStaticFavicons; return { afterGetConfig: (configData: ReactStaticConfigData) => { if (typeof reactStaticFavicons === 'undefined') { reactStaticFavicons = new ReactStaticFavicons({ inputFile: options.inputFile, outputDir: options.outputDir || configData.config.paths.ASSETS, configuration: options.configuration || {}, }); } return configData; }, beforeRenderToHtml: async (element: JSX.Element, { meta }: HookOptions) => { meta.faviconsElements = await renderFaviconsOnce(reactStaticFavicons); return element; }, headElements: async (elements: JSX.Element[], { meta }: HookOptions) => { return [ ...elements, meta.faviconsElements ] } }; }; let renderPromise: Promise<JSX.Element[]>; /** * Singleton process to render favicons * * Because the Node hooks (e.g. `beforeRenderToHtml`) of React Static get called a lot, simply * calling ReactStaticFavicons.render() would spawn a lot of process rendering favicons. * Hence, this function only calls that once, and returns that promise again if called again. * * @param rsf Configured instance of React Static Favicons * @returns Promise that completes once all icons have been generated, returning the elements that * should be added to a page's `<head>`. */ function renderFaviconsOnce(rsf: ReactStaticFavicons) { // We cannot test this due to storing `renderPromise` in the module scope, and thus preserving it // in different tests: /* istanbul ignore else */ if (typeof renderPromise === 'undefined') { renderPromise = rsf.render(); } return renderPromise; }