@@ -66,61 +66,10 @@ protected override void Write(HtmlRenderer renderer, SubstitutionLeaf leaf)
66
66
return ;
67
67
}
68
68
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 ) ;
96
71
_ = renderer . Write ( replacement ) ;
97
72
}
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
- }
124
73
}
125
74
126
75
public class SubstitutionParser : InlineParser
@@ -177,12 +126,12 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
177
126
startPosition -= openSticks ;
178
127
startPosition = Math . Max ( startPosition , 0 ) ;
179
128
180
- var key = content . ToString ( ) . Trim ( [ '{' , '}' ] ) . Trim ( ) . ToLowerInvariant ( ) ;
129
+ var rawKey = content . ToString ( ) . Trim ( [ '{' , '}' ] ) . Trim ( ) . ToLowerInvariant ( ) ;
181
130
var found = false ;
182
131
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 ) ;
186
135
187
136
if ( context . Substitutions . TryGetValue ( key , out var value ) )
188
137
{
@@ -215,19 +164,21 @@ public override bool Match(InlineProcessor processor, ref StringSlice slice)
215
164
else
216
165
{
217
166
List < SubstitutionMutation > ? mutations = null ;
218
- if ( components . Length >= 10 )
167
+ if ( mutationStrings . Length >= 10 )
219
168
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 )
221
170
{
222
- foreach ( var c in components [ 1 .. ] )
171
+ foreach ( var mutationStr in mutationStrings )
223
172
{
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 ) )
225
176
{
226
177
mutations ??= [ ] ;
227
178
mutations . Add ( mutation ) ;
228
179
}
229
180
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") ;
231
182
}
232
183
}
233
184
0 commit comments