frontacles 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -8,11 +8,60 @@ Nothing for now.
8
8
 
9
9
  <!-- ⚠️ Before a new release, make sure the documentation doesn't contain any **unreleased** mention. -->
10
10
 
11
- Compare with [last published version](https://github.com/frontacles/frontacles/compare/0.2.2...main).
11
+ <!-- Compare with [last published version](https://github.com/frontacles/frontacles/compare/0.4.0...main). -->
12
+
13
+ ## v0.4.0 (2025-03-08)
14
+
15
+ Compare with [previous version](https://github.com/frontacles/frontacles/compare/0.3.0...0.4.0).
16
+
17
+ ### New
18
+
19
+ - Add [`isEmail`](./README.md#isemail) to validate emails.
20
+
21
+ ### Documentation
22
+
23
+ - It is now more explicit in types that `Email.canParse` expects a `string` or a `Stringable` (changed from `any|Email` to `any|string|Email|Stringable`).
24
+ - Rephrase email documentation.
25
+
26
+ ### Under the hood
27
+
28
+ - Centralize all benchmarks in [`./benchs`](./benchs).
29
+ - Benchmark [`Email`](./benchs/url).
30
+
31
+ ## v0.3.0 (2025-03-06)
32
+
33
+ Compare with [previous version](https://github.com/frontacles/frontacles/compare/0.2.2...0.3.0).
34
+
35
+ ### New
36
+
37
+ #### Math
38
+
39
+ - Add [`clamp`](./README.md#clamp), a function to clamp a number in a given range.
40
+ - Add support for `Infinity` precision to the [`round` function](./README.md#round).
41
+
42
+ #### String
43
+
44
+ - Add [`capitalize`](./README.md#capitalize), a function to put the first letter of a word in uppercase.
45
+
46
+ ### Fixed
47
+
48
+ - `Email` was considering as valid an email without username (e.g. `@domain.tld`). This is now fixed.
49
+
50
+ ### Under the hood
51
+
52
+ - Shorten `round` by a couple of Bytes.
53
+ - Benchmark [`round` implementations](./benchs/math)
54
+ - Add [Valibot test suite](./src/url/test-utils/valibot-suite.js) to `Email` (all tests are passing!).
55
+
56
+ ### Documentation
57
+
58
+ - Gather sizes in the documentation introduction.
59
+ - Group utils by categories (_Math_, _String_, _URL_) to the documentation.
60
+ - Add pull request template.
12
61
 
13
62
  ## v0.2.2 (2025-03-01)
14
63
 
15
- Compare with [last published version](https://github.com/frontacles/frontacles/compare/0.2.1...0.2.2).
64
+ Compare with [previous version](https://github.com/frontacles/frontacles/compare/0.2.1...0.2.2).
16
65
 
17
66
  ### Breaking
18
67
 
@@ -40,7 +89,7 @@ Compare with [previous version](https://github.com/frontacles/frontacles/compare
40
89
 
41
90
  ### New
42
91
 
43
- - Add [`Email`](https://github.com/frontacles/frontacles#email), a class to validate emails the same way browsers do, which is rock solid.
92
+ - Add [`Email`](./README.md#email), a class to validate emails the same way browsers do, which is rock solid.
44
93
 
45
94
  ## v0.1.1 (2021-03-13)
46
95
 
package/README.md CHANGED
@@ -5,42 +5,137 @@ Cool utilities for front-end development (and potentially for Node).
5
5
  > [!WARNING]
6
6
  > Under heavy development. We are only starting!
7
7
 
8
- ## Email
8
+ We love tiny bits (using brotli compression):
9
9
 
10
- A class to instantiate an `Email` object or validate emails. It’s only [221 B compressed](https://bundlejs.com/?q=frontacles&treeshake=[{Email}]&config={%22compression%22%3A%22brotli%22}&bundle).
10
+ | categories | util | size |
11
+ | --- | --- | --- |
12
+ | math | [`clamp`](#clamp) | 35 B |
13
+ | math | [`round`](#round) | 38 B |
14
+ | string | [`capitalize`](#capitalize) | 40 B |
15
+ | url | [`isEmail`](#isemail) | 86 B |
16
+ | url | [`Email`](#email) | 173 B |
17
+ | | **everything** | 328 B |
11
18
 
12
- Unlike most libraries using [RegEx for emails](https://github.com/colinhacks/zod/blob/e2b9a5f9ac67d13ada61cd8e4b1385eb850c7592/src/types.ts#L648-L663) (and prone to [bugs](https://github.com/colinhacks/zod/issues/3913)), Frontacles `Email` class relies on the same mechanism as your browser to validate email addresses, making it robust, and very likely RFC compliant.
19
+ ## Math utils
20
+
21
+ ### `clamp`
22
+
23
+ Clamp a number between two values. A clamped number stays within a specified range. If the number is lower than the minimum, the minimum value is returned. If the number is higher than the maximum, the maximum value is returned.
24
+
25
+ `clamp` needs 3 parameters:
26
+
27
+ 1. `number`: the number to clamp
28
+ 2. `min`: the smallest value your number can have
29
+ 3. `max`: the highest value your number can have
13
30
 
14
31
  ```js
15
- import { Email } from 'frontacles/url/email'
32
+ import { clamp } from 'frontacles/math'
16
33
 
17
- const email = new Email('someone@domain.tld')
34
+ clamp(17, 3, 8) // 8
35
+ clamp(-3, 3, 8) // 3
36
+ clamp(5, 3, 8) // 5
18
37
  ```
19
38
 
20
- Get or set the username and the hostname separately.
39
+ `-0` and `Infinity` are accepted:
21
40
 
22
41
  ```js
23
- email.username // 'someone'
24
- email.hostname // 'domain.tld'
42
+ clamp(-2, -0, 10) // -0
43
+ clamp(5, 0, Infinity) // 5
44
+ clamp(Infinity, 0, 10) // 10
45
+ ```
25
46
 
26
- email.hostname = 'newdomain.tld' // ✅ domain migrated
47
+ > [!NOTE]
48
+ > `clamp` mostly follows [`Math.clamp` TC39 proposal](https://github.com/tc39/proposal-math-clamp), except it doesn’t throw if you flip the order of the _min_ (2nd parameter) and _max_ (3rd parameter) numbers.
27
49
 
28
- // destructuring also works
29
- const { username, hostname } = new Email('someone@domain.tld')
50
+ ### `round`
51
+
52
+ Round a number to the (optionally) provided decimal precision. The default precision is 0 (no decimal).
53
+
54
+ ```js
55
+ import { round } from 'frontacles/math'
56
+
57
+ round(687.3456) // 687
58
+ round(687.3456, 0) // 687
59
+ round(687.3456, 2) // 687.35
30
60
  ```
31
61
 
32
- Turn the email object into a string by using it along another string, or use `toString`.
62
+ A negative precision will round up to multiple of tens:
33
63
 
34
64
  ```js
35
- console.log(`email: ${email}`) // 'email: someone@newdomain.tld'
36
- console.log(email.toString()) // 'someone@newdomain.tld'
65
+ round(687.3456, -1) // 690
66
+ round(687.3456, -2) // 700
37
67
  ```
38
68
 
39
- Validate that a string is a valid email address. It passes the complete Zod test suites, and beyond.
69
+ Using `Infinity` is also possible:
40
70
 
41
71
  ```js
42
- Email.canParse('someone@domain.tld') // true
43
- Email.canParse('invalid@email.com:3000') // false
72
+ round(Infinity, -2) // Infinity
73
+ round(17.853, Infinity // 17.853
74
+ ```
75
+
76
+ ## String utils
77
+
78
+ ### `capitalize`
79
+
80
+ Put the first letter of a word in uppercase. It works for Latin, Greek and Cyrillic alphabets.
81
+
82
+ ```js
83
+ capitalize('jean-roger')) // 'Jean-roger' (Latin)
84
+ capitalize('έρημος')) // 'Έρημος' (Greek)
85
+ capitalize('0 books') // 0 books
86
+ capitalize('صحراء') // 'صحراء' (Arabic)
87
+ ```
88
+
89
+ > [!TIP]
90
+ > Before using `capitalize`, evaluate if [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/::first-letter) could be used instead.
91
+ >
92
+ > ```css
93
+ > .my-class::first-letter {
94
+ > text-transform: uppercase;
95
+ > }
96
+ > ```
97
+
98
+ ## URL utils
99
+
100
+ ### `isEmail`
101
+
102
+ Tells whether a string is a valid email.
103
+
104
+ ```js
105
+ isEmail('someone@domain.tld') // true
106
+ isEmail('invalid@email.com:3000') // false
107
+ ```
108
+
109
+ > [!TIP]
110
+ > Should I use `isEmail` or [`Email.canParse`](#emailcanparse) to validate emails?
111
+ >
112
+ > Short answer: use `isEmail`.
113
+ >
114
+ > <details>
115
+ > <summary>Nuanced answer</summary>
116
+ >
117
+ > Your use case:
118
+ >
119
+ > - If you **only need to validate** email addresses, use `isEmail`.
120
+ > - If you also need to be able to get or set an email username or hostname **independently**, use `Email.canParse`.
121
+ >
122
+ > When using the `Email` class, you can still use `isEmail` if you want ultra-performance (e.g. your Node API validates tons of emails per seconds) because `isEmail` is 6✕ faster, at the cost of a bit less than 100 Bytes (compressed).
123
+ >
124
+ > The reason `isEmail` is faster is that it relies on a single RegExp while `Email.canParse` uses the browser built-in, which results in a bit more of computation, but with less code. For now, it’s not planned to use `isEmail` implementation in `Email.canParse` as it would increase its size by 50 Bytes.
125
+ >
126
+ > Keep in mind that **`Email.canParse` is fast enough** for the 99% use cases. Despite their implementation difference, both behave the same and pass the same tests.
127
+ > </details>
128
+
129
+ ### `Email`
130
+
131
+ A class to instantiate an `Email` object or validate email addresses. It extends the [`URL` object](https://developer.mozilla.org/en-US/docs/Web/API/URL) and has similar predictable behaviors.
132
+
133
+ #### `Email.constructor`
134
+
135
+ ```js
136
+ import { Email } from 'frontacles/url/email'
137
+
138
+ const email = new Email('someone@domain.tld')
44
139
  ```
45
140
 
46
141
  Trying to instantiate an Email with an invalid address will throw. This behaviour is similar to the [`URL` constructor](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL), since `Email` relies on it under the hood.
@@ -49,23 +144,57 @@ Trying to instantiate an Email with an invalid address will throw. This behaviou
49
144
  new Email('double@at@sign.com') // ❌ throw TypeError
50
145
  ```
51
146
 
52
- Another behaviour from the `URL` class: you can pass an `Email` object to the `Email` constructor or to `Email.canParse`.
147
+ Another behaviour from `URL`: passing an `Email` object to the `Email` constructor or to [`Email.canParse`](#emailcanparse) is possible.
53
148
 
54
149
  ```js
55
150
  const email = new Email('someone@domain.tld')
56
-
57
151
  const alsoEmail = new Email(email) // ✅ a new Email object!
58
-
59
152
  Email.canParse(email) // ✅ true
60
153
  ```
61
154
 
155
+ #### `.username` and `.hostname`
156
+
157
+ Get or set the email username and hostname separately.
158
+
159
+ ```js
160
+ email.username // 'someone'
161
+ email.hostname // 'domain.tld'
162
+
163
+ email.hostname = 'newdomain.tld' // ✅ domain migrated
164
+
165
+ // destructuring also works
166
+ const { username, hostname } = new Email('someone@domain.tld')
167
+ ```
168
+
169
+ #### `.toString`
170
+
171
+ In a string context, an `Email` object is automatically converted to a string, or manually by calling the `toString` method.
172
+
173
+ ```js
174
+ console.log(`email: ${email}`) // 'email: someone@newdomain.tld'
175
+ console.log(email.toString()) // 'someone@newdomain.tld'
176
+ ```
177
+
178
+ #### `Email.canParse`
179
+
180
+ Validate an email address with `Email.canParse`.
181
+
182
+ Unlike most libraries using [RegExp to validate a string is an email](https://github.com/colinhacks/zod/blob/e2b9a5f9ac67d13ada61cd8e4b1385eb850c7592/src/types.ts#L648-L663) (which is prone to [bugs](https://github.com/colinhacks/zod/issues/3913)), Frontacles `Email` relies on the built-in `URL` mechanisms, making it robust, and very likely RFC compliant. It passes [popular libraries test suites](./src/url/test-utils), and beyond.
183
+
184
+ ```js
185
+ Email.canParse('someone@domain.tld') // true
186
+ Email.canParse('invalid@email.com:3000') // false
187
+ ```
188
+
189
+ If `canParse` is all you need from the `Email` class, consider using [isEmail](#isemail) instead.
190
+
62
191
  ## Changelog
63
192
 
64
- See [CHANGELOG.md](https://github.com/frontacles/frontacles/blob/main/CHANGELOG.md) or the [releases](https://github.com/frontacles/frontacles/releases).
193
+ See [CHANGELOG.md](./CHANGELOG.md) or the [releases](https://github.com/frontacles/frontacles/releases).
65
194
 
66
195
  ## Browser and tooling support
67
196
 
68
- `frontacles` is provided [as module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#browser_compatibility) for [modern browsers usage](https://github.com/frontacles/frontacles/blob/main/browserslist) with standard JavaScript syntax:
197
+ `frontacles` is provided [as module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#browser_compatibility) for [modern browsers usage](./browserslist) with standard JavaScript syntax:
69
198
  - it is up to you to transpile it for legacy browsers;
70
199
  - you can’t import it using `require('frontacles')`.
71
200
 
@@ -73,12 +202,12 @@ See [CHANGELOG.md](https://github.com/frontacles/frontacles/blob/main/CHANGELOG.
73
202
 
74
203
  ## Security
75
204
 
76
- See the [security policy](https://github.com/frontacles/frontacles/blob/main/SECURITY.md).
205
+ See the [security policy](./SECURITY.md).
77
206
 
78
207
  ## Contributing
79
208
 
80
- See the [contributing guidelines](https://github.com/frontacles/frontacles/blob/main/CONTRIBUTING.md).
209
+ See the [contributing guidelines](./CONTRIBUTING.md).
81
210
 
82
211
  ## License
83
212
 
84
- The _datetime-attribute_ package is open-sourced software licensed under the [DWTFYWTPL](https://github.com/frontacles/frontacles/blob/main/LICENSE).
213
+ The _datetime-attribute_ package is open-sourced software licensed under the [DWTFYWTPL](./LICENSE).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontacles",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "description": "Front-end utilities for artisans",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -25,11 +25,13 @@
25
25
  "build": "echo \"Nothing to build, this command is only here to please size-limit GitHub action\" && exit 0",
26
26
  "size": "size-limit",
27
27
  "lint": "eslint",
28
- "lint-fix": "eslint --fix"
28
+ "lint:fix": "eslint --fix",
29
+ "lint:inspect": "eslint --inspect-config "
29
30
  },
30
31
  "files": [
31
32
  "CHANGELOG.md",
32
33
  "src/**/*.js",
34
+ "!src/**/test-utils",
33
35
  "!src/**/*.test.js",
34
36
  "types/index.d.ts"
35
37
  ],
package/src/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './math/index.js'
2
+ export * from './string/index.js'
2
3
  export * from './url/email.js'
package/src/math/index.js CHANGED
@@ -1,5 +1,23 @@
1
1
  /**
2
- * Round a number to the (optionnally) provided precision.
2
+ * Make sure a number stays between boundaries.
3
+ * Follows {@link https://github.com/tc39/proposal-math-clamp TC39 proposal}.
4
+ *
5
+ * Examples:
6
+ *
7
+ * ```
8
+ * clamp(17, 3, 8) // 8
9
+ * clamp(-3, 3, 8) // 3
10
+ * clamp(5, 3, 8) // 5
11
+ * ```
12
+ *
13
+ * @param {number} val The number you want to maintain inside boundaries.
14
+ * @param {number} min The lowest permitted value.
15
+ * @param {number} max The highest permitted value.
16
+ */
17
+ export const clamp = (val, min, max) => Math.max(min, Math.min(max, val))
18
+
19
+ /**
20
+ * Round a number to the (optionally) provided precision.
3
21
  *
4
22
  * Examples:
5
23
  * - round(687.3456, 2) // 687.35
@@ -11,6 +29,9 @@
11
29
  * @param {number} [precision=0] Rounding precision
12
30
  */
13
31
  export const round = (number, precision = 0) => {
14
- precision = 10 ** precision
15
- return Math.round(number * precision) / precision
32
+
33
+ // Testing precision avoids a crash because `10 ** Infinity` gives `NaN`.
34
+ return precision == Infinity
35
+ ? number
36
+ : Math.round(number * 10 ** precision) / 10 ** precision
16
37
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Capitalize the first letter of a string.
3
+ *
4
+ * Before using it, evaluate if CSS could be use instead
5
+ * (`::first-letter { text-transform: uppercase; }`).
6
+ *
7
+ * Examples:
8
+ * - capitalize('jean-roger') // 'Jean-roger'
9
+ * - capitalize('0 books') // '0 books'
10
+ *
11
+ * @param {string} str
12
+ */
13
+ export const capitalize = str => str[0].toUpperCase() + str.slice(1)
package/src/url/email.js CHANGED
@@ -17,6 +17,9 @@ export class Email extends URL {
17
17
  }
18
18
 
19
19
  /**
20
+ * The email address (`username@domain.tld`) as a string.
21
+ *
22
+ * (maintainer comment)
20
23
  * Replace the string representation of the top-level class (`URL`) to be an
21
24
  * email address instead of `ftp://username@domain.tld`. It is needed for
22
25
  * situation where type casting to string is involved (`console.log`…).
@@ -31,13 +34,14 @@ export class Email extends URL {
31
34
  * @param {string} address
32
35
  */
33
36
  #validate (address) {
34
- return this.toString() == address
37
+ // `username` is tested because `@domain.tld` is valid in a `ftp` context
38
+ return this.toString() == address && this.username
35
39
  }
36
40
 
37
41
  /**
38
42
  * Whether or not an email address is parsable and valid.
39
43
  *
40
- * @param {any|Email} address
44
+ * @param {any|string|Email|Stringable} address
41
45
  */
42
46
  static canParse(address) {
43
47
  try {
@@ -48,3 +52,17 @@ export class Email extends URL {
48
52
  }
49
53
  }
50
54
  }
55
+
56
+ /**
57
+ * Whether or not an email address is parsable and valid.
58
+ *
59
+ * It uses WHATWG recommended RegExp: https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
60
+ *
61
+ * @param {any|string|Stringable} address
62
+ */
63
+ export const isEmail = address => /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(address)
64
+
65
+ /**
66
+ * @typedef {Object} Stringable
67
+ * @property {function(): string} toString - The object as a string.
68
+ */
package/types/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
+ export function clamp(val: number, min: number, max: number): number;
1
2
  export function round(number: number, precision?: number): number;
3
+ export function capitalize(str: string): string;
2
4
  export class Email extends URL {
3
5
  /**
4
6
  * The domain name and extension of the email.
@@ -15,14 +17,21 @@ export class Email extends URL {
15
17
  /**
16
18
  * Whether or not an email address is parsable and valid.
17
19
  *
18
- * @param {any|Email} address
20
+ * @param {any|string|Email|Stringable} address
19
21
  */
20
- static canParse(address: any | Email): boolean;
22
+ static canParse(address: any | string | Email | Stringable): boolean;
21
23
  /**
22
24
  * @param {string|Email} address An email address like `someone@domain.tld`.
23
25
  */
24
26
  constructor(address: string | Email);
25
27
  #private;
26
28
  }
29
+ export function isEmail(address: any | string | Stringable): boolean;
30
+ export type Stringable = {
31
+ /**
32
+ * - The object as a string.
33
+ */
34
+ toString: () => string;
35
+ };
27
36
 
28
37
  export {};
@@ -1,117 +0,0 @@
1
- /* eslint-disable no-useless-escape */
2
- // https://github.com/colinhacks/zod/blob/e2b9a5f9ac67d13ada61cd8e4b1385eb850c7592/src/types.ts#L648-L663
3
- // https://github.com/colinhacks/zod/blob/e2b9a5f9ac67d13ada61cd8e4b1385eb850c7592/deno/lib/__tests__/string.test.ts#L42-L154
4
-
5
- export const validEmailsFromZod = [
6
- `email@domain.com`,
7
- `firstname.lastname@domain.com`,
8
- `email@subdomain.domain.com`,
9
- `firstname+lastname@domain.com`,
10
- `1234567890@domain.com`,
11
- `email@domain-one.com`,
12
- `_______@domain.com`,
13
- `email@domain.name`,
14
- `email@domain.co.jp`,
15
- `firstname-lastname@domain.com`,
16
- `very.common@example.com`,
17
- `disposable.style.email.with+symbol@example.com`,
18
- `other.email-with-hyphen@example.com`,
19
- `fully-qualified-domain@example.com`,
20
- `user.name+tag+sorting@example.com`,
21
- `x@example.com`,
22
- `mojojojo@asdf.example.com`,
23
- `example-indeed@strange-example.com`,
24
- `example@s.example`,
25
- `user-@example.org`,
26
- `user@my-example.com`,
27
- `a@b.cd`,
28
- `work+user@mail.com`,
29
- `tom@test.te-st.com`,
30
- `something@subdomain.domain-with-hyphens.tld`,
31
- `common'name@domain.com`,
32
- `francois@etu.inp-n7.fr`,
33
- ]
34
-
35
- export const invalidEmailsFromZod = [
36
- // no "printable characters"
37
- // `user%example.com@example.org`,
38
- // `mailhost!username@example.org`,
39
- // `test/test@test.com`,
40
-
41
- // double @
42
- `francois@@etu.inp-n7.fr`,
43
- // do not support quotes
44
- `"email"@domain.com`,
45
- `"e asdf sadf ?<>ail"@domain.com`,
46
- `" "@example.org`,
47
- `"john..doe"@example.org`,
48
- `"very.(),:;<>[]\".VERY.\"very@\\ \"very\".unusual"@strange.example.com`,
49
- // do not support comma
50
- `a,b@domain.com`,
51
-
52
- // do not support IPv4
53
- `email@123.123.123.123`,
54
- `email@[123.123.123.123]`,
55
- `postmaster@123.123.123.123`,
56
- `user@[68.185.127.196]`,
57
- `ipv4@[85.129.96.247]`,
58
- `valid@[79.208.229.53]`,
59
- `valid@[255.255.255.255]`,
60
- `valid@[255.0.55.2]`,
61
- `valid@[255.0.55.2]`,
62
-
63
- // do not support ipv6
64
- `hgrebert0@[IPv6:4dc8:ac7:ce79:8878:1290:6098:5c50:1f25]`,
65
- `bshapiro4@[IPv6:3669:c709:e981:4884:59a3:75d1:166b:9ae]`,
66
- `jsmith@[IPv6:2001:db8::1]`,
67
- `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]`,
68
- `postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:192.168.1.1]`,
69
-
70
- // microsoft test cases
71
- `plainaddress`,
72
- `#@%^%#$@#$@#.com`,
73
- `@domain.com`,
74
- `Joe Smith &lt;email@domain.com&gt;`,
75
- `email.domain.com`,
76
- `email@domain@domain.com`,
77
- `.email@domain.com`,
78
- `email.@domain.com`,
79
- `email..email@domain.com`,
80
- `あいうえお@domain.com`,
81
- `email@domain.com (Joe Smith)`,
82
- `email@domain`,
83
- `email@-domain.com`,
84
- `email@111.222.333.44444`,
85
- `email@domain..com`,
86
- `Abc.example.com`,
87
- `A@b@c@example.com`,
88
- `colin..hacks@domain.com`,
89
- `a"b(c)d,e:f;g<h>i[j\k]l@example.com`,
90
- `just"not"right@example.com`,
91
- `this is"not\allowed@example.com`,
92
- `this\ still\"not\\allowed@example.com`,
93
-
94
- // random
95
- `i_like_underscore@but_its_not_allowed_in_this_part.example.com`,
96
- `QA[icon]CHOCOLATE[icon]@test.com`,
97
- `invalid@-start.com`,
98
- `invalid@end.com-`,
99
- `a.b@c.d`,
100
- `invalid@[1.1.1.-1]`,
101
- `invalid@[68.185.127.196.55]`,
102
- `temp@[192.168.1]`,
103
- `temp@[9.18.122.]`,
104
- `double..point@test.com`,
105
- `asdad@test..com`,
106
- `asdad@hghg...sd...au`,
107
- `asdad@hghg........au`,
108
- `invalid@[256.2.2.48]`,
109
- `invalid@[256.2.2.48]`,
110
- `invalid@[999.465.265.1]`,
111
- `jkibbey4@[IPv6:82c4:19a8::70a9:2aac:557::ea69:d985:28d]`,
112
- `mlivesay3@[9952:143f:b4df:2179:49a1:5e82:b92e:6b6]`,
113
- `gbacher0@[IPv6:bc37:4d3f:5048:2e26:37cc:248e:df8e:2f7f:af]`,
114
- `invalid@[IPv6:5348:4ed3:5d38:67fb:e9b:acd2:c13:192.168.256.1]`,
115
- `test@.com`,
116
- `aaaaaaaaaaaaaaalongemailthatcausesregexDoSvulnerability@test.c`,
117
- ]