import { installPackage } from '@antfu/install-pkg'; import { Awaitable, sleep } from '@antfu/utils'; import { cyan, yellow } from 'kolorist'; import type { IconCustomizer } from './types'; const warned = new Set(); export function warnOnce(msg: string): void { if (!warned.has(msg)) { warned.add(msg); console.warn(yellow(`[@iconify-loader] ${msg}`)); } } let pending: Promise | undefined; const tasks: Record | undefined> = {}; export async function mergeIconProps( svg: string, collection: string, icon: string, additionalProps: Record, propsProvider?: () => Awaitable>, iconCustomizer?: IconCustomizer, ): Promise { const props: Record = await propsProvider?.() ?? {} await iconCustomizer?.(collection, icon, props) Object.keys(additionalProps).forEach((p) => { const v = additionalProps[p] if (v !== undefined && v !== null) props[p] = v }) const replacement = svg.startsWith(' `${p}="${props[p]}"`).join(' ')}`) } export async function tryInstallPkg(name: string): Promise { if (pending) { await pending; } if (!tasks[name]) { // eslint-disable-next-line no-console console.log(cyan(`Installing ${name}...`)); tasks[name] = pending = installPackage(name, { dev: true, preferOffline: true, }) .then(() => sleep(300)) // eslint-disable-next-line .catch((e: any) => { warnOnce(`Failed to install ${name}`); console.error(e); }) .finally(() => { pending = undefined; }); } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return tasks[name]!; }