@xbrowser/cli 1.18.2 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{browser-BEERPZPB.js → browser-6LH6KJSW.js} +1 -1
- package/dist/{browser-TFFGGXOA.js → browser-TUD2KA5G.js} +2 -2
- package/dist/{browser-AEQS6325.js → browser-Y5SIE6LY.js} +2 -2
- package/dist/{cdp-driver-KT6HL33W.js → cdp-driver-2EECZW4X.js} +1 -1
- package/dist/{cdp-driver-4UAV56SQ.js → cdp-driver-7HO5SRNN.js} +1 -1
- package/dist/{cdp-driver-NNBPNFF2.js → cdp-driver-E7G3VHIB.js} +41 -3
- package/dist/{chunk-MTNVT2T7.js → chunk-2BPZ25RE.js} +13 -2
- package/dist/{chunk-NA7IP6PO.js → chunk-C6PW3CPA.js} +13 -2
- package/dist/{chunk-DVKIL7H6.js → chunk-GKYSCHT4.js} +41 -3
- package/dist/{chunk-7SDM4EA4.js → chunk-KLXLNQI5.js} +53 -4
- package/dist/{chunk-LL37GYPP.js → chunk-LKJZYVIX.js} +41 -3
- package/dist/cli.js +724 -14
- package/dist/daemon-main.js +732 -17
- package/dist/index.js +725 -15
- package/dist/{session-replayer-J4GXUULG.js → session-replayer-RODZYHM3.js} +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
resolveLaunchOpts,
|
|
19
19
|
saveSessionDiskMeta,
|
|
20
20
|
setActivePage
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-2BPZ25RE.js";
|
|
22
22
|
import {
|
|
23
23
|
detectAntiBot,
|
|
24
24
|
formatDetectionMessage
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
rand,
|
|
87
87
|
sleep,
|
|
88
88
|
wheelDelta
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-LKJZYVIX.js";
|
|
90
90
|
import "./chunk-3KZ34AUC.js";
|
|
91
91
|
import {
|
|
92
92
|
errMsg
|
|
@@ -124,8 +124,8 @@ import {
|
|
|
124
124
|
|
|
125
125
|
// src/executor.ts
|
|
126
126
|
import {
|
|
127
|
-
ok as
|
|
128
|
-
fail as
|
|
127
|
+
ok as ok30,
|
|
128
|
+
fail as fail15,
|
|
129
129
|
isCommandResult,
|
|
130
130
|
CompositeStorage as CompositeStorage2,
|
|
131
131
|
TipCollector as TipCollector2,
|
|
@@ -6673,6 +6673,709 @@ function describeSelector(strategy, value, name) {
|
|
|
6673
6673
|
}
|
|
6674
6674
|
}
|
|
6675
6675
|
|
|
6676
|
+
// src/commands/visual-tag.ts
|
|
6677
|
+
import { z as z29 } from "zod";
|
|
6678
|
+
import { ok as ok28, fail as fail13 } from "@dyyz1993/xcli-core";
|
|
6679
|
+
var SAFE_SET = "ahjkmnprtw3479".split("");
|
|
6680
|
+
var TAG_SCRIPT = `
|
|
6681
|
+
(function() {
|
|
6682
|
+
// \u6E05\u9664\u65E7\u6807\u6CE8
|
|
6683
|
+
var old = document.getElementById('__xb-tag-overlay');
|
|
6684
|
+
if (old) old.remove();
|
|
6685
|
+
window.__xbTagMap = {};
|
|
6686
|
+
|
|
6687
|
+
var SAFE_SET = ${JSON.stringify(SAFE_SET)};
|
|
6688
|
+
function genId(idx) {
|
|
6689
|
+
var base = SAFE_SET.length;
|
|
6690
|
+
if (idx < base * base) return SAFE_SET[Math.floor(idx / base)] + SAFE_SET[idx % base];
|
|
6691
|
+
var i = idx - base * base;
|
|
6692
|
+
return SAFE_SET[Math.floor(i / (base * base))] + SAFE_SET[Math.floor(i / base) % base] + SAFE_SET[i % base];
|
|
6693
|
+
}
|
|
6694
|
+
|
|
6695
|
+
// \u627E\u6240\u6709\u53EF\u4EA4\u4E92\u5143\u7D20
|
|
6696
|
+
var els = [];
|
|
6697
|
+
var all = document.querySelectorAll('button, a[href], input, select, textarea, [onclick], [role="button"], [contenteditable], [class*="btn"], [class*="button"], [class*="link"]');
|
|
6698
|
+
for (var i = 0; i < all.length && els.length < 200; i++) {
|
|
6699
|
+
var el = all[i];
|
|
6700
|
+
var r = el.getBoundingClientRect();
|
|
6701
|
+
if (r.width < 10 || r.height < 10) continue;
|
|
6702
|
+
if (r.x < 0 || r.y < 0 || r.x + r.width > window.innerWidth || r.y + r.height > window.innerHeight + 100) continue;
|
|
6703
|
+
var style = getComputedStyle(el);
|
|
6704
|
+
if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') continue;
|
|
6705
|
+
els.push({ el: el, rect: r });
|
|
6706
|
+
}
|
|
6707
|
+
|
|
6708
|
+
// \u521B\u5EFA\u53E0\u52A0 Canvas
|
|
6709
|
+
var canvas = document.createElement('canvas');
|
|
6710
|
+
canvas.id = '__xb-tag-overlay';
|
|
6711
|
+
canvas.width = window.innerWidth;
|
|
6712
|
+
canvas.height = Math.max(window.innerHeight, document.documentElement.scrollHeight);
|
|
6713
|
+
canvas.style.cssText = 'position:fixed;top:0;left:0;pointer-events:none;z-index:999999;';
|
|
6714
|
+
document.body.appendChild(canvas);
|
|
6715
|
+
var ctx = canvas.getContext('2d');
|
|
6716
|
+
|
|
6717
|
+
// \u7ED8\u5236\u6807\u7B7E
|
|
6718
|
+
for (var j = 0; j < els.length; j++) {
|
|
6719
|
+
var item = els[j];
|
|
6720
|
+
var id = genId(j);
|
|
6721
|
+
var x = item.rect.x;
|
|
6722
|
+
var y = item.rect.y;
|
|
6723
|
+
|
|
6724
|
+
// \u6807\u7B7E\u6846\uFF1A\u9AD8\u5BF9\u6BD4\uFF08\u9EC4\u5E95\u9ED1\u5B57\uFF09
|
|
6725
|
+
ctx.fillStyle = '#FFD700';
|
|
6726
|
+
ctx.fillRect(x - 2, y - 16, id.length * 8 + 8, 16);
|
|
6727
|
+
ctx.strokeStyle = '#000';
|
|
6728
|
+
ctx.lineWidth = 1.5;
|
|
6729
|
+
ctx.strokeRect(x - 2, y - 16, id.length * 8 + 8, 16);
|
|
6730
|
+
ctx.fillStyle = '#000';
|
|
6731
|
+
ctx.font = 'bold 12px monospace';
|
|
6732
|
+
ctx.fillText(id, x + 2, y - 5);
|
|
6733
|
+
|
|
6734
|
+
// \u5143\u7D20\u8F6E\u5ED3
|
|
6735
|
+
ctx.strokeStyle = '#FF0000';
|
|
6736
|
+
ctx.lineWidth = 1.5;
|
|
6737
|
+
ctx.strokeRect(x, y, item.rect.width, item.rect.height);
|
|
6738
|
+
|
|
6739
|
+
// \u5B58\u50A8 ID \u2192 \u5143\u7D20\u6620\u5C04
|
|
6740
|
+
window.__xbTagMap[id] = {
|
|
6741
|
+
tagName: item.el.tagName,
|
|
6742
|
+
text: (item.el.textContent || '').trim().slice(0, 50),
|
|
6743
|
+
rect: { x: x, y: y, w: item.rect.width, h: item.rect.height },
|
|
6744
|
+
selector: (function(e) {
|
|
6745
|
+
if (e.id) return '#' + e.id;
|
|
6746
|
+
if (e.getAttribute('data-testid')) return '[data-testid="' + e.getAttribute('data-testid') + '"]';
|
|
6747
|
+
// \u751F\u6210 nth-child \u9009\u62E9\u5668
|
|
6748
|
+
var path = [];
|
|
6749
|
+
var node = e;
|
|
6750
|
+
while (node && node !== document.body) {
|
|
6751
|
+
var idx = 1;
|
|
6752
|
+
var sib = node.previousElementSibling;
|
|
6753
|
+
while (sib) { if (sib.tagName === node.tagName) idx++; sib = sib.previousElementSibling; }
|
|
6754
|
+
path.unshift(node.tagName.toLowerCase() + ':nth-of-type(' + idx + ')');
|
|
6755
|
+
node = node.parentElement;
|
|
6756
|
+
}
|
|
6757
|
+
return path.join(' > ');
|
|
6758
|
+
})(item.el)
|
|
6759
|
+
};
|
|
6760
|
+
}
|
|
6761
|
+
|
|
6762
|
+
return JSON.stringify({ tagged: els.length, overlay: true });
|
|
6763
|
+
})()
|
|
6764
|
+
`;
|
|
6765
|
+
var visualTagCommand = registerCommand({
|
|
6766
|
+
name: "visual-tag",
|
|
6767
|
+
description: "\u5728\u9875\u9762\u4E0A\u7ED9\u53EF\u4EA4\u4E92\u5143\u7D20\u53E0\u52A0\u9632\u6DF7\u6DC6\u77ED ID \u6807\u7B7E\uFF08\u89C6\u89C9\u5B9A\u4F4D\u7528\uFF09",
|
|
6768
|
+
scope: "page",
|
|
6769
|
+
parameters: z29.object({
|
|
6770
|
+
action: z29.enum(["tag", "lookup", "clear", "list"]),
|
|
6771
|
+
id: z29.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID")
|
|
6772
|
+
}),
|
|
6773
|
+
result: z29.object({
|
|
6774
|
+
action: z29.string(),
|
|
6775
|
+
tagged: z29.number().optional(),
|
|
6776
|
+
id: z29.string().optional(),
|
|
6777
|
+
element: z29.record(z29.unknown()).optional()
|
|
6778
|
+
}),
|
|
6779
|
+
handler: async (p, ctx) => {
|
|
6780
|
+
switch (p.action) {
|
|
6781
|
+
case "tag": {
|
|
6782
|
+
const result = await ctx.page.evaluate(TAG_SCRIPT);
|
|
6783
|
+
const parsed = JSON.parse(result);
|
|
6784
|
+
return ok28({ action: "tag", tagged: parsed.tagged });
|
|
6785
|
+
}
|
|
6786
|
+
case "lookup": {
|
|
6787
|
+
if (!p.id) return fail13("lookup \u9700\u8981 --id \u53C2\u6570");
|
|
6788
|
+
const result = await ctx.page.evaluate(
|
|
6789
|
+
`(function() { var m = window.__xbTagMap; if (!m) return JSON.stringify({err:'no-map'}); var e = m[${JSON.stringify(p.id)}]; return e ? JSON.stringify(e) : JSON.stringify({err:'not-found'}); })()`
|
|
6790
|
+
);
|
|
6791
|
+
const parsed = JSON.parse(result);
|
|
6792
|
+
if (parsed.err) return fail13(`ID ${p.id}: ${parsed.err}`);
|
|
6793
|
+
return ok28({ action: "lookup", id: p.id, element: parsed });
|
|
6794
|
+
}
|
|
6795
|
+
case "list": {
|
|
6796
|
+
const result = await ctx.page.evaluate(
|
|
6797
|
+
`(function() { var m = window.__xbTagMap; if (!m) return '{}'; var out = {}; for (var k in m) { out[k] = m[k].text || m[k].tagName; } return JSON.stringify(out); })()`
|
|
6798
|
+
);
|
|
6799
|
+
return ok28({ action: "list", element: JSON.parse(result) });
|
|
6800
|
+
}
|
|
6801
|
+
case "clear": {
|
|
6802
|
+
await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;return 'cleared'})()`);
|
|
6803
|
+
return ok28({ action: "clear" });
|
|
6804
|
+
}
|
|
6805
|
+
}
|
|
6806
|
+
}
|
|
6807
|
+
});
|
|
6808
|
+
|
|
6809
|
+
// src/commands/visual-tag-v2.ts
|
|
6810
|
+
import { z as z30 } from "zod";
|
|
6811
|
+
import { ok as ok29, fail as fail14 } from "@dyyz1993/xcli-core";
|
|
6812
|
+
var SAFE_SET2 = "ahjkmnprtw3479".split("");
|
|
6813
|
+
var TAG_V2_SCRIPT = `
|
|
6814
|
+
(function() {
|
|
6815
|
+
var old = document.getElementById('__xb-tag-overlay');
|
|
6816
|
+
if (old) old.remove();
|
|
6817
|
+
window.__xbTagMap = {};
|
|
6818
|
+
window.__xbTagStats = {};
|
|
6819
|
+
|
|
6820
|
+
var SAFE_SET = ${JSON.stringify(SAFE_SET2)};
|
|
6821
|
+
var TYPE_PREFIX = { click:'k', input:'n', img:'m', list:'h', count:'p', text:'t' };
|
|
6822
|
+
function genId(prefix, idx) {
|
|
6823
|
+
var base = SAFE_SET.length;
|
|
6824
|
+
var suffix = SAFE_SET[Math.floor(idx / base) % base] + SAFE_SET[idx % base];
|
|
6825
|
+
return prefix + suffix;
|
|
6826
|
+
}
|
|
6827
|
+
|
|
6828
|
+
var counters = { click: 0, input: 0, img: 0, list: 0, count: 0, text: 0 };
|
|
6829
|
+
|
|
6830
|
+
var canvas = document.createElement('canvas');
|
|
6831
|
+
canvas.id = '__xb-tag-overlay';
|
|
6832
|
+
canvas.width = window.innerWidth;
|
|
6833
|
+
canvas.height = Math.max(window.innerHeight, document.documentElement.scrollHeight);
|
|
6834
|
+
canvas.style.cssText = 'position:fixed;top:0;left:0;pointer-events:none;z-index:999999;';
|
|
6835
|
+
document.body.appendChild(canvas);
|
|
6836
|
+
var ctx = canvas.getContext('2d');
|
|
6837
|
+
|
|
6838
|
+
function classifyElement(el) {
|
|
6839
|
+
var tag = el.tagName;
|
|
6840
|
+
var text = (el.textContent || '').trim();
|
|
6841
|
+
var cls = el.className || '';
|
|
6842
|
+
|
|
6843
|
+
// \u4F18\u5148\u7EA71\uFF1A\u6570\u5B57/\u8BA1\u6570\u5668\u2014\u2014\u5148\u4E8E\u5217\u8868\uFF08S129 \u9057\u7559\u95EE\u9898\u4FEE\u590D\uFF09
|
|
6844
|
+
var hasOnlySvgChildren = true;
|
|
6845
|
+
for (var ci = 0; ci < el.children.length; ci++) {
|
|
6846
|
+
if (el.children[ci].tagName.toUpperCase() !== 'SVG' && el.children[ci].tagName.toUpperCase() !== 'PATH' && el.children[ci].tagName.toUpperCase() !== 'SPAN') { hasOnlySvgChildren = false; break; }
|
|
6847
|
+
}
|
|
6848
|
+
if ((el.children.length === 0 || hasOnlySvgChildren) && text.length > 0 && text.length < 25) {
|
|
6849
|
+
var numMatch = /^[0-9]/.test(text) && text.length < 20;
|
|
6850
|
+
if (numMatch) return 'count';
|
|
6851
|
+
}
|
|
6852
|
+
// \u4F18\u5148\u7EA71.5\uFF1Aclass \u542B count/num/like/star/fork \u7684\u5BB9\u5668
|
|
6853
|
+
if (/count|num\b|like|star|fork|rating|badge/i.test(cls) && el.children.length <= 2) return 'count';
|
|
6854
|
+
|
|
6855
|
+
// \u4F18\u5148\u7EA72\uFF1A\u8F93\u5165\u6846
|
|
6856
|
+
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' ||
|
|
6857
|
+
el.getAttribute('contenteditable')) return 'input';
|
|
6858
|
+
|
|
6859
|
+
// \u4F18\u5148\u7EA73\uFF1A\u53EF\u70B9\u51FB\uFF08v3 \u6269\u5BBD\uFF1Adata-target/onclick/tab/menu/nav/link class\uFF09
|
|
6860
|
+
if (tag === 'BUTTON' || (el.getAttribute('role') === 'button') ||
|
|
6861
|
+
(tag === 'A' && el.getAttribute('href')) ||
|
|
6862
|
+
el.hasAttribute('onclick') || el.hasAttribute('data-target') ||
|
|
6863
|
+
/btn|button|click|action|tab\b|menu|nav\b|link\b/i.test(cls)) return 'click';
|
|
6864
|
+
|
|
6865
|
+
// \u4F18\u5148\u7EA74\uFF1A\u56FE\u7247\uFF08v3\uFF1A\u542B SVG \u56FE\u6807\uFF09
|
|
6866
|
+
if (tag === 'IMG' || (tag === 'SVG') ||
|
|
6867
|
+
(el.querySelector && el.querySelector('img,svg') &&
|
|
6868
|
+
el.children.length <= 2 && !text)) return 'img';
|
|
6869
|
+
|
|
6870
|
+
// \u4F18\u5148\u7EA74.5\uFF1A\u8868\u683C\u5355\u5143\u683C
|
|
6871
|
+
if (tag === 'TD' || tag === 'TH') return 'list';
|
|
6872
|
+
|
|
6873
|
+
// \u4F18\u5148\u7EA75\uFF1A\u5217\u8868\uFF08v3\uFF1A\u52A0 card\uFF09
|
|
6874
|
+
if (tag === 'UL' || tag === 'OL' || tag === 'LI' ||
|
|
6875
|
+
/list|item|feed|timeline|card/i.test(cls)) return 'list';
|
|
6876
|
+
|
|
6877
|
+
// \u4F18\u5148\u7EA76\uFF1A\u6587\u672C
|
|
6878
|
+
if (text.length > 20) return 'text';
|
|
6879
|
+
return null;
|
|
6880
|
+
}
|
|
6881
|
+
|
|
6882
|
+
var COLORS = {
|
|
6883
|
+
click: { stroke: '#FF0000', fill: '#FFD700' }, // \u7EA2+\u9EC4
|
|
6884
|
+
input: { stroke: '#0000FF', fill: '#ADD8E6' }, // \u84DD
|
|
6885
|
+
img: { stroke: '#00AA00', fill: '#90EE90' }, // \u7EFF
|
|
6886
|
+
list: { stroke: '#FFAA00', fill: '#FFE4B5' }, // \u6A59\u9EC4
|
|
6887
|
+
count: { stroke: '#9900CC', fill: '#E0B0FF' }, // \u7D2B
|
|
6888
|
+
text: { stroke: '#FF8C00', fill: '#FFECD2' }, // \u6A59
|
|
6889
|
+
};
|
|
6890
|
+
|
|
6891
|
+
var all = document.querySelectorAll('button, a[href], td, th, input, select, textarea, img, ul, ol, li, svg, [onclick], [role="button"], [contenteditable], [aria-label], [data-target], [class*="btn"], [class*="list"], [class*="item"], [class*="count"], [class*="num"], [class*="like"], [class*="comment"], [class*="stat"], [class*="card"], [class*="tab"], [class*="menu"], [class*="nav"], [class*="link"], [class*="Link"], [class*="Card"]');
|
|
6892
|
+
|
|
6893
|
+
for (var i = 0; i < all.length && i < 3000; i++) {
|
|
6894
|
+
var el = all[i];
|
|
6895
|
+
var r = el.getBoundingClientRect();
|
|
6896
|
+
if (r.width < 8 || r.height < 8) continue;
|
|
6897
|
+
if (r.x < -50 || r.y < -50 || r.x > window.innerWidth || r.y > window.innerHeight + 200) continue;
|
|
6898
|
+
var style = getComputedStyle(el);
|
|
6899
|
+
if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') continue;
|
|
6900
|
+
|
|
6901
|
+
var type = classifyElement(el);
|
|
6902
|
+
if (!type) continue;
|
|
6903
|
+
|
|
6904
|
+
var id = genId(TYPE_PREFIX[type] || 't', counters[type]);
|
|
6905
|
+
counters[type]++;
|
|
6906
|
+
var colors = COLORS[type];
|
|
6907
|
+
|
|
6908
|
+
// \u6807\u7B7E
|
|
6909
|
+
ctx.fillStyle = colors.fill;
|
|
6910
|
+
ctx.fillRect(r.x - 2, r.y - 14, id.length * 7 + 6, 14);
|
|
6911
|
+
ctx.strokeStyle = '#000';
|
|
6912
|
+
ctx.lineWidth = 1;
|
|
6913
|
+
ctx.strokeRect(r.x - 2, r.y - 14, id.length * 7 + 6, 14);
|
|
6914
|
+
ctx.fillStyle = '#000';
|
|
6915
|
+
ctx.font = 'bold 11px monospace';
|
|
6916
|
+
ctx.fillText(id, r.x + 1, r.y - 4);
|
|
6917
|
+
|
|
6918
|
+
// \u5143\u7D20\u6846\uFF08\u5206\u8272\uFF09
|
|
6919
|
+
ctx.strokeStyle = colors.stroke;
|
|
6920
|
+
ctx.lineWidth = 1.5;
|
|
6921
|
+
ctx.strokeRect(r.x, r.y, r.width, r.height);
|
|
6922
|
+
|
|
6923
|
+
// v4\uFF1A\u67E5\u7236\u7EA7\u6807\u6CE8 ID\uFF08\u5D4C\u5957\u5173\u7CFB\uFF09
|
|
6924
|
+
var parentId = null;
|
|
6925
|
+
var parentNode = el.parentElement;
|
|
6926
|
+
while (parentNode && parentNode !== document.body) {
|
|
6927
|
+
for (var pk in window.__xbTagMap) {
|
|
6928
|
+
if (window.__xbTagMap[pk]._el === parentNode) { parentId = pk; break; }
|
|
6929
|
+
}
|
|
6930
|
+
if (parentId) break;
|
|
6931
|
+
parentNode = parentNode.parentElement;
|
|
6932
|
+
}
|
|
6933
|
+
|
|
6934
|
+
// v6\uFF1A\u8868\u5355\u8BED\u4E49\u2014\u2014\u8BC6\u522B input \u7684\u5173\u8054 label
|
|
6935
|
+
var formLabel = null;
|
|
6936
|
+
if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.tagName === 'SELECT') {
|
|
6937
|
+
var inputId = el.id;
|
|
6938
|
+
if (inputId) {
|
|
6939
|
+
var lbl = document.querySelector('label[for="' + inputId + '"]');
|
|
6940
|
+
if (lbl) formLabel = lbl.textContent.trim();
|
|
6941
|
+
}
|
|
6942
|
+
if (!formLabel) {
|
|
6943
|
+
var aria = el.getAttribute('aria-label');
|
|
6944
|
+
if (aria) formLabel = aria;
|
|
6945
|
+
}
|
|
6946
|
+
if (!formLabel) {
|
|
6947
|
+
var ph = el.getAttribute('placeholder');
|
|
6948
|
+
if (ph) formLabel = '(placeholder) ' + ph;
|
|
6949
|
+
}
|
|
6950
|
+
if (!formLabel) {
|
|
6951
|
+
var parentLbl = el.closest('label');
|
|
6952
|
+
if (parentLbl) formLabel = parentLbl.textContent.trim().slice(0, 30);
|
|
6953
|
+
}
|
|
6954
|
+
if (!formLabel) {
|
|
6955
|
+
var prev = el.previousElementSibling;
|
|
6956
|
+
if (prev && (prev.tagName === 'LABEL' || prev.tagName === 'SPAN' || prev.tagName === 'DIV') && prev.textContent.trim()) {
|
|
6957
|
+
formLabel = '(adjacent) ' + prev.textContent.trim().slice(0, 30);
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
}
|
|
6961
|
+
|
|
6962
|
+
// v7\uFF1A\u8868\u683C\u8BED\u4E49\u2014\u2014\u5355\u5143\u683C \u2192 \u5217\u540D + \u884C\u53F7
|
|
6963
|
+
var tableInfo = null;
|
|
6964
|
+
if (el.tagName === 'TD' || el.tagName === 'TH') {
|
|
6965
|
+
var table = el.closest('table');
|
|
6966
|
+
if (table) {
|
|
6967
|
+
var row = el.closest('tr');
|
|
6968
|
+
var cellIndex = el.cellIndex;
|
|
6969
|
+
var rowIndex = row ? row.rowIndex : -1;
|
|
6970
|
+
// \u627E\u8868\u5934\uFF08thead \u7684 th \u6216\u7B2C\u4E00\u884C\u7684 th\uFF09
|
|
6971
|
+
var header = table.querySelector('thead th:nth-child(' + (cellIndex + 1) + ')') ||
|
|
6972
|
+
table.querySelector('tr:first-child th:nth-child(' + (cellIndex + 1) + ')');
|
|
6973
|
+
var colName = header ? header.textContent.trim() : 'col-' + (cellIndex + 1);
|
|
6974
|
+
tableInfo = { col: colName, colIndex: cellIndex, rowIndex: rowIndex, value: el.textContent.trim().slice(0, 20) };
|
|
6975
|
+
}
|
|
6976
|
+
}
|
|
6977
|
+
|
|
6978
|
+
window.__xbTagMap[id] = {
|
|
6979
|
+
type: type,
|
|
6980
|
+
parent: parentId,
|
|
6981
|
+
_el: el,
|
|
6982
|
+
formLabel: formLabel,
|
|
6983
|
+
table: tableInfo,
|
|
6984
|
+
tagName: el.tagName,
|
|
6985
|
+
text: (el.textContent || '').trim().slice(0, 40),
|
|
6986
|
+
num: (el.textContent || '').trim().match(/[\\d,.]+/)?.[0] || null,
|
|
6987
|
+
rect: { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) },
|
|
6988
|
+
selector: (function(e) {
|
|
6989
|
+
if (e.id) return '#' + e.id;
|
|
6990
|
+
if (e.getAttribute('data-testid')) return '[data-testid="' + e.getAttribute('data-testid') + '"]';
|
|
6991
|
+
var path = [];
|
|
6992
|
+
var node = e;
|
|
6993
|
+
while (node && node !== document.body) {
|
|
6994
|
+
var idx = 1;
|
|
6995
|
+
var sib = node.previousElementSibling;
|
|
6996
|
+
while (sib) { if (sib.tagName === node.tagName) idx++; sib = sib.previousElementSibling; }
|
|
6997
|
+
path.unshift(node.tagName.toLowerCase() + ':nth-of-type(' + idx + ')');
|
|
6998
|
+
node = node.parentElement;
|
|
6999
|
+
}
|
|
7000
|
+
return path.join(' > ');
|
|
7001
|
+
})(el)
|
|
7002
|
+
};
|
|
7003
|
+
}
|
|
7004
|
+
|
|
7005
|
+
// v9\uFF1A\u8DE8 frame \u6807\u6CE8\u2014\u2014\u9012\u5F52\u5904\u7406\u540C\u6E90 iframe \u5185\u7684\u5143\u7D20
|
|
7006
|
+
function tagFrame(doc, offsetX, offsetY) {
|
|
7007
|
+
var frameAll = doc.querySelectorAll('button, a[href], input, select, textarea, img, [onclick], [role=button], [contenteditable], [aria-label]');
|
|
7008
|
+
for (var fi = 0; fi < frameAll.length && fi < 100; fi++) {
|
|
7009
|
+
var fel = frameAll[fi];
|
|
7010
|
+
var fr = fel.getBoundingClientRect();
|
|
7011
|
+
if (fr.width < 8 || fr.height < 8) continue;
|
|
7012
|
+
var fType = classifyElement(fel);
|
|
7013
|
+
if (!fType) continue;
|
|
7014
|
+
var fId = genId(TYPE_PREFIX[fType] || 't', counters[fType]);
|
|
7015
|
+
counters[fType]++;
|
|
7016
|
+
var fColors = COLORS[fType];
|
|
7017
|
+
// \u5750\u6807\u504F\u79FB\u5230\u4E3B\u6587\u6863 Canvas\uFF08iframe \u5728\u4E3B\u6587\u6863\u4E2D\u7684\u4F4D\u7F6E + \u5143\u7D20\u5728 iframe \u4E2D\u7684\u4F4D\u7F6E\uFF09
|
|
7018
|
+
var fx = fr.x + offsetX, fy = fr.y + offsetY;
|
|
7019
|
+
ctx.fillStyle = fColors.fill;
|
|
7020
|
+
ctx.fillRect(fx - 2, fy - 14, fId.length * 7 + 6, 14);
|
|
7021
|
+
ctx.strokeStyle = '#000'; ctx.lineWidth = 1;
|
|
7022
|
+
ctx.strokeRect(fx - 2, fy - 14, fId.length * 7 + 6, 14);
|
|
7023
|
+
ctx.fillStyle = '#000'; ctx.font = 'bold 11px monospace';
|
|
7024
|
+
ctx.fillText(fId, fx + 1, fy - 4);
|
|
7025
|
+
ctx.strokeStyle = fColors.stroke; ctx.lineWidth = 1.5;
|
|
7026
|
+
ctx.strokeRect(fx, fy, fr.width, fr.height);
|
|
7027
|
+
window.__xbTagMap[fId] = {
|
|
7028
|
+
type: fType, tagName: fel.tagName,
|
|
7029
|
+
text: (fel.textContent||'').trim().slice(0,40),
|
|
7030
|
+
num: (fel.textContent||'').trim().match(/[0-9,.]+/)?.[0] || null,
|
|
7031
|
+
formLabel: (fel.getAttribute('aria-label')||fel.getAttribute('placeholder')||'').slice(0,30) || null,
|
|
7032
|
+
frame: 'iframe',
|
|
7033
|
+
_el: fel,
|
|
7034
|
+
rect: {x:Math.round(fx),y:Math.round(fy),w:Math.round(fr.width),h:Math.round(fr.height)},
|
|
7035
|
+
selector: (function(e){return e.id?'#'+e.id:e.tagName.toLowerCase()}) (fel)
|
|
7036
|
+
};
|
|
7037
|
+
}
|
|
7038
|
+
// \u9012\u5F52\u5904\u7406\u5D4C\u5957 iframe
|
|
7039
|
+
var nestedFrames = doc.querySelectorAll('iframe');
|
|
7040
|
+
for (var nf = 0; nf < nestedFrames.length; nf++) {
|
|
7041
|
+
try {
|
|
7042
|
+
var nestedDoc = nestedFrames[nf].contentDocument;
|
|
7043
|
+
if (!nestedDoc) continue;
|
|
7044
|
+
var nestedRect = nestedFrames[nf].getBoundingClientRect();
|
|
7045
|
+
tagFrame(nestedDoc, nestedRect.x, nestedRect.y);
|
|
7046
|
+
} catch(e) { /* \u8DE8\u57DF iframe \u8DF3\u8FC7 */ }
|
|
7047
|
+
}
|
|
7048
|
+
}
|
|
7049
|
+
// \u904D\u5386\u4E3B\u6587\u6863\u7684\u6240\u6709\u540C\u6E90 iframe
|
|
7050
|
+
var mainFrames = document.querySelectorAll('iframe');
|
|
7051
|
+
for (var mf = 0; mf < mainFrames.length; mf++) {
|
|
7052
|
+
try {
|
|
7053
|
+
var mDoc = mainFrames[mf].contentDocument;
|
|
7054
|
+
if (!mDoc) continue;
|
|
7055
|
+
var mRect = mainFrames[mf].getBoundingClientRect();
|
|
7056
|
+
tagFrame(mDoc, mRect.x, mRect.y);
|
|
7057
|
+
} catch(e) { /* \u8DE8\u57DF\u8DF3\u8FC7 */ }
|
|
7058
|
+
}
|
|
7059
|
+
|
|
7060
|
+
// v8\uFF1A\u52A8\u6001\u6807\u6CE8\u2014\u2014MutationObserver \u76D1\u542C\u65B0\u5143\u7D20\uFF0C\u81EA\u52A8\u8865\u5145\u6807\u6CE8
|
|
7061
|
+
if (window.__xbTagObserver) { window.__xbTagObserver.disconnect(); }
|
|
7062
|
+
window.__xbTagObserver = new MutationObserver(function(mutations) {
|
|
7063
|
+
var needsRetag = false;
|
|
7064
|
+
for (var mi = 0; mi < mutations.length; mi++) {
|
|
7065
|
+
if (mutations[mi].addedNodes.length > 0) { needsRetag = true; break; }
|
|
7066
|
+
}
|
|
7067
|
+
if (!needsRetag) return;
|
|
7068
|
+
// v8.1\uFF1A\u6E05\u7406\u88AB\u79FB\u9664\u5143\u7D20\u7684\u6807\u6CE8\uFF08\u6B7B\u6807\u6CE8\u4F1A\u7559\u5728 Canvas \u4E0A\uFF09
|
|
7069
|
+
for (var ri = 0; ri < mutations.length; ri++) {
|
|
7070
|
+
var removed = mutations[ri].removedNodes;
|
|
7071
|
+
for (var rj = 0; rj < removed.length; rj++) {
|
|
7072
|
+
var removedNode = removed[rj];
|
|
7073
|
+
if (!removedNode.tagName) continue;
|
|
7074
|
+
for (var rk in window.__xbTagMap) {
|
|
7075
|
+
var entry = window.__xbTagMap[rk];
|
|
7076
|
+
if (entry._el === removedNode || (entry._el && removedNode.contains && removedNode.contains(entry._el))) {
|
|
7077
|
+
delete window.__xbTagMap[rk];
|
|
7078
|
+
window.__xbTagStats.total--;
|
|
7079
|
+
}
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
// \u9632\u6296\uFF1A300ms \u5185\u7684\u8FDE\u7EED\u53D8\u5316\u53EA\u89E6\u53D1\u4E00\u6B21\u91CD\u6807\u6CE8
|
|
7084
|
+
clearTimeout(window.__xbTagRetagTimer);
|
|
7085
|
+
window.__xbTagRetagTimer = setTimeout(function() {
|
|
7086
|
+
// \u53EA\u6807\u6CE8\u65B0\u589E\u7684\u53EF\u89C1\u5143\u7D20\uFF08\u4E0D\u91CD\u753B\u6574\u4E2A Canvas\uFF09
|
|
7087
|
+
var ctx2 = document.getElementById('__xb-tag-overlay');
|
|
7088
|
+
if (!ctx2) return;
|
|
7089
|
+
var canvas2 = ctx2.getContext('2d');
|
|
7090
|
+
for (var ni = 0; ni < mutations.length; ni++) {
|
|
7091
|
+
var nodes = mutations[ni].addedNodes;
|
|
7092
|
+
for (var nj = 0; nj < nodes.length; nj++) {
|
|
7093
|
+
var node = nodes[nj];
|
|
7094
|
+
if (!node.getBoundingClientRect) continue;
|
|
7095
|
+
var r = node.getBoundingClientRect();
|
|
7096
|
+
if (r.width < 8 || r.height < 8) continue;
|
|
7097
|
+
// \u5206\u7C7B\u5E76\u6807\u6CE8
|
|
7098
|
+
var newType = classifyElement(node);
|
|
7099
|
+
if (!newType) continue;
|
|
7100
|
+
var newId = genId(TYPE_PREFIX[newType] || 't', counters[newType]);
|
|
7101
|
+
counters[newType]++;
|
|
7102
|
+
var colors = COLORS[newType];
|
|
7103
|
+
canvas2.fillStyle = colors.fill;
|
|
7104
|
+
canvas2.fillRect(r.x - 2, r.y - 14, newId.length * 7 + 6, 14);
|
|
7105
|
+
canvas2.strokeStyle = '#000';
|
|
7106
|
+
canvas2.lineWidth = 1;
|
|
7107
|
+
canvas2.strokeRect(r.x - 2, r.y - 14, newId.length * 7 + 6, 14);
|
|
7108
|
+
canvas2.fillStyle = '#000';
|
|
7109
|
+
canvas2.font = 'bold 11px monospace';
|
|
7110
|
+
canvas2.fillText(newId, r.x + 1, r.y - 4);
|
|
7111
|
+
canvas2.strokeStyle = colors.stroke;
|
|
7112
|
+
canvas2.lineWidth = 1.5;
|
|
7113
|
+
canvas2.strokeRect(r.x, r.y, r.width, r.height);
|
|
7114
|
+
// \u5B58\u6620\u5C04
|
|
7115
|
+
var parentId = null;
|
|
7116
|
+
var parentNode = node.parentElement;
|
|
7117
|
+
while (parentNode && parentNode !== document.body) {
|
|
7118
|
+
for (var pk in window.__xbTagMap) {
|
|
7119
|
+
if (window.__xbTagMap[pk]._el === parentNode) { parentId = pk; break; }
|
|
7120
|
+
}
|
|
7121
|
+
if (parentId) break;
|
|
7122
|
+
parentNode = parentNode.parentElement;
|
|
7123
|
+
}
|
|
7124
|
+
window.__xbTagMap[newId] = { type: newType, tagName: node.tagName, text: (node.textContent||'').trim().slice(0,40), parent: parentId, _el: node, rect: {x:Math.round(r.x),y:Math.round(r.y),w:Math.round(r.width),h:Math.round(r.height)} };
|
|
7125
|
+
window.__xbTagStats.total++;
|
|
7126
|
+
}
|
|
7127
|
+
}
|
|
7128
|
+
// \u66F4\u65B0 serializable
|
|
7129
|
+
var ser = {};
|
|
7130
|
+
for (var sk2 in window.__xbTagMap) {
|
|
7131
|
+
var item = {};
|
|
7132
|
+
for (var key in window.__xbTagMap[sk2]) { if (key !== '_el') item[key] = window.__xbTagMap[sk2][key]; }
|
|
7133
|
+
ser[sk2] = item;
|
|
7134
|
+
}
|
|
7135
|
+
window.__xbTagSerializable = ser;
|
|
7136
|
+
}, 300);
|
|
7137
|
+
});
|
|
7138
|
+
window.__xbTagObserver.observe(document.body, { childList: true, subtree: true });
|
|
7139
|
+
|
|
7140
|
+
// v4\uFF1A\u751F\u6210\u53EF\u5E8F\u5217\u5316\u7248\u672C\uFF08\u53BB\u6389 _el DOM \u5F15\u7528\uFF09
|
|
7141
|
+
var serializable = {};
|
|
7142
|
+
for (var sk in window.__xbTagMap) {
|
|
7143
|
+
var item = {};
|
|
7144
|
+
for (var key in window.__xbTagMap[sk]) {
|
|
7145
|
+
if (key !== '_el') item[key] = window.__xbTagMap[sk][key];
|
|
7146
|
+
}
|
|
7147
|
+
serializable[sk] = item;
|
|
7148
|
+
}
|
|
7149
|
+
window.__xbTagSerializable = serializable;
|
|
7150
|
+
window.__xbTagStats = { total: Object.keys(window.__xbTagMap).length, byType: counters };
|
|
7151
|
+
return JSON.stringify(window.__xbTagStats);
|
|
7152
|
+
})()
|
|
7153
|
+
`;
|
|
7154
|
+
var visualTagV2Command = registerCommand({
|
|
7155
|
+
name: "visual-tag-v2",
|
|
7156
|
+
description: "\u5206\u8272\u6807\u6CE8\u9875\u9762\u5143\u7D20\uFF08\u7EA2=\u53EF\u70B9\u51FB \u84DD=\u8F93\u5165 \u7EFF=\u56FE\u7247 \u9EC4=\u5217\u8868 \u7D2B=\u6570\u5B57 \u6A59=\u6587\u672C\uFF09",
|
|
7157
|
+
scope: "page",
|
|
7158
|
+
parameters: z30.object({
|
|
7159
|
+
action: z30.enum(["tag", "lookup", "clear", "stats", "by-type", "find", "export", "interact"]),
|
|
7160
|
+
id: z30.string().optional().describe("lookup \u65F6\u6307\u5B9A\u8981\u67E5\u7684 ID"),
|
|
7161
|
+
query: z30.string().optional().describe('find \u65F6\u6307\u5B9A\u641C\u7D22\u8BCD\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09'),
|
|
7162
|
+
type: z30.string().optional().describe("by-type \u65F6\u8FC7\u6EE4\u7C7B\u578B\uFF1Aclick/input/img/list/count/text"),
|
|
7163
|
+
"interact-action": z30.enum(["click", "fill", "read"]).optional().describe("interact \u52A8\u4F5C\u7C7B\u578B"),
|
|
7164
|
+
value: z30.string().optional().describe("fill \u65F6\u7684\u586B\u5145\u503C")
|
|
7165
|
+
}),
|
|
7166
|
+
result: z30.object({
|
|
7167
|
+
action: z30.string(),
|
|
7168
|
+
total: z30.number().optional(),
|
|
7169
|
+
byType: z30.record(z30.number()).optional(),
|
|
7170
|
+
element: z30.record(z30.unknown()).optional()
|
|
7171
|
+
}),
|
|
7172
|
+
handler: async (p, ctx) => {
|
|
7173
|
+
switch (p.action) {
|
|
7174
|
+
case "tag": {
|
|
7175
|
+
const result = await ctx.page.evaluate(TAG_V2_SCRIPT);
|
|
7176
|
+
const parsed = JSON.parse(result);
|
|
7177
|
+
return ok29({ action: "tag", total: parsed.total, byType: parsed.byType });
|
|
7178
|
+
}
|
|
7179
|
+
case "lookup": {
|
|
7180
|
+
if (!p.id) return fail14("lookup \u9700\u8981 --id");
|
|
7181
|
+
const result = await ctx.page.evaluate(
|
|
7182
|
+
`(function(){var m=window.__xbTagMap;if(!m)return JSON.stringify({err:'no-map'});var e=m[${JSON.stringify(p.id)}];return e?JSON.stringify(e):JSON.stringify({err:'not-found'})})()`
|
|
7183
|
+
);
|
|
7184
|
+
const parsed = JSON.parse(result);
|
|
7185
|
+
if (parsed.err) return fail14(`ID ${p.id}: ${parsed.err}`);
|
|
7186
|
+
return ok29({ action: "lookup", id: p.id, element: parsed });
|
|
7187
|
+
}
|
|
7188
|
+
case "by-type": {
|
|
7189
|
+
const result = await ctx.page.evaluate(
|
|
7190
|
+
`(function(){var m=window.__xbTagMap;if(!m)return'{}';var out={};for(var k in m){if(!${JSON.stringify(p.type || "")}||m[k].type===${JSON.stringify(p.type || "")}){out[k]={type:m[k].type,text:m[k].text,num:m[k].num,label:m[k].formLabel}}}return JSON.stringify(out)})()`
|
|
7191
|
+
);
|
|
7192
|
+
return ok29({ action: "by-type", element: JSON.parse(result) });
|
|
7193
|
+
}
|
|
7194
|
+
case "find": {
|
|
7195
|
+
const query = p.query;
|
|
7196
|
+
if (!query) return fail14('find \u9700\u8981 --query \u53C2\u6570\uFF08\u5982 "\u627E\u6709AI\u7F16\u7A0B\u6807\u7B7E\u7684\u5361\u7247"\uFF09');
|
|
7197
|
+
const result = await ctx.page.evaluate(
|
|
7198
|
+
`(function(){
|
|
7199
|
+
var map = window.__xbTagSerializable;
|
|
7200
|
+
if (!map) return JSON.stringify({err:'no-map'});
|
|
7201
|
+
var query = ${JSON.stringify(query)};
|
|
7202
|
+
var results = [];
|
|
7203
|
+
// 1) \u76F4\u63A5\u6587\u672C\u5339\u914D
|
|
7204
|
+
for (var id in map) {
|
|
7205
|
+
var e = map[id];
|
|
7206
|
+
var text = (e.text || '').toLowerCase();
|
|
7207
|
+
var q = query.toLowerCase();
|
|
7208
|
+
if (text.includes(q)) {
|
|
7209
|
+
results.push({id:id, type:e.type, text:e.text, num:e.num, parent:e.parent, reason:'text-match'});
|
|
7210
|
+
}
|
|
7211
|
+
}
|
|
7212
|
+
// 2) \u7C7B\u578B\u5339\u914D\uFF08query \u542B"\u6309\u94AE"/"\u94FE\u63A5"/"\u56FE\u7247"/"\u6570\u5B57"\u7B49\uFF09
|
|
7213
|
+
var typeMap = {button:'click', link:'click', \u6309\u94AE:'click', \u94FE\u63A5:'click', \u56FE\u7247:'img', image:'img',
|
|
7214
|
+
\u8F93\u5165:'input', input:'input', \u5217\u8868:'list', list:'list', \u5361\u7247:'list', card:'list',
|
|
7215
|
+
\u6570\u5B57:'count', count:'count', \u8BA1\u6570:'count', \u6587\u672C:'text'};
|
|
7216
|
+
for (var tk in typeMap) {
|
|
7217
|
+
if (query.toLowerCase().includes(tk)) {
|
|
7218
|
+
for (var id2 in map) {
|
|
7219
|
+
if (map[id2].type === typeMap[tk]) {
|
|
7220
|
+
results.push({id:id2, type:map[id2].type, text:map[id2].text, num:map[id2].num, parent:map[id2].parent, reason:'type-match:'+tk});
|
|
7221
|
+
}
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
7225
|
+
// 3) \u6570\u5B57\u5339\u914D\uFF08query \u542B\u6570\u5B57\uFF09
|
|
7226
|
+
var numMatch = query.match(/([0-9,.]+)/);
|
|
7227
|
+
if (numMatch && map) {
|
|
7228
|
+
var target = parseFloat(numMatch[1].replace(/,/g,''));
|
|
7229
|
+
for (var id3 in map) {
|
|
7230
|
+
if (map[id3].num && parseFloat(map[id3].num.replace(/,/g,'')) === target) {
|
|
7231
|
+
results.push({id:id3, type:map[id3].type, text:map[id3].text, num:map[id3].num, parent:map[id3].parent, reason:'num-match'});
|
|
7232
|
+
}
|
|
7233
|
+
}
|
|
7234
|
+
}
|
|
7235
|
+
return JSON.stringify({total:results.length, results:results.slice(0,20)});
|
|
7236
|
+
})()`
|
|
7237
|
+
);
|
|
7238
|
+
return ok29({ action: "find", query, element: JSON.parse(result) });
|
|
7239
|
+
}
|
|
7240
|
+
case "stats": {
|
|
7241
|
+
const result = await ctx.page.evaluate(
|
|
7242
|
+
`(function(){return JSON.stringify(window.__xbTagStats||{})})()`
|
|
7243
|
+
);
|
|
7244
|
+
return ok29({ action: "stats", element: JSON.parse(result) });
|
|
7245
|
+
}
|
|
7246
|
+
case "interact": {
|
|
7247
|
+
const query = p.query;
|
|
7248
|
+
const pAny = p;
|
|
7249
|
+
const action = pAny["interact-action"] || pAny.interactAction || pAny.interact_action;
|
|
7250
|
+
const value = pAny.value;
|
|
7251
|
+
if (!query) return fail14("interact \u9700\u8981 --query \u53C2\u6570");
|
|
7252
|
+
if (!action) return fail14("interact \u9700\u8981 --interact-action \u53C2\u6570\uFF08click/fill/read\uFF09");
|
|
7253
|
+
const findResult = await ctx.page.evaluate(
|
|
7254
|
+
`(function(){
|
|
7255
|
+
var map = window.__xbTagSerializable;
|
|
7256
|
+
if (!map) return JSON.stringify({err:'no-map'});
|
|
7257
|
+
var query = ${JSON.stringify(query)};
|
|
7258
|
+
var results = [];
|
|
7259
|
+
for (var id in map) {
|
|
7260
|
+
var e = map[id];
|
|
7261
|
+
var text = (e.text || '').toLowerCase();
|
|
7262
|
+
if (text.includes(query.toLowerCase())) {
|
|
7263
|
+
results.push({id:id, type:e.type, text:e.text, num:e.num, label:e.formLabel});
|
|
7264
|
+
}
|
|
7265
|
+
}
|
|
7266
|
+
// \u7C7B\u578B\u5339\u914D
|
|
7267
|
+
var typeMap = {button:'click', link:'click', \u6309\u94AE:'click', \u56FE\u7247:'img', image:'img',
|
|
7268
|
+
\u8F93\u5165:'input', input:'input', \u5217\u8868:'list', \u6570\u5B57:'count', count:'count'};
|
|
7269
|
+
for (var tk in typeMap) {
|
|
7270
|
+
if (query.toLowerCase().includes(tk)) {
|
|
7271
|
+
for (var id2 in map) {
|
|
7272
|
+
if (map[id2].type === typeMap[tk]) {
|
|
7273
|
+
results.push({id:id2, type:map[id2].type, text:map[id2].text, num:map[id2].num, label:map[id2].formLabel});
|
|
7274
|
+
}
|
|
7275
|
+
}
|
|
7276
|
+
}
|
|
7277
|
+
}
|
|
7278
|
+
return JSON.stringify({total:results.length, results:results.slice(0,10)});
|
|
7279
|
+
})()`
|
|
7280
|
+
);
|
|
7281
|
+
const parsed = JSON.parse(findResult);
|
|
7282
|
+
if (parsed.err) return fail14(parsed.err);
|
|
7283
|
+
if (!parsed.total || !parsed.results?.length) return fail14(`\u672A\u627E\u5230\u5339\u914D "${query}" \u7684\u5143\u7D20`);
|
|
7284
|
+
const target = parsed.results[0];
|
|
7285
|
+
if (action === "read") {
|
|
7286
|
+
return ok29({ action: "interact", query, target, result: { read: target.text || target.label } });
|
|
7287
|
+
}
|
|
7288
|
+
if (action === "click") {
|
|
7289
|
+
const el = await ctx.page.evaluate(
|
|
7290
|
+
`(function(){
|
|
7291
|
+
var map = window.__xbTagMap;
|
|
7292
|
+
if (!map) return null;
|
|
7293
|
+
var entry = map[${JSON.stringify(target.id)}];
|
|
7294
|
+
if (!entry || !entry._el) return null;
|
|
7295
|
+
var r = entry._el.getBoundingClientRect();
|
|
7296
|
+
return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
|
|
7297
|
+
})()`
|
|
7298
|
+
);
|
|
7299
|
+
if (!el) return fail14(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
|
|
7300
|
+
await ctx.page.mouse.click(el.x, el.y, { stealth: true });
|
|
7301
|
+
return ok29({ action: "interact", query, target, result: { clicked: true, x: el.x, y: el.y } });
|
|
7302
|
+
}
|
|
7303
|
+
if (action === "fill") {
|
|
7304
|
+
if (!value) return fail14("fill \u9700\u8981 --value \u53C2\u6570");
|
|
7305
|
+
const el = await ctx.page.evaluate(
|
|
7306
|
+
`(function(){
|
|
7307
|
+
var map = window.__xbTagMap;
|
|
7308
|
+
if (!map) return null;
|
|
7309
|
+
var entry = map[${JSON.stringify(target.id)}];
|
|
7310
|
+
if (!entry || !entry._el) return null;
|
|
7311
|
+
var r = entry._el.getBoundingClientRect();
|
|
7312
|
+
return {x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)};
|
|
7313
|
+
})()`
|
|
7314
|
+
);
|
|
7315
|
+
if (!el) return fail14(`\u5143\u7D20 ${target.id} \u4E0D\u53EF\u4EA4\u4E92`);
|
|
7316
|
+
await ctx.page.mouse.click(el.x, el.y, { stealth: true });
|
|
7317
|
+
await ctx.page.keyboard.type(value, { stealth: true });
|
|
7318
|
+
return ok29({ action: "interact", query, target, result: { filled: true, value } });
|
|
7319
|
+
}
|
|
7320
|
+
return fail14(`\u672A\u77E5 action: ${action}`);
|
|
7321
|
+
}
|
|
7322
|
+
case "export": {
|
|
7323
|
+
const result = await ctx.page.evaluate(
|
|
7324
|
+
`(function(){
|
|
7325
|
+
var map = window.__xbTagSerializable;
|
|
7326
|
+
if (!map) return JSON.stringify({err:'no-map'});
|
|
7327
|
+
// \u6309 type \u5206\u7EC4\u7EDF\u8BA1
|
|
7328
|
+
var byType = {};
|
|
7329
|
+
for (var id in map) {
|
|
7330
|
+
var t = map[id].type || 'unknown';
|
|
7331
|
+
byType[t] = (byType[t] || 0) + 1;
|
|
7332
|
+
}
|
|
7333
|
+
// \u6784\u5EFA\u5C42\u7EA7\u6811\uFF08parent \u2192 children\uFF09
|
|
7334
|
+
var tree = {};
|
|
7335
|
+
var roots = [];
|
|
7336
|
+
for (var id2 in map) {
|
|
7337
|
+
var parent = map[id2].parent;
|
|
7338
|
+
if (parent && map[parent]) {
|
|
7339
|
+
if (!tree[parent]) tree[parent] = [];
|
|
7340
|
+
tree[parent].push(id2);
|
|
7341
|
+
} else {
|
|
7342
|
+
roots.push(id2);
|
|
7343
|
+
}
|
|
7344
|
+
}
|
|
7345
|
+
// elements \u5BFC\u51FA\u6458\u8981\uFF08\u5B8C\u6574 DOM \u6620\u5C04\u592A\u5927\uFF0C\u53EA\u5BFC\u6838\u5FC3\u5B57\u6BB5\uFF09
|
|
7346
|
+
var elementsOut = {};
|
|
7347
|
+
for (var id3 in map) {
|
|
7348
|
+
elementsOut[id3] = {
|
|
7349
|
+
type: map[id3].type,
|
|
7350
|
+
text: (map[id3].text || '').slice(0, 20),
|
|
7351
|
+
num: map[id3].num,
|
|
7352
|
+
label: map[id3].formLabel,
|
|
7353
|
+
frame: map[id3].frame,
|
|
7354
|
+
parent: map[id3].parent,
|
|
7355
|
+
table: map[id3].table ? {col: map[id3].table.col, row: map[id3].table.rowIndex} : null
|
|
7356
|
+
};
|
|
7357
|
+
}
|
|
7358
|
+
return JSON.stringify({
|
|
7359
|
+
total: Object.keys(map).length,
|
|
7360
|
+
byType: byType,
|
|
7361
|
+
rootIds: roots.slice(0, 20),
|
|
7362
|
+
hierarchy: Object.keys(tree).slice(0, 50).reduce(function(acc, k) { acc[k] = tree[k]; return acc; }, {}),
|
|
7363
|
+
elements: elementsOut
|
|
7364
|
+
});
|
|
7365
|
+
})()`
|
|
7366
|
+
);
|
|
7367
|
+
const parsed = JSON.parse(result);
|
|
7368
|
+
if (parsed.err) return fail14(String(parsed.err));
|
|
7369
|
+
return ok29({ action: "export", element: parsed });
|
|
7370
|
+
}
|
|
7371
|
+
case "clear": {
|
|
7372
|
+
await ctx.page.evaluate(`(function(){var o=document.getElementById('__xb-tag-overlay');if(o)o.remove();window.__xbTagMap=null;window.__xbTagStats=null;return 'ok'})()`);
|
|
7373
|
+
return ok29({ action: "clear" });
|
|
7374
|
+
}
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7377
|
+
});
|
|
7378
|
+
|
|
6676
7379
|
// src/context.ts
|
|
6677
7380
|
function checkBrowserScope(scope, ctx) {
|
|
6678
7381
|
switch (scope) {
|
|
@@ -7816,7 +8519,7 @@ async function guardCheck(commandName) {
|
|
|
7816
8519
|
}
|
|
7817
8520
|
}
|
|
7818
8521
|
function errorResult(message) {
|
|
7819
|
-
return { ...
|
|
8522
|
+
return { ...fail15(message), duration: 0 };
|
|
7820
8523
|
}
|
|
7821
8524
|
function tipsToMessages(tips) {
|
|
7822
8525
|
if (!tips || tips.length === 0) return [];
|
|
@@ -7896,7 +8599,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
7896
8599
|
}
|
|
7897
8600
|
let targetPageOverride = null;
|
|
7898
8601
|
if (_target && extraOpts?.cdpEndpoint) {
|
|
7899
|
-
const { findTargetPage } = await import("./browser-
|
|
8602
|
+
const { findTargetPage } = await import("./browser-TUD2KA5G.js");
|
|
7900
8603
|
targetPageOverride = await findTargetPage(extraOpts.cdpEndpoint, _target);
|
|
7901
8604
|
if (!targetPageOverride) {
|
|
7902
8605
|
return errorResult(`Target "${_target}" not found. Use 'xbrowser targets --cdp ${extraOpts.cdpEndpoint}' to list available pages.`);
|
|
@@ -8092,7 +8795,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8092
8795
|
timestamp: start
|
|
8093
8796
|
});
|
|
8094
8797
|
if (isSuccess) {
|
|
8095
|
-
return { ...
|
|
8798
|
+
return { ...ok30(raw.data, merged.length > 0 ? merged : raw.tips), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
8096
8799
|
}
|
|
8097
8800
|
return { success: false, data: raw.data, message: raw.message, tips: mergedOrRaw, duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
8098
8801
|
}
|
|
@@ -8106,7 +8809,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8106
8809
|
duration,
|
|
8107
8810
|
timestamp: start
|
|
8108
8811
|
});
|
|
8109
|
-
return { ...
|
|
8812
|
+
return { ...ok30(raw, smartTipNormalized), duration, ...hookOutputs ? { hookOutputs } : {} };
|
|
8110
8813
|
} catch (err) {
|
|
8111
8814
|
const end = Date.now();
|
|
8112
8815
|
const duration = end - start;
|
|
@@ -8151,7 +8854,7 @@ async function executeCommand(commandName, params, sessionName = "default", extr
|
|
|
8151
8854
|
duration,
|
|
8152
8855
|
timestamp: start
|
|
8153
8856
|
});
|
|
8154
|
-
return { ...
|
|
8857
|
+
return { ...fail15(errorMessage), duration };
|
|
8155
8858
|
} finally {
|
|
8156
8859
|
}
|
|
8157
8860
|
}
|
|
@@ -8195,7 +8898,7 @@ async function executeChain(input, options) {
|
|
|
8195
8898
|
results.push({
|
|
8196
8899
|
command: cmdName,
|
|
8197
8900
|
raw: cmdStr,
|
|
8198
|
-
...
|
|
8901
|
+
...fail15(`Plugin "${cmdName}" requires a sub-command`),
|
|
8199
8902
|
duration: 0
|
|
8200
8903
|
});
|
|
8201
8904
|
if (type === "and") {
|
|
@@ -8214,7 +8917,7 @@ async function executeChain(input, options) {
|
|
|
8214
8917
|
results.push({
|
|
8215
8918
|
command: cmdName,
|
|
8216
8919
|
raw: cmdStr,
|
|
8217
|
-
...
|
|
8920
|
+
...fail15(`Unknown command "${subCommand}" for plugin "${cmdName}"`),
|
|
8218
8921
|
duration: 0
|
|
8219
8922
|
});
|
|
8220
8923
|
if (type === "and") {
|
|
@@ -8318,7 +9021,7 @@ async function executeChain(input, options) {
|
|
|
8318
9021
|
results.push({
|
|
8319
9022
|
command: `${cmdName} ${subCommand}`,
|
|
8320
9023
|
raw: cmdStr,
|
|
8321
|
-
...
|
|
9024
|
+
...ok30(data),
|
|
8322
9025
|
duration: duration2,
|
|
8323
9026
|
...hookOutputs ? { hookOutputs } : {}
|
|
8324
9027
|
});
|
|
@@ -8346,7 +9049,7 @@ async function executeChain(input, options) {
|
|
|
8346
9049
|
results.push({
|
|
8347
9050
|
command: `${cmdName} ${subCommand}`,
|
|
8348
9051
|
raw: cmdStr,
|
|
8349
|
-
...
|
|
9052
|
+
...fail15(errorMessage),
|
|
8350
9053
|
duration: duration2
|
|
8351
9054
|
});
|
|
8352
9055
|
if (type === "and") {
|
|
@@ -10578,6 +11281,7 @@ var HTML_TAGS = /* @__PURE__ */ new Set([
|
|
|
10578
11281
|
var SELECTOR_DSL_PREFIXES = /^(text=|popup-text=|xpath=|role=|css=|chain=)/;
|
|
10579
11282
|
function normalizeSelector(input) {
|
|
10580
11283
|
if (!input) return input;
|
|
11284
|
+
if (typeof input !== "string") input = String(input);
|
|
10581
11285
|
if (/^[#\.\[\:\/]/.test(input)) return input;
|
|
10582
11286
|
if (input === "*") return input;
|
|
10583
11287
|
if (SELECTOR_DSL_PREFIXES.test(input)) return input;
|
|
@@ -13613,6 +14317,12 @@ function findEvalStart(argv) {
|
|
|
13613
14317
|
async function handleEvalScript(parts, argv) {
|
|
13614
14318
|
const cdpEndpoint = extractCdpFromArgv(argv);
|
|
13615
14319
|
const sessionName = extractSessionNameFromArgv(argv);
|
|
14320
|
+
if (parts[0] === "--script-b64" && parts[1]) {
|
|
14321
|
+
const chainResult2 = await executeChain(`eval --script-b64 ${parts[1]}`, { cdpEndpoint, sessionName });
|
|
14322
|
+
printChainResult(chainResult2);
|
|
14323
|
+
if (!chainResult2.success) throw new Error("Command failed");
|
|
14324
|
+
return;
|
|
14325
|
+
}
|
|
13616
14326
|
let frame;
|
|
13617
14327
|
const scriptLines = [];
|
|
13618
14328
|
for (let i = 0; i < parts.length; i++) {
|
|
@@ -14112,7 +14822,7 @@ Run "xbrowser ${command} ${subCommand} --help" to see available parameters.`
|
|
|
14112
14822
|
const targetPage = pages[cmdTabIndex];
|
|
14113
14823
|
await targetPage.bringToFront().catch(() => {
|
|
14114
14824
|
});
|
|
14115
|
-
const { setActivePage: setActivePage2 } = await import("./browser-
|
|
14825
|
+
const { setActivePage: setActivePage2 } = await import("./browser-TUD2KA5G.js");
|
|
14116
14826
|
setActivePage2(session, targetPage);
|
|
14117
14827
|
}
|
|
14118
14828
|
}
|
|
@@ -17285,7 +17995,7 @@ var DataCollector = class {
|
|
|
17285
17995
|
return results;
|
|
17286
17996
|
}
|
|
17287
17997
|
async createBrowserContext() {
|
|
17288
|
-
const { launch } = await import("./cdp-driver-
|
|
17998
|
+
const { launch } = await import("./cdp-driver-2EECZW4X.js");
|
|
17289
17999
|
const { browser } = await launch({
|
|
17290
18000
|
headless: true,
|
|
17291
18001
|
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|