You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Browser 执行脚本(纯字符串)。禁止改为 function。
*/
export const SCROLL_WIDGET_INTO_VIEW =
"(el) => { el.scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'instant' }); }";
export const IS_SELECT_TAG = "(el) => el.tagName === 'SELECT'";
/** @deprecated Network-First 禁止 DOM 报价提取 */
export const COLLECT_EMBEDDED_JSON = `() => {
const payloads = [];
const next = document.getElementById("__NEXT_DATA__");
if (next && next.textContent) {
try { payloads.push(JSON.parse(next.textContent)); } catch (e) {}
}
document.querySelectorAll('script[type="application/json"]').forEach((el) => {
const text = el.textContent ? el.textContent.trim() : "";
if (!text) return;
try { payloads.push(JSON.parse(text)); } catch (e) {}
});
return payloads;
}`;
/** @deprecated Network-First 禁止 DOM 报价提取 */
export const COLLECT_CLIENT_STATE = `() => {
const payloads = [];
const next = document.getElementById("__NEXT_DATA__");
if (next && next.textContent) {
try { payloads.push(JSON.parse(next.textContent)); } catch (e) {}
}
for (const key of Object.keys(window)) {
if (!/quote|rate|pricing|apollo|relay|__NEXT/i.test(key)) continue;
const val = window[key];
if (val && typeof val === "object") payloads.push(val);
}
return payloads;
}`;
export const COLLECT_ADDRESS_LABELS_FROM_DOM = `({ streetNumber, cityHint }) => {
const results = [];
const seen = new Set();
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
let node = walker.nextNode();
while (node) {
const chunk = (node.textContent || "").trim();
const hitStreet = streetNumber && chunk.includes(streetNumber);
const hitCity = cityHint.length >= 3 && chunk.toLowerCase().includes(cityHint.toLowerCase());
if (!hitStreet && !hitCity) { node = walker.nextNode(); continue; }
let el = node.parentElement;
for (let depth = 0; depth < 8 && el; depth += 1) {
const tag = el.tagName.toLowerCase();
if (tag === "input" || tag === "textarea") break;
const rowText = (el.innerText || "").replace(/\\s+/g, " ").trim();
if (rowText.length >= 8 && rowText.length <= 180 && (!streetNumber || rowText.includes(streetNumber))) {
if (!seen.has(rowText)) { seen.add(rowText); results.push(rowText); }
break;
}
el = el.parentElement;
}
node = walker.nextNode();
}
return results;
}`;
/** Google Places pac-item主行 + 副行,避免 innerText 粘连导致 suburb 丢失 */
export const COLLECT_PAC_ITEM_LABELS = `() => {
const results = [];
const seen = new Set();
document.querySelectorAll(".pac-container .pac-item").forEach((item) => {
const main =
item.querySelector(".pac-item-query")?.textContent?.replace(/\\s+/g, " ").trim() ||
"";
const secondary =
item.querySelector(".pac-item-secondary")?.textContent?.replace(/\\s+/g, " ").trim() ||
"";
let label = "";
if (main && secondary) {
label = main + "|" + secondary;
} else {
label = (item.innerText || "").replace(/\\s+/g, " ").trim();
}
if (label.length >= 8 && !seen.has(label)) {
seen.add(label);
results.push(label);
}
});
return results;
}`;
/** MotherShip widget listbox + pac + styled-components主行|副行对齐图2/图3 多候选) */
export const COLLECT_WIDGET_SUGGESTION_LABELS = `(function() {
var skipRe = /use my location|使用我的位置|get a freight|freight details|pick up from|deliver to|where to/i;
var stateRe = /(USA|US|CA|NY|TX|FL|IL|PA|OH|GA|NC|MI|NJ|VA|WA|AZ|MA|TN|IN|MO|MD|WI|CO|MN|SC|AL|LA|KY|OR|OK|CT|UT|IA|NV|AR|MS|KS|NM|NE|WV|ID|HI|NH|ME|MT|RI|DE|SD|ND|AK|DC|VT|WY|PR)/;
var seen = new Set();
var results = [];
function push(label) {
var t = (label || "").replace(/\\s+/g, " ").trim();
if (t.length < 8 || t.length > 180 || skipRe.test(t) || seen.has(t)) return;
seen.add(t);
results.push(t);
}
function pushLines(el) {
var raw = (el.innerText || "").replace(/\\r/g, "");
var lines = raw.split("\\n").map(function(l) { return l.trim(); }).filter(Boolean);
if (!lines.length || lines.some(function(l) { return skipRe.test(l); })) return;
if (lines.length >= 2) {
push(lines[0] + "|" + lines.slice(1).join(", "));
} else {
push(lines[0]);
}
}
// 1. ARIA listbox/option标准
document.querySelectorAll("#react-quoter-landing-plugin [role='listbox'] [role='option']").forEach(pushLines);
// 2. Google Places pac-container标准
document.querySelectorAll(".pac-container .pac-item").forEach(function(item) {
var mainEl = item.querySelector(".pac-item-query");
var secondaryEl = item.querySelector(".pac-item-secondary");
var main = mainEl && mainEl.textContent ? mainEl.textContent.replace(/\\s+/g, " ").trim() : "";
var secondary = secondaryEl && secondaryEl.textContent ? secondaryEl.textContent.replace(/\\s+/g, " ").trim() : "";
if (main && secondary) {
push(main + "|" + secondary);
} else {
pushLines(item);
}
});
// 3. Styled-components 地址联想MotherShip 自定义)
if (results.length === 0) {
var candidateTexts = new Set();
document.querySelectorAll("div[class*='sc-']").forEach(function(el) {
var text = (el.innerText || "").replace(/\\s+/g, " ").trim();
if (text.length >= 15 && text.length <= 150 && text.indexOf(",") >= 0 && stateRe.test(text) && !skipRe.test(text)) {
var rect = el.getBoundingClientRect();
if (rect.width > 180 && rect.height >= 24 && rect.height <= 100) {
if (!candidateTexts.has(text)) {
candidateTexts.add(text);
push(text);
}
}
}
});
}
// 4. 全局 [role="listbox"] 作为后备
if (results.length === 0) {
document.querySelectorAll('[role="listbox"]:not(#react-quoter-landing-plugin *)').forEach(function(listbox) {
listbox.querySelectorAll('[role="option"], [role="menuitem"], li').forEach(pushLines);
});
}
return results;
})()`;
/** 输入框下方联想行坐标:供 page.mouse.click 使用(不依赖 ARIA listbox */
export const COLLECT_SUGGESTION_MOUSE_TARGETS = `(input) => {
if (!input) return [];
var inputRect = input.getBoundingClientRect();
var query = (input.value || "").replace(/\\s+/g, " ").trim();
var streetNum = (query.match(/^\\d+/) || [])[0] || "";
var skipRe = /use my location|使用我的位置|pick up from|deliver to|where to|freight details|search by address|搜索地址|get a freight/i;
var results = [];
var seen = new Set();
function add(el) {
if (!el || el === input) return;
var rect = el.getBoundingClientRect();
if (!rect.width || !rect.height) return;
var text = (el.innerText || "").replace(/\\s+/g, " ").trim();
if (text.length < 8 || text.length > 200 || skipRe.test(text)) return;
if (streetNum && text.indexOf(streetNum) < 0) return;
if (rect.top < inputRect.top + inputRect.height * 0.4) return;
if (rect.top > inputRect.bottom + 380) return;
if (rect.width < 100 || rect.width > 900) return;
if (rect.height < 18 || rect.height > 110) return;
var childCount = el.children ? el.children.length : 0;
if (childCount > 8) return;
var key = Math.round(rect.top) + "|" + Math.round(rect.left) + "|" + text.slice(0, 32);
if (seen.has(key)) return;
seen.add(key);
results.push({
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2,
width: rect.width,
height: rect.height,
text: text,
top: rect.top,
area: rect.width * rect.height,
});
}
document.querySelectorAll('div[class*="sc-"], span[class*="sc-"], li, [role="option"], .pac-item').forEach(add);
results.sort(function (a, b) {
if (a.top !== b.top) return a.top - b.top;
return a.area - b.area;
});
var filtered = [];
for (var i = 0; i < results.length; i++) {
var r = results[i];
var dup = filtered.some(function (f) {
return Math.abs(f.top - r.top) < 10 && Math.abs(f.x - r.x) < 60;
});
if (!dup) filtered.push(r);
}
return filtered.slice(0, 6);
}`;
/**
* 截图同款地址 chip上行门牌街名、下行 City, ST拒绝 Search 框内多逗号打字态。
*/
export const DETECT_MOTHERSHIP_ADDRESS_CHIP = `(function(arg) {
var widgetSelector = arg.widgetSelector;
var streetNum = arg.streetNum || "";
var cityToken = arg.cityToken || "";
var cityWord = cityToken.trim().split(/\\s+/)[0].toLowerCase();
var widget = document.querySelector(widgetSelector);
if (!widget) return { committed: false, reason: "no-widget" };
for (var i = 0; i < widget.querySelectorAll("input").length; i++) {
var inp = widget.querySelectorAll("input")[i];
if (!inp || inp.offsetParent === null) continue;
var ph = (inp.placeholder || "").toLowerCase();
if (!/search|address|搜索/.test(ph)) continue;
var val = (inp.value || "").replace(/\\s+/g, " ").trim();
if (val.length < 10 || !streetNum || val.indexOf(streetNum) < 0) continue;
var commaParts = val.split(",").map(function (p) { return p.trim(); }).filter(Boolean);
if (commaParts.length >= 2) {
return { committed: false, reason: "active-search-typing", preview: val };
}
}
var raw = (widget.innerText || "").replace(/\\r/g, "");
var lines = raw.split("\\n").map(function (s) { return s.trim(); }).filter(function (s) { return s.length > 0; });
for (var j = 0; j < lines.length - 1; j++) {
var streetLine = lines[j];
var cityLine = lines[j + 1];
if (!streetNum || streetLine.indexOf(streetNum) < 0) continue;
if (streetLine.split(",").filter(function (p) { return p.trim().length > 0; }).length > 1) continue;
if (!/,\\s*[A-Z]{2}\\b/.test(cityLine)) continue;
if (cityWord && cityLine.toLowerCase().indexOf(cityWord) < 0) continue;
return {
committed: true,
reason: "two-line-chip",
streetLine: streetLine,
cityLine: cityLine,
};
}
return { committed: false, reason: "no-two-line-chip" };
})`;
export const PROBE_CARGO_UI = `(widgetEl, arg) => {
const cargoFieldRe = new RegExp(arg.cargoFieldReSource, "i");
function collectBlockers(el) {
const blockers = [];
if (!el.isConnected) blockers.push("not_connected");
if (el.disabled) blockers.push("disabled");
if (el.readOnly) blockers.push("readonly");
const style = window.getComputedStyle(el);
if (style.visibility === "hidden") blockers.push("visibility_hidden");
if (style.display === "none") blockers.push("display_none");
if (style.pointerEvents === "none") blockers.push("pointer_events_none");
const rect = el.getBoundingClientRect();
if (rect.width <= 0 || rect.height <= 0) blockers.push("zero_bounding_box");
if (typeof el.checkVisibility === "function") {
try {
if (!el.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) {
blockers.push("check_visibility_false");
}
} catch (e) { blockers.push("check_visibility_error"); }
} else if (el.offsetParent === null && style.position !== "fixed") {
blockers.push("offset_parent_null");
}
return blockers;
}
function isInteractive(el) { return collectBlockers(el).length === 0; }
const mountedCargoFields = [];
const interactiveCargoFields = [];
const blockedCargoFields = [];
for (const node of widgetEl.querySelectorAll("input,textarea")) {
const el = node;
const label = (el.placeholder || "") + " " + (el.getAttribute("aria-label") || "");
if (!cargoFieldRe.test(label)) continue;
const snapshot = { placeholder: el.placeholder, ariaLabel: el.getAttribute("aria-label") };
const blockers = collectBlockers(el);
const mounted = el.isConnected && !el.disabled && !el.readOnly;
if (mounted) mountedCargoFields.push(snapshot);
if (isInteractive(el)) interactiveCargoFields.push(snapshot);
else if (mounted || blockers.length > 0) {
blockedCargoFields.push({ placeholder: snapshot.placeholder, ariaLabel: snapshot.ariaLabel, blockers });
}
}
let phase = "no_cargo_inputs";
if (interactiveCargoFields.length > 0) phase = "interactive";
else if (mountedCargoFields.length > 0 || blockedCargoFields.length > 0) phase = "hydrating";
return { phase, mountedCargoFields, interactiveCargoFields, blockedCargoFields };
}`;
export const WAIT_CARGO_INTERACTIVE = `({ selector, cargoReadyReSource }) => {
function isInteractive(el) {
if (!el.isConnected || el.disabled || el.readOnly) return false;
const style = window.getComputedStyle(el);
if (style.visibility === "hidden" || style.display === "none" || style.pointerEvents === "none") return false;
const rect = el.getBoundingClientRect();
if (rect.width <= 0 || rect.height <= 0) return false;
if (typeof el.checkVisibility === "function") {
try { return el.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }); }
catch (e) { return false; }
}
return el.offsetParent !== null || style.position === "fixed";
}
const widget = document.querySelector(selector);
if (!widget) return false;
const readyRe = new RegExp(cargoReadyReSource, "i");
for (const node of widget.querySelectorAll("input,textarea")) {
const el = node;
const label = (el.placeholder || "") + " " + (el.getAttribute("aria-label") || "");
if (!readyRe.test(label)) continue;
if (isInteractive(el)) return true;
}
return false;
}`;
export const FILL_CARGO_FIELD = `(widgetEl, arg) => {
function isInteractive(el) {
if (!el.isConnected || el.disabled || el.readOnly) return false;
const style = window.getComputedStyle(el);
if (style.visibility === "hidden" || style.display === "none" || style.pointerEvents === "none") return false;
const rect = el.getBoundingClientRect();
if (rect.width <= 0 || rect.height <= 0) return false;
if (typeof el.checkVisibility === "function") {
try { return el.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true }); }
catch (e) { return false; }
}
return el.offsetParent !== null || style.position === "fixed";
}
const re = new RegExp(arg.fieldRe, "i");
for (const node of widgetEl.querySelectorAll("input,textarea")) {
const el = node;
const label = (el.placeholder || "") + " " + (el.getAttribute("aria-label") || "");
if (!re.test(label) || !isInteractive(el)) continue;
el.focus();
el.value = arg.val;
el.dispatchEvent(new Event("input", { bubbles: true }));
el.dispatchEvent(new Event("change", { bubbles: true }));
return true;
}
return false;
}`;