1
- import { type EncoderNode , EncoderPrecedence } from '../encoder/types' ;
1
+ import type { EncodeOutput } from '../encoder/types' ;
2
2
import { escapeText } from '../utils/text' ;
3
- import type { CharacterClass } from './types' ;
3
+
4
+ export interface CharacterClass {
5
+ type : 'characterClass' ;
6
+ characters : string [ ] ;
7
+ ranges : CharacterRange [ ] ;
8
+ isInverted : boolean ;
9
+ encode : ( ) => EncodeOutput ;
10
+ }
11
+
12
+ /**
13
+ * Character range from start to end (inclusive).
14
+ */
15
+ export interface CharacterRange {
16
+ start : string ;
17
+ end : string ;
18
+ }
4
19
5
20
export const any : CharacterClass = {
6
21
type : 'characterClass' ,
7
22
characters : [ '.' ] ,
8
23
ranges : [ ] ,
9
24
isInverted : false ,
25
+ encode : encodeCharacterClass ,
10
26
} ;
11
27
12
28
export const digit : CharacterClass = {
13
29
type : 'characterClass' ,
14
30
characters : [ '\\d' ] ,
15
31
ranges : [ ] ,
16
32
isInverted : false ,
33
+ encode : encodeCharacterClass ,
17
34
} ;
18
35
19
36
export const word : CharacterClass = {
20
37
type : 'characterClass' ,
21
38
characters : [ '\\w' ] ,
22
39
ranges : [ ] ,
23
40
isInverted : false ,
41
+ encode : encodeCharacterClass ,
24
42
} ;
25
43
26
44
export const whitespace : CharacterClass = {
27
45
type : 'characterClass' ,
28
46
characters : [ '\\s' ] ,
29
47
ranges : [ ] ,
30
48
isInverted : false ,
49
+ encode : encodeCharacterClass ,
31
50
} ;
32
51
33
52
export function characterClass ( ...elements : CharacterClass [ ] ) : CharacterClass {
@@ -44,6 +63,7 @@ export function characterClass(...elements: CharacterClass[]): CharacterClass {
44
63
characters : elements . map ( ( c ) => c . characters ) . flat ( ) ,
45
64
ranges : elements . map ( ( c ) => c . ranges ) . flat ( ) ,
46
65
isInverted : false ,
66
+ encode : encodeCharacterClass ,
47
67
} ;
48
68
}
49
69
@@ -61,7 +81,7 @@ export function characterRange(start: string, end: string): CharacterClass {
61
81
}
62
82
63
83
if ( start > end ) {
64
- throw new Error ( '`start` should be less or equal to `end`' ) ;
84
+ throw new Error ( '`start` should be before or equal to `end`' ) ;
65
85
}
66
86
67
87
const range = {
@@ -74,6 +94,7 @@ export function characterRange(start: string, end: string): CharacterClass {
74
94
characters : [ ] ,
75
95
ranges : [ range ] ,
76
96
isInverted : false ,
97
+ encode : encodeCharacterClass ,
77
98
} ;
78
99
}
79
100
@@ -88,53 +109,51 @@ export function anyOf(characters: string): CharacterClass {
88
109
characters : charactersArray ,
89
110
ranges : [ ] ,
90
111
isInverted : false ,
112
+ encode : encodeCharacterClass ,
91
113
} ;
92
114
}
93
115
94
- export function inverted ( {
95
- characters,
96
- ranges,
97
- isInverted,
98
- } : CharacterClass ) : CharacterClass {
116
+ export function inverted ( element : CharacterClass ) : CharacterClass {
99
117
return {
100
118
type : 'characterClass' ,
101
- characters : characters ,
102
- ranges : ranges ,
103
- isInverted : ! isInverted ,
119
+ characters : element . characters ,
120
+ ranges : element . ranges ,
121
+ isInverted : ! element . isInverted ,
122
+ encode : encodeCharacterClass ,
104
123
} ;
105
124
}
106
125
107
- export function encodeCharacterClass ( {
108
- characters,
109
- ranges,
110
- isInverted,
111
- } : CharacterClass ) : EncoderNode {
112
- if ( characters . length === 0 && ranges . length === 0 ) {
126
+ function encodeCharacterClass ( this : CharacterClass ) : EncodeOutput {
127
+ if ( this . characters . length === 0 && this . ranges . length === 0 ) {
113
128
throw new Error (
114
129
'Character class should contain at least one character or character range'
115
130
) ;
116
131
}
117
132
118
133
// Direct rendering for single-character class
119
- if ( characters . length === 1 && ranges ?. length === 0 && ! isInverted ) {
134
+ if (
135
+ this . characters . length === 1 &&
136
+ this . ranges ?. length === 0 &&
137
+ ! this . isInverted
138
+ ) {
120
139
return {
121
- precedence : EncoderPrecedence . Atom ,
122
- pattern : characters [ 0 ] ! ,
140
+ precedence : 'atom' ,
141
+ pattern : this . characters [ 0 ] ! ,
123
142
} ;
124
143
}
125
144
126
145
// If passed characters includes hyphen (`-`) it need to be moved to
127
146
// first (or last) place in order to treat it as hyphen character and not a range.
128
147
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Character_classes#types
129
- const hyphenString = characters . includes ( '-' ) ? '-' : '' ;
130
- const charactersString = characters . filter ( ( c ) => c !== '-' ) . join ( '' ) ;
131
- const rangesString = ranges
148
+ const hyphen = this . characters . includes ( '-' ) ? '-' : '' ;
149
+ const otherCharacters = this . characters . filter ( ( c ) => c !== '-' ) . join ( '' ) ;
150
+ const ranges = this . ranges
132
151
. map ( ( { start, end } ) => `${ start } -${ end } ` )
133
152
. join ( '' ) ;
134
- const invertedString = isInverted ? '^' : '' ;
153
+ const isInverted = this . isInverted ? '^' : '' ;
135
154
136
155
return {
137
- precedence : EncoderPrecedence . Atom ,
138
- pattern : `[${ invertedString } ${ hyphenString } ${ rangesString } ${ charactersString } ]` ,
156
+ precedence : 'atom' ,
157
+ pattern : `[${ isInverted } ${ hyphen } ${ ranges } ${ otherCharacters } ]` ,
139
158
} ;
140
159
}
0 commit comments