@@ -3,6 +3,7 @@ import fs from "fs/promises";
33import glob from "fast-glob" ;
44import { optimize } from "svgo" ;
55import Mustache from "mustache" ;
6+ import { JSDOM } from "jsdom" ;
67
78async function ensureDir ( dir : string ) : Promise < void > {
89 try {
@@ -64,6 +65,58 @@ function pascalCaseName(filename: string): string {
6465 . join ( "" ) ;
6566}
6667
68+ function getSvgFragments ( svg : string ) {
69+ const dom = new JSDOM ( `<svg>${ svg } </svg>` , { contentType : "image/svg+xml" } ) ;
70+ const document = dom . window . document ;
71+
72+ const groupMap : Record < string , Element [ ] > = {
73+ "fr-artwork-decorative" : [ ] ,
74+ "fr-artwork-minor" : [ ] ,
75+ "fr-artwork-major" : [ ]
76+ } ;
77+
78+ const fillToClass = {
79+ "#ececff" : "fr-artwork-decorative" ,
80+ "#e1000f" : "fr-artwork-minor" ,
81+ "#000091" : "fr-artwork-major"
82+ } ;
83+
84+ const allPaths = Array . from ( document . querySelectorAll ( "path" ) ) ;
85+ const used = new Set < Element > ( ) ;
86+
87+ for ( const pathEl of allPaths ) {
88+ const fill = pathEl . getAttribute ( "fill" ) ?. toLowerCase ( ) ?? "" ;
89+ const groupClass = fillToClass [ fill as keyof typeof fillToClass ] ;
90+ if ( groupClass ) {
91+ pathEl . removeAttribute ( "fill" ) ;
92+ groupMap [ groupClass ] . push ( pathEl ) ;
93+ used . add ( pathEl ) ;
94+ }
95+ }
96+
97+ const fragments : string [ ] = [ ] ;
98+
99+ for ( const [ className , elements ] of Object . entries ( groupMap ) ) {
100+ if ( elements . length > 0 ) {
101+ const groupHtml = elements . map ( el => el . outerHTML ) . join ( "" ) ;
102+ fragments . push ( `<g className="${ className } ">${ groupHtml } </g>` ) ;
103+ }
104+ }
105+
106+ const svgElement = document . querySelector ( "svg" ) ;
107+ const remaining =
108+ svgElement &&
109+ Array . from ( svgElement . childNodes )
110+ . filter ( node => node . nodeType === 1 && ! used . has ( node as Element ) )
111+ . map ( node => ( node as Element ) . outerHTML )
112+ . join ( "" ) ;
113+
114+ if ( remaining ) {
115+ fragments . push ( remaining ) ;
116+ }
117+ return fragments ;
118+ }
119+
67120async function generateComponent ( svgPath : string , outputDir : string ) : Promise < string > {
68121 const svgName = path . basename ( svgPath ) ;
69122 const componentName = pascalCaseName ( svgName ) ;
@@ -85,7 +138,7 @@ export default createIcon(
85138
86139 const componentCode = Mustache . render ( template , {
87140 componentName,
88- svgContent : cleanedSvg
141+ svgContent : getSvgFragments ( cleanedSvg ) . join ( "" )
89142 } ) ;
90143
91144 const outPath = path . join ( outputDir , outputFileName ) ;
0 commit comments