2023-10-03 11:14:36 +08:00
|
|
|
'use strict';
|
|
|
|
|
|
|
|
const { parse } = 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;
|