Skip to content

Commit d65ce7b

Browse files
docs: more examples (#49)
1 parent 3c8c4fd commit d65ce7b

18 files changed

+486
-163
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const hexDigit = charClass(
2121
charRange('0', '9'),
2222
);
2323

24-
const hexColor = buildRegExp(
24+
const hexColor = buildRegExp([
2525
startOfString,
2626
optional('#'),
2727
capture(
@@ -31,7 +31,7 @@ const hexColor = buildRegExp(
3131
),
3232
),
3333
endOfString,
34-
);
34+
]);
3535
```
3636

3737
## Installation

docs/Examples.md

Lines changed: 115 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,133 @@
11
# Regex Examples
22

3-
## JavaScript number
3+
## Match hashtags
4+
5+
This regex matches and captures all hashtags in a given string.
6+
7+
```ts
8+
const hashtags = buildRegExp(
9+
[
10+
'#',
11+
capture(oneOrMore(word)),
12+
],
13+
{ global: true },
14+
);
15+
16+
const hashtagMatches = '#hello #world'.matchAll(hashtags);
17+
```
18+
19+
Encoded regex: `/#(\w+)/g`.
20+
21+
See tests: [example-hashtags.ts](../src/__tests__/example-hashtags.ts).
22+
23+
## Hex color validation
24+
25+
This regex validate whether given string is a valid hex color, with 6 or 3 hex digits.
26+
27+
```ts
28+
const hexDigit = charClass(digit, charRange('a', 'f'));
29+
30+
const regex = buildRegExp(
31+
[
32+
startOfString,
33+
optional('#'),
34+
choiceOf(
35+
repeat(hexDigit, 6), // #rrggbb
36+
repeat(hexDigit, 3), // #rgb
37+
),
38+
endOfString,
39+
],
40+
{ ignoreCase: true },
41+
);
42+
```
43+
44+
Encoded regex: `/^#?(?:[a-f\d]{6}|[a-f\d]{3})$/i`.
45+
46+
See tests: [example-hex-color.ts](../src/__tests__/example-hex-color.ts).
47+
48+
## Simple URL validation
49+
50+
This regex validates (in simplified way) whether given string is a URL.
51+
52+
```ts
53+
const protocol = [choiceOf('http', 'https'), '://'];
54+
const domainChars = charClass(charRange('a', 'z'), digit);
55+
const domainCharsHypen = charClass(domainChars, anyOf('-'));
56+
57+
const domainSegment = choiceOf(
58+
domainChars, // single char
59+
[domainChars, zeroOrMore(domainCharsHypen), domainChars], // multi char
60+
);
61+
62+
const regex = buildRegExp([
63+
startOfString,
64+
optional(protocol),
65+
oneOrMore([domainSegment, '.']), // domain segment
66+
charRange('a', 'z'), // TLD first char
67+
oneOrMore(domainChars), // TLD remaining chars
68+
endOfString,
69+
]);
70+
```
71+
72+
Encoded regex: `/^(?:(?:http|https):\/\/)?(?:(?:[a-z\d]|[a-z\d][a-z\d-]*[a-z\d])\.)+[a-z][a-z\d]+$/`.
73+
74+
See tests: [example-url.ts](../src/__tests__/example-url.ts).
75+
76+
## Email address validation
77+
78+
This regex validates whether given string is a properly formatted email address.
79+
80+
```ts
81+
const hostnameChars = charClass(charRange('a', 'z'), digit, anyOf('-.'));
82+
const domainChars = charRange('a', 'z');
83+
84+
const regex = buildRegExp(
85+
[
86+
startOfString,
87+
oneOrMore(usernameChars),
88+
'@',
89+
oneOrMore(hostnameChars),
90+
'.',
91+
repeat(domainChars, { min: 2 }),
92+
endOfString,
93+
],
94+
{ ignoreCase: true },
95+
);
96+
97+
const isValid = regex.test("user@example.com");
98+
```
99+
100+
Encoded regex: `/^[a-z\d._%+-]+@[a-z\d.-]+\.[a-z]{2,}$/i`.
101+
102+
See tests: [example-email.ts](../src/__tests__/example-email.ts).
103+
104+
## JavaScript number validation
105+
106+
This regex validates if given string is a valid JavaScript number.
107+
4108

5109
```ts
6110
const sign = anyOf('+-');
7111
const exponent = [anyOf('eE'), optional(sign), oneOrMore(digit)];
8112

9113
const regex = buildRegExp([
114+
startOfString,
10115
optional(sing),
11116
choiceOf(
12117
[oneOrMore(digit), optional(['.', zeroOrMore(digit)])], // leading digit
13118
['.', oneOrMore(digit)], // leading dot
14119
),
15120
optional(exponent), // exponent
121+
endOfString,
16122
]);
123+
124+
const isValid = regex.test("1.0e+27");
17125
```
18126

127+
Encoded regex: `/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/`.
128+
129+
See tests: [example-js-number.ts](../src/__tests__/example-js-number.ts).
130+
19131
## IPv4 address validation
20132

21133
```ts
@@ -37,9 +149,6 @@ const regex = buildRegExp([
37149
]);
38150
```
39151

40-
This code generates the following regex pattern:
152+
Encoded regex: `/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/`.
41153

42-
```ts
43-
const regex =
44-
/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/;
45-
```
154+
See tests: [example-ipv4.ts](../src/__tests__/example-ipv4.ts).

jest-setup.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
import './test-utils/to-have-pattern';
1+
import './test-utils/to-equal-regex';
22
import './test-utils/to-match-groups';
3+
import './test-utils/to-match-all-groups';
34
import './test-utils/to-match-string';

src/__tests__/example-email.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {
2+
anyOf,
3+
buildRegExp,
4+
charClass,
5+
charRange,
6+
digit,
7+
endOfString,
8+
oneOrMore,
9+
repeat,
10+
startOfString,
11+
} from '../index';
12+
13+
test('example: email validation', () => {
14+
const usernameChars = charClass(charRange('a', 'z'), digit, anyOf('._%+-'));
15+
const hostnameChars = charClass(charRange('a', 'z'), digit, anyOf('-.'));
16+
const domainChars = charRange('a', 'z');
17+
18+
const regex = buildRegExp(
19+
[
20+
startOfString,
21+
oneOrMore(usernameChars),
22+
'@',
23+
oneOrMore(hostnameChars),
24+
'.',
25+
repeat(domainChars, { min: 2 }),
26+
endOfString,
27+
],
28+
{ ignoreCase: true },
29+
);
30+
31+
expect(regex).toMatchString('aaa@gmail.co');
32+
expect(regex).toMatchString('aaa@gmail.com');
33+
expect(regex).toMatchString('Aaa@GMail.Com');
34+
expect(regex).toMatchString('aaa@long.domain.example.com');
35+
36+
expect(regex).not.toMatchString('@');
37+
expect(regex).not.toMatchString('aaa@');
38+
expect(regex).not.toMatchString('a@gmail.c');
39+
expect(regex).not.toMatchString('@gmail.com');
40+
41+
expect(regex).toEqualRegex(/^[a-z\d._%+-]+@[a-z\d.-]+\.[a-z]{2,}$/i);
42+
});

src/__tests__/example-hashtags.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { buildRegExp } from '../builders';
2+
import { capture, oneOrMore, word } from '../index';
3+
4+
test('example: extracting hashtags', () => {
5+
const regex = buildRegExp(
6+
[
7+
'#', // prettier break-line
8+
capture(oneOrMore(word)),
9+
],
10+
{ global: true },
11+
);
12+
13+
expect(regex).toMatchAllGroups('Hello #world!', [['#world', 'world']]);
14+
expect(regex).toMatchAllGroups('#Hello #world!', [
15+
['#Hello', 'Hello'],
16+
['#world', 'world'],
17+
]);
18+
19+
expect(regex).not.toMatchString('aa');
20+
expect(regex).not.toMatchString('#');
21+
expect(regex).not.toMatchString('a# ');
22+
23+
expect(regex).toEqualRegex(/#(\w+)/g);
24+
});

src/__tests__/example-hex-color.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import {
2+
buildRegExp,
3+
charClass,
4+
charRange,
5+
choiceOf,
6+
digit,
7+
endOfString,
8+
optional,
9+
repeat,
10+
startOfString,
11+
} from '../index';
12+
13+
test('example: hex color validation', () => {
14+
const hexDigit = charClass(digit, charRange('a', 'f'));
15+
16+
const regex = buildRegExp(
17+
[
18+
startOfString,
19+
optional('#'),
20+
choiceOf(
21+
repeat(hexDigit, 6), // #rrggbb
22+
repeat(hexDigit, 3), // #rgb
23+
),
24+
endOfString,
25+
],
26+
{ ignoreCase: true },
27+
);
28+
29+
expect(regex).toMatchString('#ffffff');
30+
expect(regex).toMatchString('ffffff');
31+
expect(regex).toMatchString('#eee');
32+
expect(regex).toMatchString('bbb');
33+
expect(regex).toMatchString('#000');
34+
expect(regex).toMatchString('#123456');
35+
expect(regex).toMatchString('123456');
36+
expect(regex).toMatchString('#123');
37+
expect(regex).toMatchString('123');
38+
39+
expect(regex).not.toMatchString('#1');
40+
expect(regex).not.toMatchString('#12');
41+
expect(regex).not.toMatchString('#1234');
42+
expect(regex).not.toMatchString('#12345');
43+
expect(regex).not.toMatchString('#1234567');
44+
45+
expect(regex).toEqualRegex(/^#?(?:[a-f\d]{6}|[a-f\d]{3})$/i);
46+
});

src/__tests__/example-ipv4.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
buildRegExp,
3+
charRange,
4+
choiceOf,
5+
digit,
6+
endOfString,
7+
repeat,
8+
startOfString,
9+
} from '../index';
10+
11+
test('example: IPv4 address validator', () => {
12+
const octet = choiceOf(
13+
[digit],
14+
[charRange('1', '9'), digit],
15+
['1', repeat(digit, 2)],
16+
['2', charRange('0', '4'), digit],
17+
['25', charRange('0', '5')],
18+
);
19+
20+
const regex = buildRegExp([
21+
startOfString, // prettier break-line
22+
repeat([octet, '.'], 3),
23+
octet,
24+
endOfString,
25+
]);
26+
27+
expect(regex).toMatchString('0.0.0.0');
28+
expect(regex).toMatchString('192.168.0.1');
29+
expect(regex).toMatchString('1.99.100.249');
30+
expect(regex).toMatchString('255.255.255.255');
31+
expect(regex).toMatchString('123.45.67.89');
32+
33+
expect(regex).not.toMatchString('0.0.0.');
34+
expect(regex).not.toMatchString('0.0.0.0.');
35+
expect(regex).not.toMatchString('0.-1.0.0');
36+
expect(regex).not.toMatchString('0.1000.0.0');
37+
expect(regex).not.toMatchString('0.0.300.0');
38+
expect(regex).not.toMatchString('255.255.255.256');
39+
40+
expect(regex).toEqualRegex(
41+
/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,
42+
);
43+
});
Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
import {
22
anyOf,
33
buildRegExp,
4-
charRange,
54
choiceOf,
65
digit,
76
endOfString,
87
oneOrMore,
98
optional,
10-
repeat,
119
startOfString,
1210
zeroOrMore,
1311
} from '../index';
@@ -48,39 +46,5 @@ test('example: validate JavaScript number', () => {
4846
expect(regex).not.toMatchString('.1.1');
4947
expect(regex).not.toMatchString('.');
5048

51-
expect(regex).toHavePattern(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/);
52-
});
53-
54-
test('example: IPv4 address validator', () => {
55-
const octet = choiceOf(
56-
[digit],
57-
[charRange('1', '9'), digit],
58-
['1', repeat(digit, 2)],
59-
['2', charRange('0', '4'), digit],
60-
['25', charRange('0', '5')],
61-
);
62-
63-
const regex = buildRegExp([
64-
startOfString, //
65-
repeat([octet, '.'], 3),
66-
octet,
67-
endOfString,
68-
]);
69-
70-
expect(regex).toMatchString('0.0.0.0');
71-
expect(regex).toMatchString('192.168.0.1');
72-
expect(regex).toMatchString('1.99.100.249');
73-
expect(regex).toMatchString('255.255.255.255');
74-
expect(regex).toMatchString('123.45.67.89');
75-
76-
expect(regex).not.toMatchString('0.0.0.');
77-
expect(regex).not.toMatchString('0.0.0.0.');
78-
expect(regex).not.toMatchString('0.-1.0.0');
79-
expect(regex).not.toMatchString('0.1000.0.0');
80-
expect(regex).not.toMatchString('0.0.300.0');
81-
expect(regex).not.toMatchString('255.255.255.256');
82-
83-
expect(regex).toHavePattern(
84-
/^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,
85-
);
49+
expect(regex).toEqualRegex(/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?$/);
8650
});

0 commit comments

Comments
 (0)