@@ -14,9 +14,17 @@ interface PluginProps {
1414 outputDir : string ;
1515 fileName ?: string ;
1616 cwd ?: string ;
17+ iconNameTransformer ?: ( fileName : string ) => string ;
1718}
1819
19- const generateIcons = async ( { withTypes = false , inputDir, outputDir, cwd, fileName = "sprite.svg" } : PluginProps ) => {
20+ const generateIcons = async ( {
21+ withTypes = false ,
22+ inputDir,
23+ outputDir,
24+ cwd,
25+ fileName = "sprite.svg" ,
26+ iconNameTransformer,
27+ } : PluginProps ) => {
2028 const cwdToUse = cwd ?? process . cwd ( ) ;
2129 const inputDirRelative = path . relative ( cwdToUse , inputDir ) ;
2230 const outputDirRelative = path . relative ( cwdToUse , outputDir ) ;
@@ -35,15 +43,21 @@ const generateIcons = async ({ withTypes = false, inputDir, outputDir, cwd, file
3543 inputDir,
3644 outputPath : path . join ( outputDir , fileName ) ,
3745 outputDirRelative,
46+ iconNameTransformer,
3847 } ) ;
3948 if ( withTypes ) {
4049 await generateTypes ( {
41- names : files . map ( ( file : string ) => fileNameToCamelCase ( file . replace ( / \. s v g $ / , "" ) ) ) ,
50+ names : files . map ( ( file : string ) => transformIconName ( file , iconNameTransformer ?? fileNameToCamelCase ) ) ,
4251 outputPath : path . join ( outputDir , "types.ts" ) ,
4352 } ) ;
4453 }
4554} ;
4655
56+ const transformIconName = ( fileName : string , transformer : ( iconName : string ) => string ) => {
57+ const iconName = fileName . replace ( / \. s v g $ / , "" ) ;
58+ return transformer ( iconName ) ;
59+ } ;
60+
4761function fileNameToCamelCase ( fileName : string ) : string {
4862 const words = fileName . split ( "-" ) ;
4963 const capitalizedWords = words . map ( ( word ) => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) ) ;
@@ -57,16 +71,18 @@ async function generateSvgSprite({
5771 inputDir,
5872 outputPath,
5973 outputDirRelative,
74+ iconNameTransformer,
6075} : {
6176 files : string [ ] ;
6277 inputDir : string ;
6378 outputPath : string ;
6479 outputDirRelative ?: string ;
80+ iconNameTransformer ?: ( fileName : string ) => string ;
6581} ) {
6682 // Each SVG becomes a symbol and we wrap them all in a single SVG
6783 const symbols = await Promise . all (
6884 files . map ( async ( file ) => {
69- const fileName = fileNameToCamelCase ( file . replace ( / \. s v g $ / , "" ) ) ;
85+ const fileName = transformIconName ( file , iconNameTransformer ?? fileNameToCamelCase ) ;
7086 const input = await fs . readFile ( path . join ( inputDir , file ) , "utf8" ) ;
7187
7288 const root = parse ( input ) ;
@@ -86,8 +102,8 @@ async function generateSvgSprite({
86102 } )
87103 ) ;
88104 const output = [
89- " <?xml version=\ "1.0\ " encoding=\ "UTF-8\ "?>" ,
90- " <svg xmlns=\ "http://www.w3.org/2000/svg\ " xmlns:xlink=\ "http://www.w3.org/1999/xlink\ " width=\"0\ " height=\"0\">" ,
105+ ' <?xml version="1.0" encoding="UTF-8"?>' ,
106+ ' <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="0 " height="0">' ,
91107 "<defs>" , // for semantics: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
92108 ...symbols . filter ( Boolean ) ,
93109 "</defs>" ,
@@ -136,39 +152,41 @@ async function writeIfChanged(filepath: string, newContent: string, message: str
136152 }
137153}
138154
139- export const iconsSpritesheet : ( args : PluginProps ) => Plugin = ( { withTypes, inputDir, outputDir, fileName, cwd } ) => ( {
140- name : "icon-spritesheet-generator" ,
141- apply ( config ) {
142- return config . mode === "development" ;
143- } ,
144- async configResolved ( ) {
145- await generateIcons ( {
155+ export const iconsSpritesheet : ( args : PluginProps ) => Plugin = ( {
156+ withTypes,
157+ inputDir,
158+ outputDir,
159+ fileName,
160+ cwd,
161+ iconNameTransformer,
162+ } ) => {
163+ const iconGenerator = async ( ) =>
164+ generateIcons ( {
146165 withTypes,
147166 inputDir,
148167 outputDir,
149168 fileName,
169+ iconNameTransformer,
150170 } ) ;
151- } ,
152- async watchChange ( file , type ) {
153- const inputPath = normalizePath ( path . join ( cwd ?? process . cwd ( ) , inputDir ) ) ;
154- if ( file . includes ( inputPath ) && file . endsWith ( ".svg" ) && [ "create" , "delete" ] . includes ( type . event ) ) {
155- await generateIcons ( {
156- withTypes,
157- inputDir,
158- outputDir,
159- fileName,
160- } ) ;
161- }
162- } ,
163- async handleHotUpdate ( { file } ) {
164- const inputPath = normalizePath ( path . join ( cwd ?? process . cwd ( ) , inputDir ) ) ;
165- if ( file . includes ( inputPath ) && file . endsWith ( ".svg" ) ) {
166- await generateIcons ( {
167- withTypes,
168- inputDir,
169- outputDir,
170- fileName,
171- } ) ;
172- }
173- } ,
174- } ) ;
171+ return {
172+ name : "icon-spritesheet-generator" ,
173+ apply ( config ) {
174+ return config . mode === "development" ;
175+ } ,
176+ async configResolved ( ) {
177+ await iconGenerator ( ) ;
178+ } ,
179+ async watchChange ( file , type ) {
180+ const inputPath = normalizePath ( path . join ( cwd ?? process . cwd ( ) , inputDir ) ) ;
181+ if ( file . includes ( inputPath ) && file . endsWith ( ".svg" ) && [ "create" , "delete" ] . includes ( type . event ) ) {
182+ await iconGenerator ( ) ;
183+ }
184+ } ,
185+ async handleHotUpdate ( { file } ) {
186+ const inputPath = normalizePath ( path . join ( cwd ?? process . cwd ( ) , inputDir ) ) ;
187+ if ( file . includes ( inputPath ) && file . endsWith ( ".svg" ) ) {
188+ await iconGenerator ( ) ;
189+ }
190+ } ,
191+ } ;
192+ } ;
0 commit comments