-
-
Notifications
You must be signed in to change notification settings - Fork 61
/
is_external_link.js
55 lines (40 loc) · 1.44 KB
/
is_external_link.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
'use strict';
const { parse, URL } = require('url');
const Cache = require('./cache');
const cache = new Cache();
/**
* Check whether the link is external
* @param {String} input The url to check
* @param {String} input The hostname / url of website
* @param {Array} input Exclude hostnames. Specific subdomain is required when applicable, including www.
* @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url
*/
function isExternalLink(input, sitehost, exclude) {
return cache.apply(`${input}-${sitehost}-${exclude}`, () => {
// Return false early for internal link
if (!/^(\/\/|http(s)?:)/.test(input)) return false;
sitehost = parse(sitehost).hostname || sitehost;
if (!sitehost) return false;
// handle relative url and invalid url
let data;
try {
data = new URL(input, `http://${sitehost}`);
} catch (e) { }
// if input is invalid url, data should be undefined
if (typeof data !== 'object') return false;
// handle mailto: javascript: vbscript: and so on
if (data.origin === 'null') return false;
const host = data.hostname;
if (exclude) {
exclude = Array.isArray(exclude) ? exclude : [exclude];
if (exclude && exclude.length) {
for (const i of exclude) {
if (host === i) return false;
}
}
}
if (host !== sitehost) return true;
return false;
});
}
module.exports = isExternalLink;