--- import type { HTMLAttributes } from 'astro/types'; import { parse } from 'node-html-parser'; type _ModIcons = | 'oneconfig' | 'chatting' | 'polysprint' | 'vanillahud' | 'overflowanimations' | 'crashpatch' | 'polytime' | 'polyweather' | 'keystrokes'; export type ModIcons = _ModIcons; // bypass for Astro compiler issue https://github.com/withastro/compiler/issues/554#issuecomment-1741702411 type _External = | 'discord' | 'github' | 'youtube' | 'twitter'; export type External = _External; type _Icons = | 'chevron-down' | 'download' | 'book-open' | 'link-external' | 'code' | 'chat' | 'user' | External | ModIcons; export type Icons = _Icons; // bypass for Astro compiler issue https://github.com/withastro/compiler/issues/554#issuecomment-1741702411 interface Props extends HTMLAttributes<'svg'> { icon: Icons; path?: string; size?: number | [number, number]; } async function getSVG(name: string) { const file = (await import(`./impl/${name}.svg?raw`)).default; if (!file) throw new Error(`${name} not found`); const content = parse(file); const svg = content.querySelector('svg'); if (!svg) throw new Error(`${name} is not a valid SVG`); const { attributes, innerHTML } = svg; return { attributes, innerHTML, }; } const { icon, size, ...attributes } = Astro.props as Props; let svgAttributes = {}; let html = ''; try { const sizeAttributes = () => { if (!size) return {}; if (Array.isArray(size)) { return { width: size[0], height: size[1], }; } return { width: size, height: size, }; }; const { attributes: baseAttributes, innerHTML } = await getSVG(icon); svgAttributes = { ...baseAttributes, ...attributes, ...sizeAttributes(), }; const colorRegex = /(fill|stroke)=\"([^"]*)\"/g; html = innerHTML.replaceAll(colorRegex, '$1="currentColor"'); } catch (err) { console.error(err); // ignored } ---