webtap-tool 0.4.0__tar.gz → 0.5.0__tar.gz
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.
Potentially problematic release.
This version of webtap-tool might be problematic. Click here for more details.
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/CHANGELOG.md +33 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/PKG-INFO +1 -1
- webtap_tool-0.5.0/extension/content.js +97 -0
- webtap_tool-0.5.0/extension/manifest.json +22 -0
- webtap_tool-0.5.0/extension/sidepanel.html +317 -0
- webtap_tool-0.5.0/extension/sidepanel.js +625 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/pyproject.toml +1 -1
- webtap_tool-0.5.0/src/webtap/api.py +591 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/app.py +12 -5
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/session.py +101 -1
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/DEVELOPER_GUIDE.md +108 -22
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/TIPS.md +24 -1
- webtap_tool-0.5.0/src/webtap/commands/_builders.py +265 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/body.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/connection.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/console.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/events.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/fetch.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/inspect.py +1 -2
- webtap_tool-0.5.0/src/webtap/commands/javascript.py +102 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/navigation.py +1 -2
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/network.py +17 -35
- webtap_tool-0.5.0/src/webtap/commands/selections.py +129 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/server.py +1 -0
- webtap_tool-0.5.0/src/webtap/services/dom.py +512 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/main.py +14 -0
- webtap_tool-0.4.0/extension/manifest.json +0 -12
- webtap_tool-0.4.0/extension/popup.html +0 -181
- webtap_tool-0.4.0/extension/popup.js +0 -314
- webtap_tool-0.4.0/src/webtap/api.py +0 -282
- webtap_tool-0.4.0/src/webtap/commands/_builders.py +0 -127
- webtap_tool-0.4.0/src/webtap/commands/_errors.py +0 -108
- webtap_tool-0.4.0/src/webtap/commands/javascript.py +0 -87
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/.gitignore +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/ARCHITECTURE.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/README.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/data/filters.json +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/llms.txt +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/VISION.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/__init__.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/README.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/__init__.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/query.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/schema/README.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/schema/cdp_protocol.json +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/cdp/schema/cdp_version.json +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/__init__.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/_tips.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/_utils.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/filters.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/launch.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/commands/setup.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/filters.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/README.md +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/__init__.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/body.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/console.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/fetch.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/network.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/__init__.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/chrome.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/desktop.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/extension.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/filters.py +0 -0
- {webtap_tool-0.4.0 → webtap_tool-0.5.0}/src/webtap/services/setup/platform.py +0 -0
|
@@ -15,6 +15,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
15
15
|
|
|
16
16
|
### Removed
|
|
17
17
|
|
|
18
|
+
## [0.5.0] - 2025-10-09
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- **Real-time SSE streaming**: API endpoint `/events` for Server-Sent Events broadcasting full state to extension
|
|
22
|
+
- **Element selection**: CDP-native `Overlay.setInspectMode` with visual badges on page
|
|
23
|
+
- New `DOMService` for element inspection via CDP
|
|
24
|
+
- `selections()` command for viewing selected elements with preview and data extraction
|
|
25
|
+
- `content.js` for badge rendering on page
|
|
26
|
+
- Thread-safe selection processing via background ThreadPoolExecutor
|
|
27
|
+
- Auto-clear selections on disconnect and frame navigation
|
|
28
|
+
- **Error state management**: Persistent error banner in extension with dismiss endpoint `/errors/dismiss`
|
|
29
|
+
- **Broadcast queue**: Cross-thread signaling from WebSocket thread → FastAPI event loop via `asyncio.Queue`
|
|
30
|
+
- **Progress indicators**: Extension shows pending count during async element selection
|
|
31
|
+
- **Auto-refresh**: Page list updates on tab activate/create/remove/move events
|
|
32
|
+
- **CDP event callbacks**: `register_event_callback()` system for real-time event handling
|
|
33
|
+
- **js() element integration**: New `selection` parameter to run JavaScript on selected elements
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
- **Extension architecture**: Migrated from popup (popup.html/popup.js) to side panel (sidepanel.html/sidepanel.js)
|
|
37
|
+
- **State propagation**: Replaced 2-second polling with SSE streaming (<100ms latency vs 2s worst-case)
|
|
38
|
+
- **API server**: Hybrid REST + SSE architecture with broadcast processor and graceful SSE client shutdown
|
|
39
|
+
- **Page list**: Increased size from 6 to 15 rows, auto-highlights connected page
|
|
40
|
+
- **CDP session**: Increased ping timeout from 10s to 20s, added 1-second debounce on event broadcasts
|
|
41
|
+
- **Response builders**: Consolidated `_errors.py` functionality into `_builders.py` with enhanced helpers
|
|
42
|
+
- **Cleanup flow**: `app.cleanup()` now calls `service.disconnect()` for proper state cleanup
|
|
43
|
+
- **Thread safety**: All blocking CDP calls in API endpoints wrapped in `asyncio.to_thread()`
|
|
44
|
+
- **Queue initialization**: Uses `threading.Event` for synchronization instead of sleep
|
|
45
|
+
|
|
46
|
+
### Removed
|
|
47
|
+
- **popup.html** and **popup.js**: Replaced by side panel architecture
|
|
48
|
+
- **_errors.py**: Merged into `_builders.py` for cleaner response builder consolidation
|
|
49
|
+
- **2-second polling**: Extension no longer polls `/status` endpoint
|
|
50
|
+
|
|
18
51
|
## [0.4.0] - 2025-09-28
|
|
19
52
|
|
|
20
53
|
### Added
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// WebTap Badge Renderer - Displays element selection badges only
|
|
2
|
+
// All element selection logic moved to CDP backend
|
|
3
|
+
|
|
4
|
+
console.log("[WebTap] Badge renderer loaded");
|
|
5
|
+
|
|
6
|
+
// Track rendered badges - Map<selectionId, badgeElement>
|
|
7
|
+
const renderedBadges = new Map();
|
|
8
|
+
|
|
9
|
+
// Listen for badge updates from side panel
|
|
10
|
+
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|
11
|
+
console.log("[WebTap] Received message:", msg.action);
|
|
12
|
+
|
|
13
|
+
if (msg.action === "ping") {
|
|
14
|
+
// Health check - respond immediately
|
|
15
|
+
sendResponse({ ready: true });
|
|
16
|
+
} else if (msg.action === "updateBadges") {
|
|
17
|
+
updateBadges(msg.selections);
|
|
18
|
+
sendResponse({ success: true });
|
|
19
|
+
} else if (msg.action === "clearBadges") {
|
|
20
|
+
clearAllBadges();
|
|
21
|
+
sendResponse({ success: true });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return true; // Keep channel open for async response
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Update badges incrementally - add new, remove deleted
|
|
29
|
+
*/
|
|
30
|
+
function updateBadges(selections) {
|
|
31
|
+
const selectionIds = new Set(Object.keys(selections));
|
|
32
|
+
|
|
33
|
+
// Add new badges
|
|
34
|
+
Object.entries(selections).forEach(([id, data]) => {
|
|
35
|
+
if (!renderedBadges.has(id) && data.badge) {
|
|
36
|
+
const badge = createBadge(id, data.badge.x, data.badge.y);
|
|
37
|
+
renderedBadges.set(id, badge);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Remove badges for deleted selections
|
|
42
|
+
renderedBadges.forEach((badge, id) => {
|
|
43
|
+
if (!selectionIds.has(id)) {
|
|
44
|
+
badge.remove();
|
|
45
|
+
renderedBadges.delete(id);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
console.log(`[WebTap] Badges updated: ${renderedBadges.size} active`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create a badge element at specified position
|
|
54
|
+
*/
|
|
55
|
+
function createBadge(id, x, y) {
|
|
56
|
+
const badge = document.createElement("div");
|
|
57
|
+
badge.className = "webtap-badge";
|
|
58
|
+
badge.dataset.selectionId = id;
|
|
59
|
+
badge.textContent = `#${id}`;
|
|
60
|
+
|
|
61
|
+
// Position with scroll offset
|
|
62
|
+
badge.style.cssText = `
|
|
63
|
+
position: absolute;
|
|
64
|
+
top: ${y + window.scrollY}px;
|
|
65
|
+
left: ${x}px;
|
|
66
|
+
background: #4CAF50;
|
|
67
|
+
color: white;
|
|
68
|
+
padding: 4px 8px;
|
|
69
|
+
border-radius: 4px;
|
|
70
|
+
font: bold 12px monospace;
|
|
71
|
+
z-index: 2147483647;
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.3);
|
|
74
|
+
transition: opacity 0.2s;
|
|
75
|
+
`;
|
|
76
|
+
|
|
77
|
+
document.body.appendChild(badge);
|
|
78
|
+
return badge;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Clear all badges from page
|
|
83
|
+
*/
|
|
84
|
+
function clearAllBadges() {
|
|
85
|
+
renderedBadges.forEach((badge) => {
|
|
86
|
+
if (badge.parentNode) {
|
|
87
|
+
badge.parentNode.removeChild(badge);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
renderedBadges.clear();
|
|
91
|
+
console.log("[WebTap] All badges cleared");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Clear badges on navigation
|
|
95
|
+
window.addEventListener("beforeunload", () => {
|
|
96
|
+
clearAllBadges();
|
|
97
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "WebTap DevTools",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"description": "Chrome DevTools Protocol debugger via WebTap",
|
|
6
|
+
"permissions": ["activeTab", "tabs", "scripting", "sidePanel"],
|
|
7
|
+
"side_panel": {
|
|
8
|
+
"default_path": "sidepanel.html"
|
|
9
|
+
},
|
|
10
|
+
"action": {
|
|
11
|
+
"default_title": "WebTap - Open side panel"
|
|
12
|
+
},
|
|
13
|
+
"host_permissions": ["http://localhost:8765/*", "<all_urls>"],
|
|
14
|
+
"content_scripts": [
|
|
15
|
+
{
|
|
16
|
+
"matches": ["<all_urls>"],
|
|
17
|
+
"js": ["content.js"],
|
|
18
|
+
"run_at": "document_idle",
|
|
19
|
+
"all_frames": false
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<style>
|
|
5
|
+
body {
|
|
6
|
+
margin: 0;
|
|
7
|
+
padding: 12px;
|
|
8
|
+
font-family:
|
|
9
|
+
system-ui,
|
|
10
|
+
-apple-system,
|
|
11
|
+
sans-serif;
|
|
12
|
+
font-size: 13px;
|
|
13
|
+
}
|
|
14
|
+
h3 {
|
|
15
|
+
margin: 0 0 12px 0;
|
|
16
|
+
font-size: 15px;
|
|
17
|
+
}
|
|
18
|
+
h4 {
|
|
19
|
+
margin: 12px 0 8px 0;
|
|
20
|
+
font-size: 13px;
|
|
21
|
+
}
|
|
22
|
+
select {
|
|
23
|
+
width: 100%;
|
|
24
|
+
padding: 6px;
|
|
25
|
+
margin-bottom: 8px;
|
|
26
|
+
border: 1px solid #ccc;
|
|
27
|
+
border-radius: 4px;
|
|
28
|
+
font-size: 12px;
|
|
29
|
+
}
|
|
30
|
+
button {
|
|
31
|
+
padding: 8px;
|
|
32
|
+
border: 1px solid #ccc;
|
|
33
|
+
border-radius: 4px;
|
|
34
|
+
background: white;
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
font-size: 12px;
|
|
37
|
+
}
|
|
38
|
+
button:hover {
|
|
39
|
+
background: #f0f0f0;
|
|
40
|
+
}
|
|
41
|
+
button:disabled {
|
|
42
|
+
opacity: 0.5;
|
|
43
|
+
cursor: not-allowed;
|
|
44
|
+
}
|
|
45
|
+
.button-row {
|
|
46
|
+
display: flex;
|
|
47
|
+
gap: 5px;
|
|
48
|
+
margin-bottom: 8px;
|
|
49
|
+
}
|
|
50
|
+
.button-row button {
|
|
51
|
+
flex: 1;
|
|
52
|
+
}
|
|
53
|
+
#status {
|
|
54
|
+
padding: 8px;
|
|
55
|
+
font-size: 12px;
|
|
56
|
+
background: #f5f5f5;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
margin-bottom: 8px;
|
|
59
|
+
}
|
|
60
|
+
.error {
|
|
61
|
+
color: #d00;
|
|
62
|
+
}
|
|
63
|
+
.connected {
|
|
64
|
+
color: #080;
|
|
65
|
+
font-weight: bold;
|
|
66
|
+
}
|
|
67
|
+
.divider {
|
|
68
|
+
border-top: 1px solid #ddd;
|
|
69
|
+
margin: 12px 0;
|
|
70
|
+
}
|
|
71
|
+
.fetch-row {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: space-between;
|
|
75
|
+
padding: 5px 0;
|
|
76
|
+
}
|
|
77
|
+
.fetch-status {
|
|
78
|
+
font-size: 12px;
|
|
79
|
+
}
|
|
80
|
+
.toggle {
|
|
81
|
+
background: #e0e0e0;
|
|
82
|
+
border: 1px solid #ccc;
|
|
83
|
+
border-radius: 4px;
|
|
84
|
+
padding: 4px 12px;
|
|
85
|
+
cursor: pointer;
|
|
86
|
+
}
|
|
87
|
+
.toggle.on {
|
|
88
|
+
background: #4caf50;
|
|
89
|
+
color: white;
|
|
90
|
+
}
|
|
91
|
+
.filter-section label {
|
|
92
|
+
display: block;
|
|
93
|
+
padding: 4px 0;
|
|
94
|
+
font-size: 12px;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
}
|
|
97
|
+
.filter-section input[type="checkbox"] {
|
|
98
|
+
margin-right: 6px;
|
|
99
|
+
}
|
|
100
|
+
.filter-count {
|
|
101
|
+
color: #666;
|
|
102
|
+
font-size: 11px;
|
|
103
|
+
margin-left: 4px;
|
|
104
|
+
}
|
|
105
|
+
.selection-list {
|
|
106
|
+
max-height: 150px;
|
|
107
|
+
overflow-y: auto;
|
|
108
|
+
margin: 8px 0;
|
|
109
|
+
border: 1px solid #ddd;
|
|
110
|
+
border-radius: 4px;
|
|
111
|
+
background: #fafafa;
|
|
112
|
+
}
|
|
113
|
+
.selection-item {
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
padding: 6px 8px;
|
|
117
|
+
font-size: 11px;
|
|
118
|
+
border-bottom: 1px solid #eee;
|
|
119
|
+
}
|
|
120
|
+
.selection-item:last-child {
|
|
121
|
+
border-bottom: none;
|
|
122
|
+
}
|
|
123
|
+
.selection-badge {
|
|
124
|
+
background: #4caf50;
|
|
125
|
+
color: white;
|
|
126
|
+
padding: 2px 5px;
|
|
127
|
+
border-radius: 3px;
|
|
128
|
+
font-weight: bold;
|
|
129
|
+
margin-right: 8px;
|
|
130
|
+
font-size: 10px;
|
|
131
|
+
}
|
|
132
|
+
.selection-preview {
|
|
133
|
+
flex: 1;
|
|
134
|
+
color: #333;
|
|
135
|
+
overflow: hidden;
|
|
136
|
+
text-overflow: ellipsis;
|
|
137
|
+
white-space: nowrap;
|
|
138
|
+
}
|
|
139
|
+
.selection-remove {
|
|
140
|
+
background: #f44336;
|
|
141
|
+
color: white;
|
|
142
|
+
border: none;
|
|
143
|
+
padding: 2px 6px;
|
|
144
|
+
border-radius: 3px;
|
|
145
|
+
cursor: pointer;
|
|
146
|
+
font-size: 10px;
|
|
147
|
+
}
|
|
148
|
+
.selection-remove:hover {
|
|
149
|
+
background: #d32f2f;
|
|
150
|
+
}
|
|
151
|
+
.help-text {
|
|
152
|
+
font-size: 11px;
|
|
153
|
+
color: #666;
|
|
154
|
+
margin-top: 8px;
|
|
155
|
+
padding: 8px;
|
|
156
|
+
background: #f9f9f9;
|
|
157
|
+
border-radius: 4px;
|
|
158
|
+
border: 1px solid #e0e0e0;
|
|
159
|
+
}
|
|
160
|
+
.help-text code {
|
|
161
|
+
background: #e8e8e8;
|
|
162
|
+
padding: 2px 4px;
|
|
163
|
+
border-radius: 2px;
|
|
164
|
+
font-family: monospace;
|
|
165
|
+
font-size: 10px;
|
|
166
|
+
}
|
|
167
|
+
.error-banner {
|
|
168
|
+
display: none;
|
|
169
|
+
background: #ffebee;
|
|
170
|
+
border: 1px solid #ef5350;
|
|
171
|
+
border-radius: 4px;
|
|
172
|
+
padding: 10px;
|
|
173
|
+
margin-bottom: 12px;
|
|
174
|
+
font-size: 12px;
|
|
175
|
+
}
|
|
176
|
+
.error-banner.visible {
|
|
177
|
+
display: block;
|
|
178
|
+
}
|
|
179
|
+
.error-banner-header {
|
|
180
|
+
display: flex;
|
|
181
|
+
justify-content: space-between;
|
|
182
|
+
align-items: flex-start;
|
|
183
|
+
}
|
|
184
|
+
.error-banner-message {
|
|
185
|
+
color: #c62828;
|
|
186
|
+
flex: 1;
|
|
187
|
+
margin-right: 8px;
|
|
188
|
+
}
|
|
189
|
+
.error-banner-dismiss {
|
|
190
|
+
background: transparent;
|
|
191
|
+
border: none;
|
|
192
|
+
color: #c62828;
|
|
193
|
+
cursor: pointer;
|
|
194
|
+
padding: 0;
|
|
195
|
+
font-size: 16px;
|
|
196
|
+
line-height: 1;
|
|
197
|
+
font-weight: bold;
|
|
198
|
+
}
|
|
199
|
+
.error-banner-dismiss:hover {
|
|
200
|
+
color: #b71c1c;
|
|
201
|
+
}
|
|
202
|
+
</style>
|
|
203
|
+
</head>
|
|
204
|
+
<body>
|
|
205
|
+
<h3>WebTap DevTools</h3>
|
|
206
|
+
|
|
207
|
+
<div id="errorBanner" class="error-banner">
|
|
208
|
+
<div class="error-banner-header">
|
|
209
|
+
<div class="error-banner-message" id="errorMessage"></div>
|
|
210
|
+
<button
|
|
211
|
+
class="error-banner-dismiss"
|
|
212
|
+
id="dismissError"
|
|
213
|
+
title="Dismiss error"
|
|
214
|
+
>
|
|
215
|
+
✕
|
|
216
|
+
</button>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<select id="pageList" size="15">
|
|
221
|
+
<option disabled>Loading pages...</option>
|
|
222
|
+
</select>
|
|
223
|
+
|
|
224
|
+
<div class="button-row">
|
|
225
|
+
<button id="connect">Connect</button>
|
|
226
|
+
<button id="disconnect">Disconnect</button>
|
|
227
|
+
</div>
|
|
228
|
+
|
|
229
|
+
<div id="status">Not connected</div>
|
|
230
|
+
|
|
231
|
+
<div class="divider"></div>
|
|
232
|
+
|
|
233
|
+
<div class="fetch-row">
|
|
234
|
+
<span class="fetch-status"
|
|
235
|
+
>Intercept: <span id="fetchStatus">OFF</span></span
|
|
236
|
+
>
|
|
237
|
+
<button id="fetchToggle" class="toggle">Toggle</button>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<div style="margin-top: 5px; font-size: 11px">
|
|
241
|
+
<label style="cursor: pointer">
|
|
242
|
+
<input type="checkbox" id="responseStage" style="margin-right: 4px" />
|
|
243
|
+
Also pause at Response stage
|
|
244
|
+
</label>
|
|
245
|
+
</div>
|
|
246
|
+
|
|
247
|
+
<div class="button-row" style="margin-top: 8px">
|
|
248
|
+
<button id="clear" style="width: 100%">Clear Events</button>
|
|
249
|
+
</div>
|
|
250
|
+
|
|
251
|
+
<div class="divider"></div>
|
|
252
|
+
|
|
253
|
+
<div class="filter-section">
|
|
254
|
+
<div
|
|
255
|
+
style="
|
|
256
|
+
display: flex;
|
|
257
|
+
justify-content: space-between;
|
|
258
|
+
align-items: center;
|
|
259
|
+
"
|
|
260
|
+
>
|
|
261
|
+
<h4 style="margin: 5px 0">Filters</h4>
|
|
262
|
+
<span id="filterStats" style="font-size: 11px; color: #666"
|
|
263
|
+
>Loading...</span
|
|
264
|
+
>
|
|
265
|
+
</div>
|
|
266
|
+
<div id="filterList" style="margin: 8px 0"></div>
|
|
267
|
+
<div class="button-row" style="margin-top: 8px">
|
|
268
|
+
<button id="enableAllFilters" style="font-size: 11px">
|
|
269
|
+
Enable All
|
|
270
|
+
</button>
|
|
271
|
+
<button id="disableAllFilters" style="font-size: 11px">
|
|
272
|
+
Disable All
|
|
273
|
+
</button>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
<div class="divider"></div>
|
|
278
|
+
|
|
279
|
+
<div class="filter-section">
|
|
280
|
+
<h4 style="margin: 5px 0">Element Selection</h4>
|
|
281
|
+
|
|
282
|
+
<button id="startSelection" style="width: 100%; margin: 8px 0">
|
|
283
|
+
Start Selection Mode
|
|
284
|
+
</button>
|
|
285
|
+
|
|
286
|
+
<div id="selectionStatus" style="display: none">
|
|
287
|
+
<div
|
|
288
|
+
style="
|
|
289
|
+
display: flex;
|
|
290
|
+
justify-content: space-between;
|
|
291
|
+
align-items: center;
|
|
292
|
+
margin-bottom: 4px;
|
|
293
|
+
"
|
|
294
|
+
>
|
|
295
|
+
<span style="font-size: 12px"
|
|
296
|
+
>Selected: <strong id="selectionCount">0</strong> elements</span
|
|
297
|
+
>
|
|
298
|
+
<button
|
|
299
|
+
id="clearSelections"
|
|
300
|
+
style="padding: 4px 8px; font-size: 11px"
|
|
301
|
+
>
|
|
302
|
+
Clear
|
|
303
|
+
</button>
|
|
304
|
+
</div>
|
|
305
|
+
|
|
306
|
+
<div id="selectionList" class="selection-list"></div>
|
|
307
|
+
|
|
308
|
+
<div class="help-text">
|
|
309
|
+
Use <code>@webtap:webtap://selections</code> in Claude Code prompts to
|
|
310
|
+
analyze selected elements. Reference elements as #1, #2, etc.
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<script src="sidepanel.js"></script>
|
|
316
|
+
</body>
|
|
317
|
+
</html>
|