@@ -92,6 +92,29 @@ const CSS_IMPORT_RE =
9292
9393const REBASE_URL_RE = / \b u r l \( \s * ( [ " ' ] ? ) ( [ ^ ) " ' ] + ) \1\s * \) / g;
9494
95+ const CSS_COMMENT_RE = / \/ \* [ \s \S ] * ?\* \/ / g;
96+
97+ function withCommentsStripped < T > (
98+ css : string ,
99+ fn : ( stripped : string ) => T ,
100+ ) : { result : T ; restore : ( s : string ) => string } {
101+ const comments : string [ ] = [ ] ;
102+ const stripped = css . replace ( CSS_COMMENT_RE , ( m ) => {
103+ const idx = comments . length ;
104+ comments . push ( m ) ;
105+ return `/*__hf_c${ idx } __*/` ;
106+ } ) ;
107+ const result = fn ( stripped ) ;
108+ const restore = ( s : string ) => {
109+ let out = s ;
110+ for ( let i = 0 ; i < comments . length ; i ++ ) {
111+ out = out . replace ( `/*__hf_c${ i } __*/` , comments [ i ] ! ) ;
112+ }
113+ return out ;
114+ } ;
115+ return { result, restore } ;
116+ }
117+
95118function rebaseCssUrls ( css : string , cssFileDir : string , projectDir : string ) : string {
96119 const resolvedRoot = resolve ( projectDir ) ;
97120 const resolvedDir = resolve ( cssFileDir ) ;
@@ -101,7 +124,7 @@ function rebaseCssUrls(css: string, cssFileDir: string, projectDir: string): str
101124 const { basePath, suffix } = splitUrlSuffix ( urlValue . trim ( ) ) ;
102125 if ( ! basePath ) return full ;
103126 const absolutePath = resolve ( resolvedDir , basePath ) ;
104- const rebased = relative ( resolvedRoot , absolutePath ) ;
127+ const rebased = relative ( resolvedRoot , absolutePath ) . split ( sep ) . join ( "/" ) ;
105128 if ( rebased === basePath ) return full ;
106129 return `url(${ quote || "" } ${ rebased } ${ suffix } ${ quote || "" } )` ;
107130 } ) ;
@@ -113,29 +136,32 @@ function inlineCssFile(
113136 projectDir : string ,
114137 visited : Set < string > = new Set ( ) ,
115138) : string {
116- const placeholders : string [ ] = [ ] ;
117- const withPlaceholders = css . replace (
139+ const { result : strippedCss , restore : restoreComments } = withCommentsStripped ( css , ( s ) => s ) ;
140+ const importPlaceholders : string [ ] = [ ] ;
141+ const withPlaceholders = strippedCss . replace (
118142 CSS_IMPORT_RE ,
119143 ( full , _q1 , urlPath , _q2 , barePath , mediaQuery ) => {
120144 const importPath = urlPath ?? barePath ;
121145 if ( ! importPath || ! isRelativeUrl ( importPath ) ) return full ;
122146 const resolved = resolve ( cssFileDir , importPath ) ;
123147 const normalizedBase = resolve ( projectDir ) + sep ;
124- if ( ! resolved . startsWith ( normalizedBase ) || visited . has ( resolved ) ) return full ;
148+ if ( ! resolved . startsWith ( normalizedBase ) ) return full ;
149+ if ( visited . has ( resolved ) ) return "" ;
125150 const content = safeReadFile ( resolved ) ;
126151 if ( content == null ) return full ;
127152 visited . add ( resolved ) ;
128153 const inlined = inlineCssFile ( content , dirname ( resolved ) , projectDir , visited ) ;
129154 const trimmedMedia = ( mediaQuery || "" ) . trim ( ) ;
130155 const block = trimmedMedia ? `@media ${ trimmedMedia } {\n${ inlined } \n}\n` : inlined + "\n" ;
131- const idx = placeholders . length ;
132- placeholders . push ( block ) ;
156+ const idx = importPlaceholders . length ;
157+ importPlaceholders . push ( block ) ;
133158 return `/*__hf_import_${ idx } __*/` ;
134159 } ,
135160 ) ;
136161 let rebased = rebaseCssUrls ( withPlaceholders , cssFileDir , projectDir ) ;
137- for ( let i = 0 ; i < placeholders . length ; i ++ ) {
138- rebased = rebased . replace ( `/*__hf_import_${ i } __*/` , placeholders [ i ] ! ) ;
162+ rebased = restoreComments ( rebased ) ;
163+ for ( let i = 0 ; i < importPlaceholders . length ; i ++ ) {
164+ rebased = rebased . replace ( `/*__hf_import_${ i } __*/` , importPlaceholders [ i ] ! ) ;
139165 }
140166 return rebased ;
141167}
0 commit comments