UNPKG

@openscript/unplugin-favicons

Version:

Generate favicons for your project with caching for blazing fast rebuilds.

107 lines 4.38 kB
import { basename, join, resolve } from "node:path"; import { colorize } from "consola/utils"; import { favicons } from "favicons"; import { DEFAULT_FAVICONS_OPTIONS, DEFAULT_ICON_OPTIONS } from "../const.js"; import consola from "../utils/consola.js"; import generateCacheKeyForJob from "./generate-cache-key-for-job.js"; import getCacheResponse from "./get-cache-response.js"; import putCacheResponse from "./put-cache-response.js"; /** * @private * * Provided a `FaviconsPluginOptions` object, returns an array of * [source, FaviconOptions] tuples, each representing a distinct `favicons` job * to run. */ const mapOptionsToJobs = (options) => { const { icons: notUsed, ...others } = (options.favicons ?? {}); // eslint-disable-next-line unicorn/no-array-reduce return Object.entries(options.icons).reduce((jobs, [iconType, sourceAndIconOptions]) => { const { source, ...iconOptions } = sourceAndIconOptions; // Create a new 'icons' configuration key that contains only the current // icon type. const icons = { ...DEFAULT_ICON_OPTIONS, [iconType]: iconOptions }; const config = { ...others, icons }; const job = { config, iconType, source }; return [...jobs, job]; }, []); }; /** * @private * * Provided an array of `FaviconResponse` objects from each job, merges them * into a single `FaviconResponse` object. */ const reduceResponses = (responses) => // eslint-disable-next-line unicorn/no-array-reduce responses.reduce((response, currentResponse) => { currentResponse.files.forEach((file) => { response.files.push(file); }); currentResponse.images.forEach((image) => { response.images.push(image); }); currentResponse.html.forEach((html) => { response.html.push(html); }); return response; }, { files: [], html: [], images: [], }); /** * Provided a FaviconsPluginOptions object, generates assets and returns a * FaviconResponse object. */ const generateFavicons = async (options) => { // Because favicons only allows a single source asset per invocation, map // incoming configuration into a list of jobs we will need to run. const jobConfigs = []; if (options.icons && !options.logo) { jobConfigs.push(...mapOptionsToJobs(options)); } else { const config = { ...DEFAULT_FAVICONS_OPTIONS, ...options.favicons, icons: { ...DEFAULT_FAVICONS_OPTIONS.icons, ...options.favicons?.icons, }, }; // eslint-disable-next-line no-param-reassign options.logo = resolve(options.logo ?? join("assets", "logo.png")); jobConfigs.push({ config, iconType: "logo", source: options.logo }); } const jobs = jobConfigs.map(async (jobConfig) => { // N.B. Favicons modifies the `config` object in-place, so we need to // generate a key now to ensure that our cache get/put functions use the // same one. const cacheKeyForJob = await generateCacheKeyForJob(jobConfig); const { config, iconType, source } = jobConfig; const sourceFileName = basename(source); if (options.cache) { // If we have a cached response for this source asset, return it. const cachedResponse = await getCacheResponse(cacheKeyForJob, iconType); if (cachedResponse) { consola.verbose(`Using cached ${colorize("bold", iconType)} assets from source ${colorize("green", sourceFileName)}.`); return cachedResponse; } } const response = await favicons(source, config); if (options.cache) { // Return the response immediately without awaiting the cache write. // eslint-disable-next-line no-void,promise/always-return void putCacheResponse(cacheKeyForJob, response, iconType).then(() => { consola.verbose(`Cached rendered ${colorize("bold", iconType)} assets from source ${colorize("green", sourceFileName)}.`); }); } return response; }); // Merge each response into a single `FaviconsResponse`. // eslint-disable-next-line compat/compat return reduceResponses(await Promise.all(jobs)); }; export default generateFavicons; //# sourceMappingURL=generate-favicons.js.map