@@ -7,9 +7,6 @@ const files = import.meta.glob('@/assets/svg/icons/**.svg', {
77 query : '?raw' ,
88} )
99const re = / \/ ( [ ^ / ] + ) \. s v g $ /
10- const materialIconInnerSvgClass
11- = '[&_svg]:block [&_svg]:size-full overflow-hidden'
12-
1310type FolderIconSource = 'material' | 'lucide'
1411type FolderIconFilter = 'all' | FolderIconSource
1512
@@ -23,6 +20,7 @@ interface FolderIconOption {
2320 name : string
2421 searchValue : string
2522 source : FolderIconSource
23+ src ?: string
2624 svg ?: string
2725 value : string
2826}
@@ -45,7 +43,37 @@ function createFolderIconValue(source: FolderIconSource, name: string) {
4543 return `${ source } :${ name } `
4644}
4745
46+ function escapeRegExp ( value : string ) {
47+ return value . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, '\\$&' )
48+ }
49+
50+ function sanitizeMaterialIconSvg ( name : string , svg : string ) {
51+ const prefix = `folder-icon-${ name . replace ( / [ ^ \w - ] / g, '-' ) } -`
52+ const ids = [ ...svg . matchAll ( / \b i d = " ( [ ^ " ] + ) " / g) ] . map ( ( [ , id ] ) => id )
53+
54+ if ( ids . length === 0 )
55+ return svg
56+
57+ return ids . reduce ( ( result , id ) => {
58+ const uniqueId = `${ prefix } ${ id } `
59+ const escapedId = escapeRegExp ( id )
60+
61+ return result
62+ . replace ( new RegExp ( `\\bid="${ escapedId } "` , 'g' ) , `id="${ uniqueId } "` )
63+ . replace ( new RegExp ( `url\\(#${ escapedId } \\)` , 'g' ) , `url(#${ uniqueId } )` )
64+ . replace (
65+ new RegExp ( `\\b(xlink:href|href)="#${ escapedId } "` , 'g' ) ,
66+ `$1="#${ uniqueId } "` ,
67+ )
68+ } , svg )
69+ }
70+
71+ function createMaterialIconSrc ( svg : string ) {
72+ return `data:image/svg+xml;charset=utf-8,${ encodeURIComponent ( svg ) } `
73+ }
74+
4875const materialIconsSet : Record < string , string > = { }
76+ const materialIconSrcSet : Record < string , string > = { }
4977
5078const materialIcons : FolderIconOption [ ] = Object . entries ( files )
5179 . flatMap ( ( [ path , raw ] ) => {
@@ -54,15 +82,17 @@ const materialIcons: FolderIconOption[] = Object.entries(files)
5482 if ( ! name )
5583 return [ ]
5684
57- const svg = raw as string
85+ const svg = sanitizeMaterialIconSvg ( name , raw as string )
5886
5987 materialIconsSet [ name ] = svg
88+ materialIconSrcSet [ name ] = createMaterialIconSrc ( svg )
6089
6190 return [
6291 {
6392 name,
6493 searchValue : name . toLowerCase ( ) ,
6594 source : 'material' as const ,
95+ src : materialIconSrcSet [ name ] ,
6696 svg,
6797 value : createFolderIconValue ( 'material' , name ) ,
6898 } ,
@@ -135,14 +165,16 @@ function resolveFolderIcon(value?: string | null): FolderIconOption | null {
135165
136166 if ( parsedValue . source === 'material' ) {
137167 const svg = materialIconsSet [ parsedValue . name ]
168+ const src = materialIconSrcSet [ parsedValue . name ]
138169
139- if ( ! svg )
170+ if ( ! svg || ! src )
140171 return null
141172
142173 return {
143174 name : parsedValue . name ,
144175 searchValue : parsedValue . name . toLowerCase ( ) ,
145176 source : parsedValue . source ,
177+ src,
146178 svg,
147179 value : createFolderIconValue ( parsedValue . source , parsedValue . name ) ,
148180 }
@@ -195,7 +227,6 @@ export {
195227 groupFolderIcons ,
196228 materialIcons as icons ,
197229 materialIconsSet as iconsSet ,
198- materialIconInnerSvgClass ,
199230 materialIcons ,
200231 materialIconsSet ,
201232 parseFolderIconValue ,
0 commit comments