@@ -66,61 +66,10 @@ protected override void Write(HtmlRenderer renderer, SubstitutionLeaf leaf)
6666 return ;
6767 }
6868
69- foreach ( var mutation in leaf . Mutations )
70- {
71- var ( success , update ) = mutation switch
72- {
73- SubstitutionMutation . MajorComponent => TryGetVersion ( replacement , v => $ "{ v . Major } ") ,
74- SubstitutionMutation . MajorX => TryGetVersion ( replacement , v => $ "{ v . Major } .x") ,
75- SubstitutionMutation . MajorMinor => TryGetVersion ( replacement , v => $ "{ v . Major } .{ v . Minor } ") ,
76- SubstitutionMutation . IncreaseMajor => TryGetVersion ( replacement , v => $ "{ v . Major + 1 } .0.0") ,
77- SubstitutionMutation . IncreaseMinor => TryGetVersion ( replacement , v => $ "{ v . Major } .{ v . Minor + 1 } .0") ,
78- SubstitutionMutation . LowerCase => ( true , replacement . ToLowerInvariant ( ) ) ,
79- SubstitutionMutation . UpperCase => ( true , replacement . ToUpperInvariant ( ) ) ,
80- SubstitutionMutation . Capitalize => ( true , Capitalize ( replacement ) ) ,
81- SubstitutionMutation . KebabCase => ( true , ToKebabCase ( replacement ) ) ,
82- SubstitutionMutation . CamelCase => ( true , ToCamelCase ( replacement ) ) ,
83- SubstitutionMutation . PascalCase => ( true , ToPascalCase ( replacement ) ) ,
84- SubstitutionMutation . SnakeCase => ( true , ToSnakeCase ( replacement ) ) ,
85- SubstitutionMutation . TitleCase => ( true , TitleCase ( replacement ) ) ,
86- SubstitutionMutation . Trim => ( true , Trim ( replacement ) ) ,
87- _ => throw new Exception ( $ "encountered an unknown mutation '{ mutation . ToStringFast ( true ) } '")
88- } ;
89- if ( ! success )
90- {
91- _ = renderer . Write ( leaf . Content ) ;
92- return ;
93- }
94- replacement = update ;
95- }
69+ // Apply mutations using shared utility
70+ replacement = SubstitutionMutationHelper . ApplyMutations ( replacement , leaf . Mutations ) ;
9671 _ = renderer . Write ( replacement ) ;
9772 }
98-
99- private static string ToCamelCase ( string str ) => JsonNamingPolicy . CamelCase . ConvertName ( str . Replace ( " " , string . Empty ) ) ;
100- private static string ToSnakeCase ( string str ) => JsonNamingPolicy . SnakeCaseLower . ConvertName ( str ) . Replace ( " " , string . Empty ) ;
101- private static string ToKebabCase ( string str ) => JsonNamingPolicy . KebabCaseLower . ConvertName ( str ) . Replace ( " " , string . Empty ) ;
102- private static string ToPascalCase ( string str ) => TitleCase ( str ) . Replace ( " " , string . Empty ) ;
103-
104- private static string TitleCase ( string str ) => CultureInfo . InvariantCulture . TextInfo . ToTitleCase ( str ) ;
105-
106- private static string Trim ( string str ) =>
107- str . AsSpan ( ) . Trim ( [ '!' , ' ' , '\t ' , '\r ' , '\n ' , '.' , ',' , ')' , '(' , ':' , ';' , '<' , '>' , '[' , ']' ] ) . ToString ( ) ;
108-
109- private static string Capitalize ( string input ) =>
110- input switch
111- {
112- null => string . Empty ,
113- "" => string . Empty ,
114- _ => string . Concat ( input [ 0 ] . ToString ( ) . ToUpper ( ) , input . AsSpan ( 1 ) )
115- } ;
116-
117- private ( bool , string ) TryGetVersion ( string version , Func < SemVersion , string > mutate )
118- {
119- if ( ! SemVersion . TryParse ( version , out var v ) && ! SemVersion . TryParse ( version + ".0" , out v ) )
120- return ( false , string . Empty ) ;
121-
122- return ( true , mutate ( v ) ) ;
123- }
12473}
12574
12675public class SubstitutionParser : InlineParser
@@ -177,12 +126,12 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
177126 startPosition -= openSticks ;
178127 startPosition = Math . Max ( startPosition , 0 ) ;
179128
180- var key = content . ToString ( ) . Trim ( [ '{' , '}' ] ) . Trim ( ) . ToLowerInvariant ( ) ;
129+ var rawKey = content . ToString ( ) . Trim ( [ '{' , '}' ] ) . Trim ( ) . ToLowerInvariant ( ) ;
181130 var found = false ;
182131 var replacement = string . Empty ;
183- var components = key . Split ( '|' ) ;
184- if ( components . Length > 1 )
185- key = components [ 0 ] . Trim ( [ '{' , '}' ] ) . Trim ( ) . ToLowerInvariant ( ) ;
132+
133+ // Use shared mutation parsing logic
134+ var ( key , mutationStrings ) = SubstitutionMutationHelper . ParseKeyWithMutations ( rawKey ) ;
186135
187136 if ( context . Substitutions . TryGetValue ( key , out var value ) )
188137 {
@@ -215,19 +164,21 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
215164 else
216165 {
217166 List < SubstitutionMutation > ? mutations = null ;
218- if ( components . Length >= 10 )
167+ if ( mutationStrings . Length >= 10 )
219168 processor . EmitError ( line + 1 , column + 3 , substitutionLeaf . Span . Length - 3 , $ "Substitution key {{{key}}} defines too many mutations, none will be applied") ;
220- else if ( components . Length > 1 )
169+ else if ( mutationStrings . Length > 0 )
221170 {
222- foreach ( var c in components [ 1 .. ] )
171+ foreach ( var mutationStr in mutationStrings )
223172 {
224- if ( SubstitutionMutationExtensions . TryParse ( c . Trim ( ) , out var mutation , true , true ) )
173+ // Ensure mutation string is properly trimmed and normalized
174+ var trimmedMutation = mutationStr . Trim ( ) ;
175+ if ( SubstitutionMutationExtensions . TryParse ( trimmedMutation , out var mutation , true , true ) )
225176 {
226177 mutations ??= [ ] ;
227178 mutations . Add ( mutation ) ;
228179 }
229180 else
230- processor . EmitError ( line + 1 , column + 3 , substitutionLeaf . Span . Length - 3 , $ "Mutation '{ c } ' on {{{key}}} is undefined") ;
181+ processor . EmitError ( line + 1 , column + 3 , substitutionLeaf . Span . Length - 3 , $ "Mutation '{ trimmedMutation } ' on {{{key}}} is undefined") ;
231182 }
232183 }
233184
0 commit comments