@@ -137,6 +137,10 @@ export interface ParseOptions {
137137 * List of characters to automatically consider prefixes when parsing.
138138 */
139139 prefixes ?: string ;
140+ /**
141+ * Function for encoding input strings for output into path.
142+ */
143+ encode ?: Encode ;
140144}
141145
142146class Iter {
@@ -178,11 +182,15 @@ class Iter {
178182 * Parse a string for the raw tokens.
179183 */
180184export function parse ( str : string , options : ParseOptions = { } ) : Token [ ] {
181- const { prefixes = DEFAULT_PREFIXES , delimiter = DEFAULT_DELIMITER } =
182- options ;
183- const defaultPattern = `[^${ escapeString ( delimiter ) } ]+?` ;
185+ const {
186+ prefixes = DEFAULT_PREFIXES ,
187+ delimiter = DEFAULT_DELIMITER ,
188+ encode = DEFAULT_ENCODE ,
189+ } = options ;
190+ const defaultPattern = `[^${ escape ( delimiter ) } ]+?` ;
184191 const result : Token [ ] = [ ] ;
185192 const tokens = lexer ( str ) ;
193+ const stringify = encoder ( delimiter , encode ) ;
186194 let key = 0 ;
187195 let path = "" ;
188196
@@ -207,7 +215,7 @@ export function parse(str: string, options: ParseOptions = {}): Token[] {
207215
208216 result . push ( {
209217 name : name || key ++ ,
210- prefix,
218+ prefix : stringify ( prefix ) ,
211219 suffix : "" ,
212220 pattern : pattern || defaultPattern ,
213221 modifier : modifier || "" ,
@@ -222,7 +230,7 @@ export function parse(str: string, options: ParseOptions = {}): Token[] {
222230 }
223231
224232 if ( path ) {
225- result . push ( path ) ;
233+ result . push ( stringify ( path ) ) ;
226234 path = "" ;
227235 }
228236
@@ -238,8 +246,8 @@ export function parse(str: string, options: ParseOptions = {}): Token[] {
238246 result . push ( {
239247 name : name || ( pattern ? key ++ : "" ) ,
240248 pattern : name && ! pattern ? defaultPattern : pattern ,
241- prefix,
242- suffix,
249+ prefix : stringify ( prefix ) ,
250+ suffix : stringify ( suffix ) ,
243251 modifier : tokens . tryConsume ( "MODIFIER" ) || "" ,
244252 } ) ;
245253 continue ;
@@ -252,19 +260,21 @@ export function parse(str: string, options: ParseOptions = {}): Token[] {
252260 return result ;
253261}
254262
263+ export type Encode = ( value : string ) => string ;
264+
255265export interface TokensToFunctionOptions {
256266 /**
257267 * When `true` the regexp will be case sensitive. (default: `false`)
258268 */
259269 sensitive ?: boolean ;
260- /**
261- * Function for encoding input strings for output.
262- */
263- encode ?: ( value : string , token : Key ) => string ;
264270 /**
265271 * When `false` the function can produce an invalid (unmatched) path. (default: `true`)
266272 */
267273 validate ?: boolean ;
274+ /**
275+ * Function for encoding input strings for output.
276+ */
277+ encode ?: Encode ;
268278}
269279
270280/**
@@ -325,7 +335,7 @@ export function tokensToFunction<P extends object = object>(
325335 }
326336
327337 for ( let j = 0 ; j < value . length ; j ++ ) {
328- const segment = encode ( value [ j ] , token ) ;
338+ const segment = encode ( value [ j ] ) ;
329339
330340 if ( validate && ! ( matches [ i ] as RegExp ) . test ( segment ) ) {
331341 throw new TypeError (
@@ -340,7 +350,7 @@ export function tokensToFunction<P extends object = object>(
340350 }
341351
342352 if ( typeof value === "string" || typeof value === "number" ) {
343- const segment = encode ( String ( value ) , token ) ;
353+ const segment = encode ( String ( value ) ) ;
344354
345355 if ( validate && ! ( matches [ i ] as RegExp ) . test ( segment ) ) {
346356 throw new TypeError (
@@ -440,10 +450,18 @@ export function regexpToFunction<P extends object = object>(
440450/**
441451 * Escape a regular expression string.
442452 */
443- function escapeString ( str : string ) {
453+ function escape ( str : string ) {
444454 return str . replace ( / ( [ . + * ? = ^ ! : $ { } ( ) [ \] | / \\ ] ) / g, "\\$1" ) ;
445455}
446456
457+ /**
458+ * Encode all non-delimiter characters using the encode function.
459+ */
460+ function encoder ( delimiter : string , encode : Encode ) {
461+ const re = new RegExp ( `[^${ escape ( delimiter ) } ]+` , "g" ) ;
462+ return ( value : string ) => value . replace ( re , encode ) ;
463+ }
464+
447465/**
448466 * Get the flags for a regexp from the options.
449467 */
@@ -538,10 +556,6 @@ export interface TokensToRegexpOptions {
538556 * List of characters that can also be "end" characters.
539557 */
540558 endsWith ?: string ;
541- /**
542- * Encode path tokens for use in the `RegExp`.
543- */
544- encode ?: ( value : string ) => string ;
545559}
546560
547561/**
@@ -556,21 +570,20 @@ export function tokensToRegexp(
556570 strict = false ,
557571 start = true ,
558572 end = true ,
559- encode = DEFAULT_ENCODE ,
560573 delimiter = DEFAULT_DELIMITER ,
561574 endsWith = "" ,
562575 } = options ;
563- const endsWithRe = `[${ escapeString ( endsWith ) } ]|$` ;
564- const delimiterRe = `[${ escapeString ( delimiter ) } ]` ;
576+ const endsWithRe = `[${ escape ( endsWith ) } ]|$` ;
577+ const delimiterRe = `[${ escape ( delimiter ) } ]` ;
565578 let route = start ? "^" : "" ;
566579
567580 // Iterate over the tokens and create our regexp string.
568581 for ( const token of tokens ) {
569582 if ( typeof token === "string" ) {
570- route += escapeString ( encode ( token ) ) ;
583+ route += escape ( token ) ;
571584 } else {
572- const prefix = escapeString ( encode ( token . prefix ) ) ;
573- const suffix = escapeString ( encode ( token . suffix ) ) ;
585+ const prefix = escape ( token . prefix ) ;
586+ const suffix = escape ( token . suffix ) ;
574587
575588 if ( token . pattern ) {
576589 if ( keys ) keys . push ( token ) ;
0 commit comments