no message
This commit is contained in:
@@ -220,11 +220,11 @@
|
|||||||
"description": "Username selector label"
|
"description": "Username selector label"
|
||||||
},
|
},
|
||||||
"usernameSelectorPlaceholder": {
|
"usernameSelectorPlaceholder": {
|
||||||
"message": "Empty=auto find, e.g. #username or input[name=account]",
|
"message": "Empty=auto find, or paste element HTML / CSS selector",
|
||||||
"description": "Username selector placeholder"
|
"description": "Username selector placeholder"
|
||||||
},
|
},
|
||||||
"usernameSelectorHelp": {
|
"usernameSelectorHelp": {
|
||||||
"message": "Leave empty. Wrong value will cause username not filled.",
|
"message": "Paste the input's DOM node, or a CSS selector; empty = auto find.",
|
||||||
"description": "Username selector help"
|
"description": "Username selector help"
|
||||||
},
|
},
|
||||||
"passwordSelectorLabel": {
|
"passwordSelectorLabel": {
|
||||||
@@ -232,11 +232,11 @@
|
|||||||
"description": "Password selector label"
|
"description": "Password selector label"
|
||||||
},
|
},
|
||||||
"passwordSelectorPlaceholder": {
|
"passwordSelectorPlaceholder": {
|
||||||
"message": "Empty=auto find, e.g. #password or input[type=password]",
|
"message": "Empty=auto find, or paste element HTML / CSS selector",
|
||||||
"description": "Password selector placeholder"
|
"description": "Password selector placeholder"
|
||||||
},
|
},
|
||||||
"passwordSelectorHelp": {
|
"passwordSelectorHelp": {
|
||||||
"message": "Leave empty. Wrong value will cause password not filled.",
|
"message": "Paste the input's DOM node, or a CSS selector; empty = auto find.",
|
||||||
"description": "Password selector help"
|
"description": "Password selector help"
|
||||||
},
|
},
|
||||||
"submitSelectorLabel": {
|
"submitSelectorLabel": {
|
||||||
@@ -244,11 +244,11 @@
|
|||||||
"description": "Submit selector label"
|
"description": "Submit selector label"
|
||||||
},
|
},
|
||||||
"submitSelectorPlaceholder": {
|
"submitSelectorPlaceholder": {
|
||||||
"message": "Empty=auto find, e.g. #loginBtn or button[type=submit]",
|
"message": "Empty=auto find, or paste element HTML / CSS selector",
|
||||||
"description": "Submit selector placeholder"
|
"description": "Submit selector placeholder"
|
||||||
},
|
},
|
||||||
"submitSelectorHelp": {
|
"submitSelectorHelp": {
|
||||||
"message": "Leave empty. Wrong value will cause auto-submit not to click.",
|
"message": "Paste the button's DOM node, or a CSS selector; empty = auto find.",
|
||||||
"description": "Submit selector help"
|
"description": "Submit selector help"
|
||||||
},
|
},
|
||||||
"addConfigBtn": {
|
"addConfigBtn": {
|
||||||
|
|||||||
@@ -220,11 +220,11 @@
|
|||||||
"description": "用户名选择器 label"
|
"description": "用户名选择器 label"
|
||||||
},
|
},
|
||||||
"usernameSelectorPlaceholder": {
|
"usernameSelectorPlaceholder": {
|
||||||
"message": "留空=自动查找,如 #username 或 input[name=account]",
|
"message": "留空=自动查找,可粘贴元素 HTML 或填 CSS 选择器",
|
||||||
"description": "用户名选择器 placeholder"
|
"description": "用户名选择器 placeholder"
|
||||||
},
|
},
|
||||||
"usernameSelectorHelp": {
|
"usernameSelectorHelp": {
|
||||||
"message": "留空即可。填错会导致用户名填不进框。",
|
"message": "直接粘贴该输入框的 DOM 节点,或填 CSS 选择器;留空则自动查找。",
|
||||||
"description": "用户名选择器下方说明"
|
"description": "用户名选择器下方说明"
|
||||||
},
|
},
|
||||||
"passwordSelectorLabel": {
|
"passwordSelectorLabel": {
|
||||||
@@ -232,11 +232,11 @@
|
|||||||
"description": "密码选择器 label"
|
"description": "密码选择器 label"
|
||||||
},
|
},
|
||||||
"passwordSelectorPlaceholder": {
|
"passwordSelectorPlaceholder": {
|
||||||
"message": "留空=自动查找,如 #password 或 input[type=password]",
|
"message": "留空=自动查找,可粘贴元素 HTML 或填 CSS 选择器",
|
||||||
"description": "密码选择器 placeholder"
|
"description": "密码选择器 placeholder"
|
||||||
},
|
},
|
||||||
"passwordSelectorHelp": {
|
"passwordSelectorHelp": {
|
||||||
"message": "留空即可。填错会导致密码填不进框。",
|
"message": "直接粘贴该输入框的 DOM 节点,或填 CSS 选择器;留空则自动查找。",
|
||||||
"description": "密码选择器下方说明"
|
"description": "密码选择器下方说明"
|
||||||
},
|
},
|
||||||
"submitSelectorLabel": {
|
"submitSelectorLabel": {
|
||||||
@@ -244,11 +244,11 @@
|
|||||||
"description": "登录按钮选择器 label"
|
"description": "登录按钮选择器 label"
|
||||||
},
|
},
|
||||||
"submitSelectorPlaceholder": {
|
"submitSelectorPlaceholder": {
|
||||||
"message": "留空=自动查找,如 #loginBtn 或 button[type=submit]",
|
"message": "留空=自动查找,可粘贴元素 HTML 或填 CSS 选择器",
|
||||||
"description": "登录按钮选择器 placeholder"
|
"description": "登录按钮选择器 placeholder"
|
||||||
},
|
},
|
||||||
"submitSelectorHelp": {
|
"submitSelectorHelp": {
|
||||||
"message": "留空即可。填错会导致不会自动点击登录。",
|
"message": "直接粘贴该按钮的 DOM 节点,或填 CSS 选择器;留空则自动查找。",
|
||||||
"description": "登录按钮选择器下方说明"
|
"description": "登录按钮选择器下方说明"
|
||||||
},
|
},
|
||||||
"addConfigBtn": {
|
"addConfigBtn": {
|
||||||
|
|||||||
+66
-12
@@ -71,13 +71,49 @@ function setNativeValue(el, value) {
|
|||||||
el.dispatchEvent(new Event("change", { bubbles: true }));
|
el.dispatchEvent(new Event("change", { bubbles: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
function findUsernameField(config) {
|
function resolveElement(value, multiple) {
|
||||||
let searchScope = config.usernameSelector ? document.querySelector(config.usernameSelector) : null;
|
if (!value) return null;
|
||||||
if (!searchScope) {
|
const trimmed = value.trim();
|
||||||
const passwordField = findPasswordField(config);
|
if (!trimmed.startsWith("<")) {
|
||||||
if (!passwordField) return null;
|
return multiple ? Array.from(document.querySelectorAll(trimmed)) : document.querySelector(trimmed);
|
||||||
searchScope = passwordField.closest("form") || document;
|
|
||||||
}
|
}
|
||||||
|
const doc = new DOMParser().parseFromString(trimmed, "text/html");
|
||||||
|
const el = doc.body.firstElementChild;
|
||||||
|
if (!el) return null;
|
||||||
|
const tag = el.tagName.toLowerCase();
|
||||||
|
const id = el.id;
|
||||||
|
const cls = Array.from(el.classList);
|
||||||
|
const type = el.getAttribute("type");
|
||||||
|
const nameAttr = el.getAttribute("name");
|
||||||
|
const candidates = [];
|
||||||
|
if (id) candidates.push(`${tag}#${CSS.escape(id)}`);
|
||||||
|
if (cls.length) candidates.push(`${tag}.${cls.map(CSS.escape).join(".")}`);
|
||||||
|
if (type) candidates.push(`${tag}[type="${type}"]`);
|
||||||
|
if (nameAttr) candidates.push(`${tag}[name="${CSS.escape(nameAttr)}"]`);
|
||||||
|
for (const c of cls) candidates.push(`${tag}.${CSS.escape(c)}`);
|
||||||
|
candidates.push(tag);
|
||||||
|
for (const sel of candidates) {
|
||||||
|
if (multiple) {
|
||||||
|
const els = Array.from(document.querySelectorAll(sel));
|
||||||
|
if (els.length) return els;
|
||||||
|
} else {
|
||||||
|
const found = document.querySelector(sel);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findUsernameField(config) {
|
||||||
|
if (config.usernameSelector) {
|
||||||
|
const el = resolveElement(config.usernameSelector);
|
||||||
|
if (el) return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordField = findPasswordField(config);
|
||||||
|
if (!passwordField) return null;
|
||||||
|
|
||||||
|
const searchScope = passwordField.closest("form") || document;
|
||||||
|
|
||||||
const selectors = [
|
const selectors = [
|
||||||
"input[type='text']",
|
"input[type='text']",
|
||||||
@@ -125,8 +161,12 @@ function findUsernameField(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findPasswordField(config) {
|
function findPasswordField(config) {
|
||||||
const scope = config.passwordSelector ? (document.querySelector(config.passwordSelector) || document) : document;
|
if (config.passwordSelector) {
|
||||||
const passwordInputs = scope.querySelectorAll("input[type='password']");
|
const el = resolveElement(config.passwordSelector);
|
||||||
|
if (el) return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
const passwordInputs = document.querySelectorAll("input[type='password']");
|
||||||
for (const input of passwordInputs) {
|
for (const input of passwordInputs) {
|
||||||
if (input.offsetParent !== null || input.offsetWidth > 0) {
|
if (input.offsetParent !== null || input.offsetWidth > 0) {
|
||||||
return input;
|
return input;
|
||||||
@@ -137,12 +177,26 @@ function findPasswordField(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function findSubmitButton(config, passwordField) {
|
function findSubmitButton(config, passwordField) {
|
||||||
let searchScope = config.submitSelector ? document.querySelector(config.submitSelector) : null;
|
if (config.submitSelector) {
|
||||||
if (!searchScope) {
|
const els = resolveElement(config.submitSelector, true);
|
||||||
const form = passwordField ? passwordField.closest("form") : null;
|
if (els && els.length === 1) return els[0];
|
||||||
searchScope = form || document;
|
if (els && els.length > 1) {
|
||||||
|
for (const el of els) {
|
||||||
|
if (el.offsetParent === null && el.offsetWidth === 0) continue;
|
||||||
|
const compact = (el.textContent || el.value || "").toLowerCase().replace(/\s/g, "");
|
||||||
|
if (compact.includes("登录") || compact.includes("login") || compact.includes("signin")) {
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const el of els) {
|
||||||
|
if (el.offsetParent !== null || el.offsetWidth > 0) return el;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const form = passwordField ? passwordField.closest("form") : null;
|
||||||
|
const searchScope = form || document;
|
||||||
|
|
||||||
const submitSelectors = [
|
const submitSelectors = [
|
||||||
"button[type='submit']",
|
"button[type='submit']",
|
||||||
"input[type='submit']",
|
"input[type='submit']",
|
||||||
|
|||||||
@@ -1052,6 +1052,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
const value = u.pathname && u.pathname !== "/" ? host + u.pathname : host;
|
const value = u.pathname && u.pathname !== "/" ? host + u.pathname : host;
|
||||||
domainInput.value = value;
|
domainInput.value = value;
|
||||||
|
if (tab.title) aliasInput.value = tab.title;
|
||||||
saveDraft();
|
saveDraft();
|
||||||
showToast(t("toastDomainFilled", value));
|
showToast(t("toastDomainFilled", value));
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -19,18 +19,20 @@
|
|||||||
if (!url || !pattern) return false;
|
if (!url || !pattern) return false;
|
||||||
try {
|
try {
|
||||||
const u = new URL(url);
|
const u = new URL(url);
|
||||||
const hostname = u.hostname;
|
|
||||||
const rawPattern = String(pattern).trim();
|
const rawPattern = String(pattern).trim();
|
||||||
|
|
||||||
if (rawPattern.includes("/")) {
|
if (rawPattern.includes("/")) {
|
||||||
const slashIdx = rawPattern.indexOf("/");
|
const slashIdx = rawPattern.indexOf("/");
|
||||||
const hostPart = rawPattern.slice(0, slashIdx);
|
const hostPart = rawPattern.slice(0, slashIdx);
|
||||||
const pathPart = rawPattern.slice(slashIdx + 1) || "";
|
const pathPart = rawPattern.slice(slashIdx + 1) || "";
|
||||||
if (!matchHost(hostname, hostPart)) return false;
|
const hostForMatch = hostPart.includes(":") ? u.host : u.hostname;
|
||||||
|
if (!matchHost(hostForMatch, hostPart)) return false;
|
||||||
return matchPath(u.pathname, pathPart);
|
return matchPath(u.pathname, pathPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchHost(hostname, rawPattern);
|
const hostForMatch = rawPattern.includes(":") ? u.host : u.hostname;
|
||||||
|
return matchHost(hostForMatch, rawPattern);
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user