is_external_link.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. 'use strict';
  2. const { parse } = require('url');
  3. const Cache = require('./cache');
  4. const cache = new Cache();
  5. /**
  6. * Check whether the link is external
  7. * @param {String} input The url to check
  8. * @param {String} input The hostname / url of website
  9. * @param {Array} input Exclude hostnames. Specific subdomain is required when applicable, including www.
  10. * @returns {Boolean} True if the link doesn't have protocol or link has same host with config.url
  11. */
  12. function isExternalLink(input, sitehost, exclude) {
  13. return cache.apply(`${input}-${sitehost}-${exclude}`, () => {
  14. // Return false early for internal link
  15. if (!/^(\/\/|http(s)?:)/.test(input)) return false;
  16. sitehost = parse(sitehost).hostname || sitehost;
  17. if (!sitehost) return false;
  18. // handle relative url and invalid url
  19. let data;
  20. try {
  21. data = new URL(input, `http://${sitehost}`);
  22. } catch (e) { }
  23. // if input is invalid url, data should be undefined
  24. if (typeof data !== 'object') return false;
  25. // handle mailto: javascript: vbscript: and so on
  26. if (data.origin === 'null') return false;
  27. const host = data.hostname;
  28. if (exclude) {
  29. exclude = Array.isArray(exclude) ? exclude : [exclude];
  30. if (exclude && exclude.length) {
  31. for (const i of exclude) {
  32. if (host === i) return false;
  33. }
  34. }
  35. }
  36. if (host !== sitehost) return true;
  37. return false;
  38. });
  39. }
  40. module.exports = isExternalLink;