-
-
Notifications
You must be signed in to change notification settings - Fork 47
/
index.js
69 lines (56 loc) · 1.59 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import urlRegex from 'url-regex-safe';
import normalizeUrl from 'normalize-url';
import {isMatch, matches} from 'super-regex';
const getUrlsFromQueryParameters = url => {
const returnValue = new Set();
const {searchParams} = (new URL(url.replace(/^(?:\/\/|(?:www\.))/i, 'http://$2')));
for (const [, value] of searchParams) {
if (isMatch(urlRegex({exact: true}), value, {timeout: 500})) {
returnValue.add(value);
}
}
return returnValue;
};
export default function getUrls(text, options = {}) {
if (typeof text !== 'string') {
throw new TypeError(`The \`text\` argument should be a string, got ${typeof text}`);
}
if (options.exclude !== undefined && !Array.isArray(options.exclude)) {
throw new TypeError('The `exclude` option must be an array');
}
const returnValue = new Set();
const add = url => {
try {
returnValue.add(normalizeUrl(url.trim().replace(/\.+$/, ''), options));
} catch {}
};
const results = matches(
urlRegex(options.requireSchemeOrWww === undefined ? undefined : {
re2: false,
strict: options.requireSchemeOrWww,
parens: true,
}),
text,
{
matchTimeout: 500,
},
);
for (const {match: url} of results) {
add(url);
if (options.extractFromQueryString) {
const queryStringUrls = getUrlsFromQueryParameters(url);
for (const queryStringUrl of queryStringUrls) {
add(queryStringUrl);
}
}
}
for (const excludedItem of options.exclude ?? []) {
const regex = new RegExp(excludedItem);
for (const item of returnValue) {
if (isMatch(regex, item, {timeout: 500})) {
returnValue.delete(item);
}
}
}
return returnValue;
}