@@ -139,25 +139,32 @@ export function fixedCharCensorStrategy(char: string): TextCensorStrategy {
139
139
140
140
/**
141
141
* A text censoring strategy that generates replacement strings made up of
142
- * random characters from the set of characters provided.
142
+ * random characters from the set of characters provided. The strings never
143
+ * contain two of the same character in a row.
143
144
*
144
145
* @example
145
146
* ```typescript
146
147
* const strategy = randomCharFromSetCensorStrategy('$#!');
147
148
* const censor = new TextCensor().setStrategy(strategy);
148
149
* // Before: 'fuck you!'
149
- * // After: '!##$ you!'
150
+ * // After: '!#$# you!'
150
151
* ```
151
152
* @param charset - Set of characters from which the replacement string should
152
- * be constructed. Must not be empty .
153
+ * be constructed. Must have at least two characters .
153
154
* @returns A [[TextCensorStrategy]] for use with the [[TextCensor]].
154
155
*/
155
156
export function randomCharFromSetCensorStrategy ( charset : string ) : TextCensorStrategy {
156
157
const chars = [ ...charset ] ;
157
- if ( chars . length === 0 ) throw new Error ( 'The character set passed must not be empty .' ) ;
158
+ if ( chars . length < 2 ) throw new Error ( 'The character set passed must have at least 2 characters .' ) ;
158
159
return ( ctx : CensorContext ) => {
159
160
let censored = '' ;
160
- for ( let i = 0 ; i < ctx . matchLength ; i ++ ) censored += chars [ Math . floor ( Math . random ( ) * chars . length ) ] ;
161
+ let prev = chars . length ;
162
+ for ( let i = 0 ; i < ctx . matchLength ; i ++ ) {
163
+ let idx = Math . floor ( Math . random ( ) * ( i ? chars . length - 1 : chars . length ) ) ;
164
+ if ( idx >= prev ) idx ++ ;
165
+ prev = idx ;
166
+ censored += chars [ idx ] ;
167
+ }
161
168
return censored ;
162
169
} ;
163
170
}
0 commit comments