1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
---
import type { HTMLAttributes } from 'astro/types';
import { parse } from 'node-html-parser';
type _ModIcons =
| '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 _Icons =
| 'chevron-down'
| 'download'
| 'book-open'
| 'link-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
size?: number | [number, number]
}
async function getSVG(name: string) {
const file = await import(/* @vite-ignore */ `./impl/${name}.svg?raw`);
if (!file)
throw new Error(`${name} not found`);
const content = parse(file.default);
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) {
// ignored
}
---
<svg {...svgAttributes} set:html={html}></svg>
|