1
1
import { type EncoderNode , EncoderPrecedence } from '../encoder/types' ;
2
2
import { escapeText } from '../utils' ;
3
- import type { CharacterClass } from './types' ;
3
+ import type { CharacterClass , CharacterRange } from './types' ;
4
4
5
5
export const any : CharacterClass = {
6
6
type : 'characterClass' ,
@@ -22,6 +22,24 @@ export const word: CharacterClass = {
22
22
characters : [ '\\w' ] ,
23
23
} ;
24
24
25
+ export function characterClass (
26
+ ...charactersOrRanges : Array < string | CharacterRange >
27
+ ) : CharacterClass {
28
+ const characters = charactersOrRanges . filter (
29
+ ( c ) => ! Array . isArray ( c )
30
+ ) as string [ ] ;
31
+
32
+ const ranges = charactersOrRanges . filter ( ( c ) =>
33
+ Array . isArray ( c )
34
+ ) as CharacterRange [ ] ;
35
+
36
+ return {
37
+ type : 'characterClass' ,
38
+ characters : characters . map ( ( c ) => escapeText ( c ) ) ,
39
+ ranges : ranges . map ( ( r ) => [ escapeText ( r [ 0 ] ) , escapeText ( r [ 1 ] ) ] ) ,
40
+ } ;
41
+ }
42
+
25
43
export function anyOf ( characters : string ) : CharacterClass {
26
44
const charactersArray = characters . split ( '' ) . map ( escapeText ) ;
27
45
if ( charactersArray . length === 0 ) {
@@ -36,12 +54,15 @@ export function anyOf(characters: string): CharacterClass {
36
54
37
55
export function encodeCharacterClass ( {
38
56
characters,
57
+ ranges = [ ] ,
39
58
} : CharacterClass ) : EncoderNode {
40
- if ( characters . length === 0 ) {
41
- throw new Error ( 'Character class should contain at least one character' ) ;
59
+ if ( characters . length === 0 && ranges . length === 0 ) {
60
+ throw new Error (
61
+ 'Character class should contain at least one range or character'
62
+ ) ;
42
63
}
43
64
44
- if ( characters . length === 1 ) {
65
+ if ( characters . length === 1 && ranges . length === 0 ) {
45
66
return {
46
67
precedence : EncoderPrecedence . Atom ,
47
68
pattern : characters [ 0 ] ! ,
@@ -50,17 +71,22 @@ export function encodeCharacterClass({
50
71
51
72
return {
52
73
precedence : EncoderPrecedence . Atom ,
53
- pattern : `[${ reorderHyphen ( characters ) . join ( '' ) } ]` ,
74
+ pattern : `[${ formatClass ( characters , ranges ) } ]` ,
54
75
} ;
55
76
}
56
77
57
78
// If passed characters includes hyphen (`-`) it need to be moved to
58
79
// first (or last) place in order to treat it as hyphen character and not a range.
59
80
// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Character_classes#types
60
- function reorderHyphen ( characters : string [ ] ) {
81
+ function formatClass ( characters : string [ ] , ranges : CharacterRange [ ] = [ ] ) {
82
+ const formattedCharacters = characters . filter ( ( c ) => c !== '-' ) . join ( '' ) ;
83
+ const formattedRanges = ranges
84
+ . map ( ( [ start , end ] ) => `${ start } -${ end } ` )
85
+ . join ( '' ) ;
86
+
61
87
if ( characters . includes ( '-' ) ) {
62
- return [ '-' , ... characters . filter ( ( c ) => c !== '-' ) ] ;
88
+ return `- ${ formattedRanges } ${ formattedCharacters } ` ;
63
89
}
64
90
65
- return characters ;
91
+ return ` ${ formattedRanges } ${ formattedCharacters } ` ;
66
92
}
0 commit comments