@@ -687,23 +687,10 @@ fn remap_style_names(
687687 } )
688688 . collect ( ) ;
689689
690- // Replace __font_N__ placeholders in style JSON with font-family names
690+ // Replace placeholders in a single pass per style JSON.
691+ // This is needed for font-family references and selectors like `${parent}:hover &`.
691692 for entry in new_styles. values_mut ( ) {
692- for ( placeholder, font_family) in & font_family_map {
693- if entry. json . contains ( placeholder) {
694- entry. json = entry. json . replace ( placeholder, font_family) ;
695- }
696- }
697- }
698-
699- // Replace __style_N__ placeholders in style JSON with variable names
700- // This is needed for selectors that reference other styles like `${parent}:hover &`
701- for entry in new_styles. values_mut ( ) {
702- for ( placeholder, var_name) in & placeholder_to_name {
703- if entry. json . contains ( placeholder) {
704- entry. json = entry. json . replace ( placeholder, var_name) ;
705- }
706- }
693+ replace_placeholders_in_json ( & mut entry. json , & font_family_map, & placeholder_to_name) ;
707694 }
708695
709696 collected. styles = new_styles;
@@ -717,6 +704,45 @@ fn remap_style_names(
717704 collected. themes = new_themes;
718705}
719706
707+ fn replace_placeholders_in_json (
708+ json : & mut String ,
709+ font_family_map : & FxHashMap < & str , & str > ,
710+ placeholder_to_name : & FxHashMap < String , String > ,
711+ ) {
712+ let source = json. as_str ( ) ;
713+ let mut search_start = 0 ;
714+ let mut last_copied = 0 ;
715+ let mut output = None :: < String > ;
716+
717+ while let Some ( relative_start) = source[ search_start..] . find ( "__" ) {
718+ let start = search_start + relative_start;
719+ let Some ( relative_end) = source[ start + 2 ..] . find ( "__" ) else {
720+ break ;
721+ } ;
722+ let end = start + 2 + relative_end + 2 ;
723+ let placeholder = & source[ start..end] ;
724+ let replacement = font_family_map
725+ . get ( placeholder)
726+ . copied ( )
727+ . or_else ( || placeholder_to_name. get ( placeholder) . map ( String :: as_str) ) ;
728+
729+ if let Some ( replacement) = replacement {
730+ let output = output. get_or_insert_with ( || String :: with_capacity ( source. len ( ) ) ) ;
731+ output. push_str ( & source[ last_copied..start] ) ;
732+ output. push_str ( replacement) ;
733+ last_copied = end;
734+ search_start = end;
735+ } else {
736+ search_start = start + 2 ;
737+ }
738+ }
739+
740+ if let Some ( mut output) = output {
741+ output. push_str ( & source[ last_copied..] ) ;
742+ * json = output;
743+ }
744+ }
745+
720746/// Convert TypeScript to JavaScript using Oxc Transformer and replace imports
721747fn preprocess_typescript ( code : & str , package : & str ) -> String {
722748 let allocator = Allocator :: default ( ) ;
0 commit comments