Files
auto-login/utils.js
T
2026-09-16 16:26:44 +08:00

81 lines
2.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// URL 匹配 + HTML 转义,浏览器与 Node 通用
(function (root, factory) {
if (typeof module === "object" && module.exports) {
module.exports = factory();
} else {
const api = factory();
root.isDomainMatch = api.isDomainMatch;
root.escapeHtml = api.escapeHtml;
}
})(typeof globalThis !== "undefined" ? globalThis : this, function () {
"use strict";
/**
* 判断 URL 是否匹配规则。
* 纯 hostname:example.com / *.example.com
* hostname+path:example.com/login/*,路径部分支持 * 通配
*/
function isDomainMatch(url, pattern) {
if (!url || !pattern) return false;
try {
const u = new URL(url);
const rawPattern = String(pattern).trim().replace(/^https?:\/\//i, "");
if (rawPattern.includes("/")) {
const slashIdx = rawPattern.indexOf("/");
const hostPart = rawPattern.slice(0, slashIdx);
const pathPart = rawPattern.slice(slashIdx + 1) || "";
const hostForMatch = hostPart.includes(":") ? u.host : u.hostname;
if (!matchHost(hostForMatch, hostPart)) return false;
return matchPath(u.pathname, pathPart);
}
const hostForMatch = rawPattern.includes(":") ? u.host : u.hostname;
return matchHost(hostForMatch, rawPattern);
} catch {
return false;
}
}
function matchHost(hostname, hostPart) {
if (hostPart.startsWith("*.")) {
const suffix = hostPart.slice(2);
return hostname === suffix || hostname.endsWith("." + suffix);
}
if (hostPart.includes("*")) {
const regexStr = hostPart.replace(/\./g, "\\.").replace(/\*/g, ".*");
return new RegExp("^" + regexStr + "$").test(hostname);
}
return hostname === hostPart;
}
function matchPath(pathname, pathPart) {
const pagePath = pathname.startsWith("/") ? pathname.slice(1) : pathname;
if (!pathPart) return true;
if (pathPart === "*") return true;
if (pathPart.endsWith("/*")) {
const prefix = pathPart.slice(0, -2);
return pagePath === prefix || pagePath.startsWith(prefix + "/");
}
if (pathPart.includes("*")) {
const regexStr = pathPart.replace(/\//g, "\\/").replace(/\*/g, ".*");
return new RegExp("^" + regexStr + "$").test(pagePath);
}
return pagePath === pathPart;
}
/** HTML 转义,防止配置中的特殊字符破坏页面 */
function escapeHtml(str) {
if (str == null) return "";
return String(str)
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#39;");
}
return { isDomainMatch, escapeHtml };
});