@@ -20,7 +20,7 @@ class StaticValueReplacePattern {
2020}
2121
2222/**
23- * Assigned when the replace pattern has replacemend patterns.
23+ * Assigned when the replace pattern has replacement patterns.
2424 */
2525class DynamicPiecesReplacePattern {
2626 public readonly kind = ReplacePatternKind . DynamicPieces ;
@@ -68,7 +68,38 @@ export class ReplacePattern {
6868 }
6969
7070 // match index ReplacePiece
71- result += ReplacePattern . _substitute ( piece . matchIndex , matches ) ;
71+ let match : string = ReplacePattern . _substitute ( piece . matchIndex , matches ) ;
72+ if ( piece . caseOps !== null && piece . caseOps . length > 0 ) {
73+ let repl : string [ ] = [ ] ;
74+ let lenOps : number = piece . caseOps . length ;
75+ let opIdx : number = 0 ;
76+ for ( let idx : number = 0 , len : number = match . length ; idx < len ; idx ++ ) {
77+ if ( opIdx >= lenOps ) {
78+ repl . push ( match . slice ( idx ) ) ;
79+ break ;
80+ }
81+ switch ( piece . caseOps [ opIdx ] ) {
82+ case 'U' :
83+ repl . push ( match [ idx ] . toUpperCase ( ) ) ;
84+ break ;
85+ case 'u' :
86+ repl . push ( match [ idx ] . toUpperCase ( ) ) ;
87+ opIdx ++ ;
88+ break ;
89+ case 'L' :
90+ repl . push ( match [ idx ] . toLowerCase ( ) ) ;
91+ break ;
92+ case 'l' :
93+ repl . push ( match [ idx ] . toLowerCase ( ) ) ;
94+ opIdx ++ ;
95+ break ;
96+ default :
97+ repl . push ( match [ idx ] ) ;
98+ }
99+ }
100+ match = repl . join ( '' ) ;
101+ }
102+ result += match ;
72103 }
73104
74105 return result ;
@@ -102,19 +133,29 @@ export class ReplacePattern {
102133export class ReplacePiece {
103134
104135 public static staticValue ( value : string ) : ReplacePiece {
105- return new ReplacePiece ( value , - 1 ) ;
136+ return new ReplacePiece ( value , - 1 , null ) ;
106137 }
107138
108139 public static matchIndex ( index : number ) : ReplacePiece {
109- return new ReplacePiece ( null , index ) ;
140+ return new ReplacePiece ( null , index , null ) ;
141+ }
142+
143+ public static caseOps ( index : number , caseOps : string [ ] ) : ReplacePiece {
144+ return new ReplacePiece ( null , index , caseOps ) ;
110145 }
111146
112147 public readonly staticValue : string | null ;
113148 public readonly matchIndex : number ;
149+ public readonly caseOps : string [ ] | null ;
114150
115- private constructor ( staticValue : string | null , matchIndex : number ) {
151+ private constructor ( staticValue : string | null , matchIndex : number , caseOps : string [ ] | null ) {
116152 this . staticValue = staticValue ;
117153 this . matchIndex = matchIndex ;
154+ if ( ! caseOps || caseOps . length === 0 ) {
155+ this . caseOps = null ;
156+ } else {
157+ this . caseOps = caseOps . slice ( 0 ) ;
158+ }
118159 }
119160}
120161
@@ -151,12 +192,12 @@ class ReplacePieceBuilder {
151192 this . _currentStaticPiece += value ;
152193 }
153194
154- public emitMatchIndex ( index : number , toCharIndex : number ) : void {
195+ public emitMatchIndex ( index : number , toCharIndex : number , caseOps : string [ ] ) : void {
155196 if ( this . _currentStaticPiece . length !== 0 ) {
156197 this . _result [ this . _resultLen ++ ] = ReplacePiece . staticValue ( this . _currentStaticPiece ) ;
157198 this . _currentStaticPiece = '' ;
158199 }
159- this . _result [ this . _resultLen ++ ] = ReplacePiece . matchIndex ( index ) ;
200+ this . _result [ this . _resultLen ++ ] = ReplacePiece . caseOps ( index , caseOps ) ;
160201 this . _lastCharIndex = toCharIndex ;
161202 }
162203
@@ -175,6 +216,10 @@ class ReplacePieceBuilder {
175216 * \n => inserts a LF
176217 * \t => inserts a TAB
177218 * \\ => inserts a "\".
219+ * \u => upper-cases one character in a match.
220+ * \U => upper-cases ALL remaining characters in a match.
221+ * \l => lower-cases one character in a match.
222+ * \L => lower-cases ALL remaining characters in a match.
178223 * $$ => inserts a "$".
179224 * $& and $0 => inserts the matched substring.
180225 * $n => Where n is a non-negative integer lesser than 100, inserts the nth parenthesized submatch string
@@ -187,6 +232,7 @@ export function parseReplaceString(replaceString: string): ReplacePattern {
187232 return new ReplacePattern ( null ) ;
188233 }
189234
235+ let caseOps : string [ ] = [ ] ;
190236 let result = new ReplacePieceBuilder ( replaceString ) ;
191237
192238 for ( let i = 0 , len = replaceString . length ; i < len ; i ++ ) {
@@ -221,6 +267,20 @@ export function parseReplaceString(replaceString: string): ReplacePattern {
221267 result . emitUnchanged ( i - 1 ) ;
222268 result . emitStatic ( '\t' , i + 1 ) ;
223269 break ;
270+ // Case modification of string replacements, patterned after Boost, but only applied
271+ // to the replacement text, not subsequent content.
272+ case CharCode . u :
273+ // \u => upper-cases one character.
274+ case CharCode . U :
275+ // \U => upper-cases ALL following characters.
276+ case CharCode . l :
277+ // \l => lower-cases one character.
278+ case CharCode . L :
279+ // \L => lower-cases ALL following characters.
280+ result . emitUnchanged ( i - 1 ) ;
281+ result . emitStatic ( '' , i + 1 ) ;
282+ caseOps . push ( String . fromCharCode ( nextChCode ) ) ;
283+ break ;
224284 }
225285
226286 continue ;
@@ -248,7 +308,8 @@ export function parseReplaceString(replaceString: string): ReplacePattern {
248308 if ( nextChCode === CharCode . Digit0 || nextChCode === CharCode . Ampersand ) {
249309 // $& and $0 => inserts the matched substring.
250310 result . emitUnchanged ( i - 1 ) ;
251- result . emitMatchIndex ( 0 , i + 1 ) ;
311+ result . emitMatchIndex ( 0 , i + 1 , caseOps ) ;
312+ caseOps . length = 0 ;
252313 continue ;
253314 }
254315
@@ -268,13 +329,15 @@ export function parseReplaceString(replaceString: string): ReplacePattern {
268329 matchIndex = matchIndex * 10 + ( nextNextChCode - CharCode . Digit0 ) ;
269330
270331 result . emitUnchanged ( i - 2 ) ;
271- result . emitMatchIndex ( matchIndex , i + 1 ) ;
332+ result . emitMatchIndex ( matchIndex , i + 1 , caseOps ) ;
333+ caseOps . length = 0 ;
272334 continue ;
273335 }
274336 }
275337
276338 result . emitUnchanged ( i - 1 ) ;
277- result . emitMatchIndex ( matchIndex , i + 1 ) ;
339+ result . emitMatchIndex ( matchIndex , i + 1 , caseOps ) ;
340+ caseOps . length = 0 ;
278341 continue ;
279342 }
280343 }
0 commit comments