Skip to content

Commit be41aa6

Browse files
committed
feat: add option to not use re2 (per spamscanner/url-regex-safe#28), bump deps, modernize config
1 parent 1293f72 commit be41aa6

File tree

7 files changed

+58
-60
lines changed

7 files changed

+58
-60
lines changed

.commitlintrc.json

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ jobs:
1010
os:
1111
- ubuntu-latest
1212
node_version:
13-
- 14
1413
- 16
1514
- 18
1615
name: Node ${{ matrix.node_version }} on ${{ matrix.os }}

.prettierrc

Lines changed: 0 additions & 5 deletions
This file was deleted.

.remarkrc

Lines changed: 0 additions & 5 deletions
This file was deleted.

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
[![license](https://img.shields.io/github/license/spamscanner/email-regex-safe.svg)](LICENSE)
88
[![npm downloads](https://img.shields.io/npm/dt/email-regex-safe.svg)](https://npm.im/email-regex-safe)
99

10-
> Regular expression matching for email addresses. Maintained, configurable, more accurate, and browser-friendly alternative to [email-regex][]. Works in Node v14+ and browsers. **Made for [Spam Scanner][spam-scanner] and [Forward Email][forward-email]**
10+
> Regular expression matching for email addresses. Maintained, configurable, more accurate, and browser-friendly alternative to [email-regex][]. Works in Node v14+ and browsers. **Maintained for [Spam Scanner][spam-scanner] and [Forward Email][forward-email]**.
1111
1212

1313
## Table of Contents
@@ -35,12 +35,12 @@ This package should hopefully more closely resemble real-world intended usage of
3535

3636
## Install
3737

38-
**NOTE:** As of v2.0.0 you must also install `re2` as a peer dependency. As of v3.0.0 `re2` is optional and it will default to using `RegExp`.
38+
**NOTE:** The default behavior of this package will attempt to load [re2](https://github.com/uhop/node-re2) (it is an optional peer dependency used to prevent regular expression denial of service attacks and more). If you wish to use this behavior, you must have `re2` installed via `npm install re2` – otherwise it will fallback to using normal `RegExp` instances. As of v4.0.0 we added an option if you wish to force this package to not even attempt to load `re2` (e.g. it's in your `node_modules` [but you don't want to use it](https://github.com/spamscanner/url-regex-safe/issues/28)) – simply pass `re2: false` as an option.
3939

4040
[npm][]:
4141

4242
```sh
43-
npm install email-regex-safe re2
43+
npm install email-regex-safe
4444
```
4545

4646

@@ -94,6 +94,7 @@ Assuming you are using [browserify][], [webpack][], [rollup][], or another bundl
9494

9595
| Property | Type | Default Value | Description |
9696
| -------------- | ------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
97+
| `re2` | Boolean | `true` | Attempt to load `re2` to use instead of `RegExp` for creating new regular expression instances. If you pass `re2: false`, then `re2` will not even be attempted to be loaded. |
9798
| `exact` | Boolean | `false` | Only match an exact String. Useful with `regex.test(str)` to check if a String is an email address. We set this to `false` by default as the most common use case for a RegExp parser is to parse out emails, as opposed to check strict validity; we feel this closely more resembles real-world intended usage of this package. |
9899
| `strict` | Boolean | `false` | If `true`, then it will allow any TLD as long as it is a minimum of 2 valid characters. If it is `false`, then it will match the TLD against the list of valid TLD's using [tlds](https://github.com/stephenmathieson/node-tlds#readme). |
99100
| `gmail` | Boolean | `true` | Whether or not to abide by Gmail's rules for email usernames (see Gmail's [Create a username article](https://support.google.com/mail/answer/9211434) for more insight). Note that since [RE2][] does not support negative lookahead nor negative lookbehind, we are leaving it up to you to filter out a select few invalid matches while using `gmail: true`. Invalid matches would be those that end with a "." (period) or "+" (plus symbol), or have two or more consecutive ".." periods in a row anywhere in the username portion. We recommend to use `str.matches(emailSafeRegex())` to get an Array of all matches, and then filter those that pass [validator.isEmail][validator-email] after having end period(s) and/or plus symbol(s) stripped from them, as well as filtering out matches with repeated periods. |
@@ -112,7 +113,7 @@ If you would like to validate email addresses found, then you should use the [va
112113

113114
## Limitations
114115

115-
Since we cannot use regular expression's "negative lookbehinds" functionality (due to [RE2][] limitations), we could not merge the logic from this [pull request](https://github.com/kevva/url-regex/pull/67/commits/6c31d81c35c3bb72c413c6e4af92a37b2689ead2). This would have allowed us to make it so `example.jpeg` would match only if it was `example.jp`, however if you pass `example.jpeg` right now it will extract `example.jp` from it (since `.jp` is a TLD). An alternative solution may exist, and we welcome community contributions regarding this issue.
116+
**This limitation only applies if you are using `re2`**: Since we cannot use regular expression's "negative lookbehinds" functionality (due to [RE2][] limitations), we could not merge the logic from this [pull request](https://github.com/kevva/url-regex/pull/67/commits/6c31d81c35c3bb72c413c6e4af92a37b2689ead2). This would have allowed us to make it so `example.jpeg` would match only if it was `example.jp`, however if you pass `example.jpeg` right now it will extract `example.jp` from it (since `.jp` is a TLD). An alternative solution may exist, and we welcome community contributions regarding this issue.
116117

117118

118119
## Contributors

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,34 @@
1414
],
1515
"dependencies": {
1616
"ip-regex": "4",
17-
"tlds": "^1.240.0"
17+
"tlds": "^1.242.0"
1818
},
1919
"devDependencies": {
20-
"@babel/cli": "^7.22.9",
21-
"@babel/core": "^7.22.9",
22-
"@babel/eslint-parser": "^7.22.9",
23-
"@babel/preset-env": "^7.22.9",
24-
"@commitlint/cli": "^17.6.7",
25-
"@commitlint/config-conventional": "^17.6.7",
20+
"@babel/cli": "^7.22.10",
21+
"@babel/core": "^7.22.10",
22+
"@babel/eslint-parser": "^7.22.10",
23+
"@babel/preset-env": "^7.22.10",
24+
"@commitlint/cli": "^17.7.1",
25+
"@commitlint/config-conventional": "^17.7.0",
2626
"ava": "^4.3.0",
2727
"babelify": "^10.0.0",
2828
"browserify": "^17.0.0",
2929
"cross-env": "^7.0.3",
30-
"eslint": "^8.46.0",
30+
"eslint": "^8.47.0",
3131
"eslint-config-xo-lass": "^2.0.1",
3232
"eslint-plugin-compat": "^4.1.4",
3333
"eslint-plugin-node": "^11.1.0",
3434
"fixpack": "^4.0.0",
3535
"husky": "^8.0.3",
3636
"jsdom": "15",
37-
"lint-staged": "^13.2.3",
37+
"lint-staged": "^14.0.0",
3838
"nyc": "^15.1.0",
3939
"re2": "^1.20.1",
4040
"remark-cli": "^11.0.0",
4141
"remark-preset-github": "^4.0.4",
42-
"rimraf": "^3.0.2",
42+
"rimraf": "^5.0.1",
4343
"tinyify": "^3.1.0",
44-
"xo": "^0.55.0"
44+
"xo": "^0.56.0"
4545
},
4646
"engines": {
4747
"node": ">=14"

src/index.js

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,58 @@
11
const ipRegex = require('ip-regex');
22
const tlds = require('tlds');
33

4-
/* istanbul ignore next */
5-
const SafeRegExp = (() => {
6-
try {
7-
const RE2 = require('re2');
8-
return typeof RE2 === 'function' ? RE2 : RegExp;
9-
} catch {
10-
return RegExp;
11-
}
12-
})();
134
const ipv4 = ipRegex.v4().source;
145
const ipv6 = ipRegex.v6().source;
6+
const host = '(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)';
7+
const domain = '(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*';
8+
const strictTld = '(?:[a-z\\u00a1-\\uffff]{2,})';
9+
const defaultTlds = `(?:${tlds.sort((a, b) => b.length - a.length).join('|')})`;
10+
11+
let RE2;
12+
let hasRE2;
1513

1614
module.exports = (options) => {
17-
// eslint-disable-next-line prefer-object-spread
18-
options = Object.assign(
19-
{
20-
exact: false,
21-
strict: false,
22-
gmail: true,
23-
utf8: true,
24-
localhost: true,
25-
ipv4: true,
26-
ipv6: false,
27-
tlds,
28-
returnString: false
29-
},
30-
options
31-
);
15+
options = {
16+
//
17+
// attempt to use re2, if set to false will use RegExp
18+
// (we did this approach because we don't want to load in-memory re2 if users don't want it)
19+
// <https://github.com/spamscanner/url-regex-safe/issues/28>
20+
//
21+
re2: true,
22+
exact: false,
23+
strict: false,
24+
gmail: true,
25+
utf8: true,
26+
localhost: true,
27+
ipv4: true,
28+
ipv6: false,
29+
returnString: false,
30+
...options
31+
};
3232

33-
const host = '(?:(?:[a-z\\u00a1-\\uffff0-9][-_]*)*[a-z\\u00a1-\\uffff0-9]+)';
34-
const domain =
35-
'(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*';
33+
/* istanbul ignore next */
34+
const SafeRegExp =
35+
options.re2 && hasRE2 !== false
36+
? (() => {
37+
if (typeof RE2 === 'function') return RE2;
38+
try {
39+
RE2 = require('re2');
40+
return typeof RE2 === 'function' ? RE2 : RegExp;
41+
} catch {
42+
hasRE2 = false;
43+
return RegExp;
44+
}
45+
})()
46+
: RegExp;
3647

3748
// Add ability to pass custom list of tlds
3849
// <https://github.com/kevva/url-regex/pull/66>
3950
const tld = `(?:\\.${
4051
options.strict
41-
? '(?:[a-z\\u00a1-\\uffff]{2,})'
42-
: `(?:${options.tlds.sort((a, b) => b.length - a.length).join('|')})`
52+
? strictTld
53+
: options.tlds
54+
? `(?:${options.tlds.sort((a, b) => b.length - a.length).join('|')})`
55+
: defaultTlds
4356
})`;
4457

4558
// <https://github.com/validatorjs/validator.js/blob/master/src/lib/isEmail.js>

0 commit comments

Comments
 (0)