remote_BC1y8RCW.mjs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. globalThis.process ??= {}; globalThis.process.env ??= {};
  2. function matchPattern(url, remotePattern) {
  3. return matchProtocol(url, remotePattern.protocol) && matchHostname(url, remotePattern.hostname, true) && matchPort(url, remotePattern.port) && matchPathname(url, remotePattern.pathname, true);
  4. }
  5. function matchPort(url, port) {
  6. return !port || port === url.port;
  7. }
  8. function matchProtocol(url, protocol) {
  9. return !protocol || protocol === url.protocol.slice(0, -1);
  10. }
  11. function matchHostname(url, hostname, allowWildcard = false) {
  12. if (!hostname) {
  13. return true;
  14. } else if (!allowWildcard || !hostname.startsWith("*")) {
  15. return hostname === url.hostname;
  16. } else if (hostname.startsWith("**.")) {
  17. const slicedHostname = hostname.slice(2);
  18. return slicedHostname !== url.hostname && url.hostname.endsWith(slicedHostname);
  19. } else if (hostname.startsWith("*.")) {
  20. const slicedHostname = hostname.slice(1);
  21. const additionalSubdomains = url.hostname.replace(slicedHostname, "").split(".").filter(Boolean);
  22. return additionalSubdomains.length === 1;
  23. }
  24. return false;
  25. }
  26. function matchPathname(url, pathname, allowWildcard = false) {
  27. if (!pathname) {
  28. return true;
  29. } else if (!allowWildcard || !pathname.endsWith("*")) {
  30. return pathname === url.pathname;
  31. } else if (pathname.endsWith("/**")) {
  32. const slicedPathname = pathname.slice(0, -2);
  33. return slicedPathname !== url.pathname && url.pathname.startsWith(slicedPathname);
  34. } else if (pathname.endsWith("/*")) {
  35. const slicedPathname = pathname.slice(0, -1);
  36. const additionalPathChunks = url.pathname.replace(slicedPathname, "").split("/").filter(Boolean);
  37. return additionalPathChunks.length === 1;
  38. }
  39. return false;
  40. }
  41. function isRemoteAllowed(src, {
  42. domains,
  43. remotePatterns
  44. }) {
  45. if (!URL.canParse(src)) {
  46. return false;
  47. }
  48. const url = new URL(src);
  49. if (url.protocol === "data:") {
  50. return true;
  51. }
  52. if (!["http:", "https:"].includes(url.protocol)) {
  53. return false;
  54. }
  55. return domains.some((domain) => matchHostname(url, domain)) || remotePatterns.some((remotePattern) => matchPattern(url, remotePattern));
  56. }
  57. export { isRemoteAllowed as i, matchPattern as m };