refactor: Convert icon manager into class

This commit is contained in:
Sidharth Vinod
2025-10-29 01:38:42 +09:00
parent 13baf51b35
commit a23c2baed8

View File

@@ -23,10 +23,11 @@ export const unknownIcon: IconifyIcon = {
width: 80, width: 80,
}; };
const iconsStore = new Map<string, IconifyJSON>(); class IconManager {
const loaderStore = new Map<string, AsyncIconLoader['loader']>(); private iconsStore = new Map<string, IconifyJSON>();
private loaderStore = new Map<string, AsyncIconLoader['loader']>();
export const registerIconPacks = (iconLoaders: IconLoader[]) => { registerIconPacks(iconLoaders: IconLoader[]): void {
for (const iconLoader of iconLoaders) { for (const iconLoader of iconLoaders) {
if (!iconLoader.name) { if (!iconLoader.name) {
throw new Error( throw new Error(
@@ -35,17 +36,20 @@ export const registerIconPacks = (iconLoaders: IconLoader[]) => {
} }
log.debug('Registering icon pack:', iconLoader.name); log.debug('Registering icon pack:', iconLoader.name);
if ('loader' in iconLoader) { if ('loader' in iconLoader) {
loaderStore.set(iconLoader.name, iconLoader.loader); this.loaderStore.set(iconLoader.name, iconLoader.loader);
} else if ('icons' in iconLoader) { } else if ('icons' in iconLoader) {
iconsStore.set(iconLoader.name, iconLoader.icons); this.iconsStore.set(iconLoader.name, iconLoader.icons);
} else { } else {
log.error('Invalid icon loader:', iconLoader); log.error('Invalid icon loader:', iconLoader);
throw new Error('Invalid icon loader. Must have either "icons" or "loader" property.'); throw new Error('Invalid icon loader. Must have either "icons" or "loader" property.');
} }
} }
}; }
const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string) => { private async getRegisteredIconData(
iconName: string,
fallbackPrefix?: string
): Promise<ExtendedIconifyIcon> {
const data = stringToIcon(iconName, true, fallbackPrefix !== undefined); const data = stringToIcon(iconName, true, fallbackPrefix !== undefined);
if (!data) { if (!data) {
throw new Error(`Invalid icon name: ${iconName}`); throw new Error(`Invalid icon name: ${iconName}`);
@@ -54,16 +58,16 @@ const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string)
if (!prefix) { if (!prefix) {
throw new Error(`Icon name must contain a prefix: ${iconName}`); throw new Error(`Icon name must contain a prefix: ${iconName}`);
} }
let icons = iconsStore.get(prefix); let icons = this.iconsStore.get(prefix);
if (!icons) { if (!icons) {
const loader = loaderStore.get(prefix); const loader = this.loaderStore.get(prefix);
if (!loader) { if (!loader) {
throw new Error(`Icon set not found: ${data.prefix}`); throw new Error(`Icon set not found: ${data.prefix}`);
} }
try { try {
const loaded = await loader(); const loaded = await loader();
icons = { ...loaded, prefix }; icons = { ...loaded, prefix };
iconsStore.set(prefix, icons); this.iconsStore.set(prefix, icons);
} catch (e) { } catch (e) {
log.error(e); log.error(e);
throw new Error(`Failed to load icon set: ${data.prefix}`); throw new Error(`Failed to load icon set: ${data.prefix}`);
@@ -74,25 +78,25 @@ const getRegisteredIconData = async (iconName: string, fallbackPrefix?: string)
throw new Error(`Icon not found: ${iconName}`); throw new Error(`Icon not found: ${iconName}`);
} }
return iconData; return iconData;
}; }
export const isIconAvailable = async (iconName: string) => { async isIconAvailable(iconName: string): Promise<boolean> {
try { try {
await getRegisteredIconData(iconName); await this.getRegisteredIconData(iconName);
return true; return true;
} catch { } catch {
return false; return false;
} }
}; }
export const getIconSVG = async ( async getIconSVG(
iconName: string, iconName: string,
customisations?: IconifyIconCustomisations & { fallbackPrefix?: string }, customisations?: IconifyIconCustomisations & { fallbackPrefix?: string },
extraAttributes?: Record<string, string> extraAttributes?: Record<string, string>
) => { ): Promise<string> {
let iconData: ExtendedIconifyIcon; let iconData: ExtendedIconifyIcon;
try { try {
iconData = await getRegisteredIconData(iconName, customisations?.fallbackPrefix); iconData = await this.getRegisteredIconData(iconName, customisations?.fallbackPrefix);
} catch (e) { } catch (e) {
log.error(e); log.error(e);
iconData = unknownIcon; iconData = unknownIcon;
@@ -103,4 +107,22 @@ export const getIconSVG = async (
...extraAttributes, ...extraAttributes,
}); });
return sanitizeText(svg, getConfig()); return sanitizeText(svg, getConfig());
}
}
const globalIconManager = new IconManager();
// Export the singleton instance methods for backward compatibility
export const registerIconPacks = (iconLoaders: IconLoader[]) =>
globalIconManager.registerIconPacks(iconLoaders);
export const isIconAvailable = async (iconName: string) => {
return await globalIconManager.isIconAvailable(iconName);
};
export const getIconSVG = async (
iconName: string,
customisations?: IconifyIconCustomisations & { fallbackPrefix?: string },
extraAttributes?: Record<string, string>
) => {
return await globalIconManager.getIconSVG(iconName, customisations, extraAttributes);
}; };