1
1
import { exactly } from './inputs'
2
2
import type { GetValue } from './types/escape'
3
3
import type { InputSource } from './types/sources'
4
+ import { IfSingle , wrap } from './wrap'
4
5
5
6
export interface Input < V extends string , G extends string = never > {
6
7
and : {
@@ -29,16 +30,18 @@ export interface Input<V extends string, G extends string = never> {
29
30
notBefore : < I extends InputSource < string > > ( input : I ) => Input < `${V } (?!${GetValue < I > } )`, G >
30
31
times : {
31
32
/** repeat the previous pattern an exact number of times */
32
- < N extends number > ( number : N ) : Input < `(${V } ){${N } }`, G >
33
+ < N extends number > ( number : N ) : IfSingle < V , Input < `${ V } {${ N } }` , G > , Input < ` (${V } ){${N } }`, G > >
33
34
/** specify that the expression can repeat any number of times, _including none_ */
34
- any : ( ) => Input < `(${V } )*`, G >
35
+ any : ( ) => IfSingle < V , Input < `${V } *`, G > , Input < `(${V } )*`, G > >
36
+ /** specify that the expression must occur at least x times */
37
+ atLeast : < N extends number > (
38
+ number : N
39
+ ) => IfSingle < V , Input < `${V } {${N } ,}`, G > , Input < `(${V } ){${N } ,}`, G > >
35
40
/** specify a range of times to repeat the previous pattern */
36
41
between : < Min extends number , Max extends number > (
37
42
min : Min ,
38
43
max : Max
39
- ) => Input < `(${V } ){${Min } ,${Max } }`, G >
40
- /** specify that the expression must occur at least x times */
41
- atLeast : < N extends number > ( number : N ) => Input < `(${V } ){${N } ,}`, G >
44
+ ) => IfSingle < V , Input < `${V } {${Min } ,${Max } }`, G > , Input < `(${V } ){${Min } ,${Max } }`, G > >
42
45
}
43
46
/** this defines the entire input so far as a named capture group. You will get type safety when using the resulting RegExp with `String.match()` */
44
47
as : < K extends string > ( key : K ) => Input < `(?<${K } >${V } )`, G | K >
@@ -48,7 +51,7 @@ export interface Input<V extends string, G extends string = never> {
48
51
lineEnd : ( ) => Input < `${V } $`, G >
49
52
}
50
53
/** this allows you to mark the input so far as optional */
51
- optionally : ( ) => Input < `(${V } )?`, G >
54
+ optionally : ( ) => IfSingle < V , Input < `${ V } ?` , G > , Input < ` (${V } )?`, G > >
52
55
toString : ( ) => string
53
56
}
54
57
@@ -65,12 +68,12 @@ export const createInput = <Value extends string, Groups extends string = never>
65
68
before : input => createInput ( `${ s } (?=${ exactly ( input ) } )` ) ,
66
69
notAfter : input => createInput ( `(?<!${ exactly ( input ) } )${ s } ` ) ,
67
70
notBefore : input => createInput ( `${ s } (?!${ exactly ( input ) } )` ) ,
68
- times : Object . assign ( ( number : number ) => createInput ( `( ${ s } ) {${ number } }` ) , {
69
- any : ( ) => createInput ( `( ${ s } ) *` ) ,
70
- atLeast : ( min : number ) => createInput ( `( ${ s } ) {${ min } ,}` ) ,
71
- between : ( min : number , max : number ) => createInput ( `( ${ s } ) {${ min } ,${ max } }` ) ,
71
+ times : Object . assign ( ( number : number ) => createInput ( `${ wrap ( s ) } {${ number } }` ) as any , {
72
+ any : ( ) => createInput ( `${ wrap ( s ) } *` ) as any ,
73
+ atLeast : ( min : number ) => createInput ( `${ wrap ( s ) } {${ min } ,}` ) as any ,
74
+ between : ( min : number , max : number ) => createInput ( `${ wrap ( s ) } {${ min } ,${ max } }` ) as any ,
72
75
} ) ,
73
- optionally : ( ) => createInput ( `( ${ s } ) ?` ) ,
76
+ optionally : ( ) => createInput ( `${ wrap ( s ) } ?` ) as any ,
74
77
as : key => createInput ( `(?<${ key } >${ s } )` ) ,
75
78
at : {
76
79
lineStart : ( ) => createInput ( `^${ s } ` ) ,
0 commit comments