@quanta-intellect/vessel-browser 0.1.11 → 0.1.13
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/README.md +6 -3
- package/out/main/index.js +4086 -549
- package/out/preload/content-script.js +61 -17
- package/out/preload/index.js +29 -0
- package/out/renderer/assets/{index-DOCQcMR5.css → index-DMd-y6tm.css} +95 -0
- package/out/renderer/assets/{index-BUYEjb3N.js → index-DiB_DxLD.js} +411 -122
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
|
@@ -2128,33 +2128,76 @@ const elementSelectors = {};
|
|
|
2128
2128
|
let indexedElements = /* @__PURE__ */ new WeakMap();
|
|
2129
2129
|
const indexedElementRefs = {};
|
|
2130
2130
|
let activeOverlays = [];
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
const MAX_DEPTH = 3;
|
|
2131
|
+
const MAX_SHADOW_HOSTS = 150;
|
|
2132
|
+
const MAX_SHADOW_DEPTH = 5;
|
|
2133
|
+
const MAX_WALK_ELEMENTS = 1e4;
|
|
2134
|
+
function collectShadowRoots(root) {
|
|
2136
2135
|
const shadowRoots = [];
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2136
|
+
let walked = 0;
|
|
2137
|
+
const walk = (node, depth) => {
|
|
2138
|
+
if (depth > MAX_SHADOW_DEPTH || shadowRoots.length >= MAX_SHADOW_HOSTS) return;
|
|
2139
|
+
const tw = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);
|
|
2140
|
+
let el = tw.nextNode();
|
|
2141
|
+
while (el && walked < MAX_WALK_ELEMENTS && shadowRoots.length < MAX_SHADOW_HOSTS) {
|
|
2142
|
+
walked++;
|
|
2142
2143
|
if (el.shadowRoot) {
|
|
2143
2144
|
shadowRoots.push(el.shadowRoot);
|
|
2144
|
-
|
|
2145
|
-
}
|
|
2146
|
-
if (el.children.length > 0 && el.children.length < 200) {
|
|
2147
|
-
findShadowRoots(el, depth);
|
|
2145
|
+
walk(el.shadowRoot, depth + 1);
|
|
2148
2146
|
}
|
|
2147
|
+
el = tw.nextNode();
|
|
2149
2148
|
}
|
|
2150
2149
|
};
|
|
2151
|
-
|
|
2152
|
-
|
|
2150
|
+
walk(root, 0);
|
|
2151
|
+
return shadowRoots;
|
|
2152
|
+
}
|
|
2153
|
+
function deepQuerySelectorAll(selector, root = document) {
|
|
2154
|
+
const results = [];
|
|
2155
|
+
root.querySelectorAll(selector).forEach((el) => results.push(el));
|
|
2156
|
+
for (const sr of collectShadowRoots(root)) {
|
|
2153
2157
|
sr.querySelectorAll(selector).forEach((el) => results.push(el));
|
|
2154
2158
|
}
|
|
2155
2159
|
return results;
|
|
2156
2160
|
}
|
|
2161
|
+
function isInShadowDom(el) {
|
|
2162
|
+
return el.getRootNode() instanceof ShadowRoot;
|
|
2163
|
+
}
|
|
2164
|
+
function generateShadowPiercingSelector(el) {
|
|
2165
|
+
const segments = [];
|
|
2166
|
+
let current = el;
|
|
2167
|
+
while (current) {
|
|
2168
|
+
const rootNode = current.getRootNode();
|
|
2169
|
+
const innerSel = generateStableSelector(current);
|
|
2170
|
+
if (rootNode instanceof ShadowRoot) {
|
|
2171
|
+
segments.unshift(innerSel);
|
|
2172
|
+
current = rootNode.host;
|
|
2173
|
+
} else {
|
|
2174
|
+
segments.unshift(innerSel);
|
|
2175
|
+
break;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
if (segments.length <= 1) return null;
|
|
2179
|
+
return segments.join(" >>> ");
|
|
2180
|
+
}
|
|
2181
|
+
function resolveShadowSelector(selectorPath) {
|
|
2182
|
+
const segments = selectorPath.split(" >>> ").map((s) => s.trim());
|
|
2183
|
+
let scope = document;
|
|
2184
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2185
|
+
const el = scope.querySelector(segments[i]);
|
|
2186
|
+
if (!el) return null;
|
|
2187
|
+
if (i < segments.length - 1) {
|
|
2188
|
+
if (!el.shadowRoot) return null;
|
|
2189
|
+
scope = el.shadowRoot;
|
|
2190
|
+
} else {
|
|
2191
|
+
return el;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
return null;
|
|
2195
|
+
}
|
|
2157
2196
|
function generateSelector(el) {
|
|
2197
|
+
if (isInShadowDom(el)) {
|
|
2198
|
+
const shadowPath = generateShadowPiercingSelector(el);
|
|
2199
|
+
if (shadowPath) return shadowPath;
|
|
2200
|
+
}
|
|
2158
2201
|
return generateStableSelector(el);
|
|
2159
2202
|
}
|
|
2160
2203
|
function assignIndex(el) {
|
|
@@ -2672,7 +2715,7 @@ function extractLandmarks() {
|
|
|
2672
2715
|
"dialog, [role='dialog'], [role='alertdialog']"
|
|
2673
2716
|
];
|
|
2674
2717
|
selectors.forEach((selector) => {
|
|
2675
|
-
|
|
2718
|
+
deepQuerySelectorAll(selector).forEach((el) => {
|
|
2676
2719
|
const tag = el.tagName.toLowerCase();
|
|
2677
2720
|
const role = el.getAttribute("role") || (tag === "header" ? "banner" : tag === "nav" ? "navigation" : tag === "main" ? "main" : tag === "aside" ? "complementary" : tag === "footer" ? "contentinfo" : tag === "article" ? "article" : tag === "section" ? "region" : tag === "dialog" ? "dialog" : "generic");
|
|
2678
2721
|
landmarks.push({
|
|
@@ -2896,6 +2939,7 @@ electron.contextBridge.exposeInMainWorld("__vessel", {
|
|
|
2896
2939
|
extractContent: vesselExtractContent,
|
|
2897
2940
|
getElementSelector: resolveElementSelector,
|
|
2898
2941
|
interactByIndex,
|
|
2942
|
+
resolveShadowSelector,
|
|
2899
2943
|
notifyHighlightSelection: (text) => {
|
|
2900
2944
|
if (typeof text === "string" && text.trim()) {
|
|
2901
2945
|
electron.ipcRenderer.send("vessel:highlight-selection", text.trim());
|
package/out/preload/index.js
CHANGED
|
@@ -35,6 +35,7 @@ const Channels = {
|
|
|
35
35
|
SIDEBAR_RESIZE: "ui:sidebar-resize",
|
|
36
36
|
SIDEBAR_RESIZE_START: "ui:sidebar-resize-start",
|
|
37
37
|
SIDEBAR_RESIZE_COMMIT: "ui:sidebar-resize-commit",
|
|
38
|
+
SIDEBAR_CONTEXT_MENU: "ui:sidebar-context-menu",
|
|
38
39
|
FOCUS_MODE_TOGGLE: "ui:focus-mode-toggle",
|
|
39
40
|
SETTINGS_VISIBILITY: "ui:settings-visibility",
|
|
40
41
|
// Settings
|
|
@@ -47,12 +48,18 @@ const Channels = {
|
|
|
47
48
|
BOOKMARKS_UPDATE: "bookmarks:update",
|
|
48
49
|
BOOKMARK_SAVE: "bookmarks:save",
|
|
49
50
|
BOOKMARK_REMOVE: "bookmarks:remove",
|
|
51
|
+
BOOKMARK_ADD_CONTEXT_TO_CHAT: "bookmarks:add-context-to-chat",
|
|
50
52
|
FOLDER_CREATE: "bookmarks:folder-create",
|
|
51
53
|
FOLDER_REMOVE: "bookmarks:folder-remove",
|
|
52
54
|
FOLDER_RENAME: "bookmarks:folder-rename",
|
|
53
55
|
// Highlights
|
|
54
56
|
HIGHLIGHT_CAPTURE: "highlights:capture",
|
|
55
57
|
HIGHLIGHT_CAPTURE_RESULT: "highlights:capture-result",
|
|
58
|
+
HIGHLIGHT_NAV_COUNT: "highlights:nav-count",
|
|
59
|
+
HIGHLIGHT_NAV_SCROLL: "highlights:nav-scroll",
|
|
60
|
+
HIGHLIGHT_NAV_REMOVE: "highlights:nav-remove",
|
|
61
|
+
HIGHLIGHT_NAV_CLEAR: "highlights:nav-clear",
|
|
62
|
+
SIDEBAR_HIGHLIGHT_ACTION: "highlights:sidebar-action",
|
|
56
63
|
// DevTools panel
|
|
57
64
|
DEVTOOLS_PANEL_TOGGLE: "devtools-panel:toggle",
|
|
58
65
|
DEVTOOLS_PANEL_STATE: "devtools-panel:state",
|
|
@@ -120,6 +127,15 @@ const api = {
|
|
|
120
127
|
const handler = (_, result) => cb(result);
|
|
121
128
|
electron.ipcRenderer.on(Channels.HIGHLIGHT_CAPTURE_RESULT, handler);
|
|
122
129
|
return () => electron.ipcRenderer.removeListener(Channels.HIGHLIGHT_CAPTURE_RESULT, handler);
|
|
130
|
+
},
|
|
131
|
+
getCount: () => electron.ipcRenderer.invoke(Channels.HIGHLIGHT_NAV_COUNT),
|
|
132
|
+
scrollTo: (index) => electron.ipcRenderer.invoke(Channels.HIGHLIGHT_NAV_SCROLL, index),
|
|
133
|
+
remove: (index) => electron.ipcRenderer.invoke(Channels.HIGHLIGHT_NAV_REMOVE, index),
|
|
134
|
+
clearAll: () => electron.ipcRenderer.invoke(Channels.HIGHLIGHT_NAV_CLEAR),
|
|
135
|
+
onSidebarAction: (cb) => {
|
|
136
|
+
const handler = (_, action) => cb(action);
|
|
137
|
+
electron.ipcRenderer.on(Channels.SIDEBAR_HIGHLIGHT_ACTION, handler);
|
|
138
|
+
return () => electron.ipcRenderer.removeListener(Channels.SIDEBAR_HIGHLIGHT_ACTION, handler);
|
|
123
139
|
}
|
|
124
140
|
},
|
|
125
141
|
ui: {
|
|
@@ -127,6 +143,11 @@ const api = {
|
|
|
127
143
|
startSidebarResize: () => electron.ipcRenderer.invoke(Channels.SIDEBAR_RESIZE_START),
|
|
128
144
|
resizeSidebar: (width) => electron.ipcRenderer.invoke(Channels.SIDEBAR_RESIZE, width),
|
|
129
145
|
commitSidebarResize: () => electron.ipcRenderer.invoke(Channels.SIDEBAR_RESIZE_COMMIT),
|
|
146
|
+
onSidebarContextMenu: (cb) => {
|
|
147
|
+
const handler = (_, position) => cb(position);
|
|
148
|
+
electron.ipcRenderer.on(Channels.SIDEBAR_CONTEXT_MENU, handler);
|
|
149
|
+
return () => electron.ipcRenderer.removeListener(Channels.SIDEBAR_CONTEXT_MENU, handler);
|
|
150
|
+
},
|
|
130
151
|
toggleFocusMode: () => electron.ipcRenderer.invoke(Channels.FOCUS_MODE_TOGGLE),
|
|
131
152
|
setSettingsVisibility: (open) => electron.ipcRenderer.invoke(Channels.SETTINGS_VISIBILITY, open)
|
|
132
153
|
},
|
|
@@ -148,6 +169,14 @@ const api = {
|
|
|
148
169
|
createFolderWithSummary: (name, summary) => electron.ipcRenderer.invoke(Channels.FOLDER_CREATE, name, summary),
|
|
149
170
|
removeFolder: (id) => electron.ipcRenderer.invoke(Channels.FOLDER_REMOVE, id),
|
|
150
171
|
renameFolder: (id, newName, summary) => electron.ipcRenderer.invoke(Channels.FOLDER_RENAME, id, newName, summary),
|
|
172
|
+
onAddContextToChat: (cb) => {
|
|
173
|
+
const handler = (_, bookmarkId) => cb(bookmarkId);
|
|
174
|
+
electron.ipcRenderer.on(Channels.BOOKMARK_ADD_CONTEXT_TO_CHAT, handler);
|
|
175
|
+
return () => electron.ipcRenderer.removeListener(
|
|
176
|
+
Channels.BOOKMARK_ADD_CONTEXT_TO_CHAT,
|
|
177
|
+
handler
|
|
178
|
+
);
|
|
179
|
+
},
|
|
151
180
|
onUpdate: (cb) => {
|
|
152
181
|
const handler = (_, state) => cb(state);
|
|
153
182
|
electron.ipcRenderer.on(Channels.BOOKMARKS_UPDATE, handler);
|
|
@@ -2533,6 +2533,101 @@
|
|
|
2533
2533
|
border-color: var(--border-visible);
|
|
2534
2534
|
}
|
|
2535
2535
|
|
|
2536
|
+
/* ═══════════════════════════════════════
|
|
2537
|
+
Highlight navigation bar
|
|
2538
|
+
═══════════════════════════════════════ */
|
|
2539
|
+
|
|
2540
|
+
.highlight-nav {
|
|
2541
|
+
display: flex;
|
|
2542
|
+
align-items: center;
|
|
2543
|
+
justify-content: flex-end;
|
|
2544
|
+
gap: 2px;
|
|
2545
|
+
padding: 4px 14px;
|
|
2546
|
+
flex-shrink: 0;
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
.highlight-nav-btn {
|
|
2550
|
+
display: inline-flex;
|
|
2551
|
+
align-items: center;
|
|
2552
|
+
justify-content: center;
|
|
2553
|
+
width: 24px;
|
|
2554
|
+
height: 24px;
|
|
2555
|
+
padding: 0;
|
|
2556
|
+
color: var(--text-muted);
|
|
2557
|
+
background: transparent;
|
|
2558
|
+
border: 1px solid transparent;
|
|
2559
|
+
border-radius: var(--radius-sm);
|
|
2560
|
+
cursor: pointer;
|
|
2561
|
+
transition: color var(--duration-fast) var(--ease-in-out),
|
|
2562
|
+
background var(--duration-fast) var(--ease-in-out);
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
.highlight-nav-btn:hover:not(:disabled) {
|
|
2566
|
+
color: var(--text-primary);
|
|
2567
|
+
background: var(--bg-tertiary);
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
.highlight-nav-btn:disabled {
|
|
2571
|
+
opacity: 0.3;
|
|
2572
|
+
cursor: default;
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
.highlight-nav-label {
|
|
2576
|
+
display: inline-flex;
|
|
2577
|
+
align-items: center;
|
|
2578
|
+
gap: 5px;
|
|
2579
|
+
padding: 3px 10px;
|
|
2580
|
+
font-size: 11px;
|
|
2581
|
+
font-weight: 500;
|
|
2582
|
+
color: rgba(196, 160, 90, 0.85);
|
|
2583
|
+
background: rgba(196, 160, 90, 0.08);
|
|
2584
|
+
border: 1px solid rgba(196, 160, 90, 0.2);
|
|
2585
|
+
border-radius: var(--radius-md);
|
|
2586
|
+
cursor: pointer;
|
|
2587
|
+
transition: background var(--duration-fast) var(--ease-in-out),
|
|
2588
|
+
border-color var(--duration-fast) var(--ease-in-out);
|
|
2589
|
+
white-space: nowrap;
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
.highlight-nav-label:hover {
|
|
2593
|
+
background: rgba(196, 160, 90, 0.14);
|
|
2594
|
+
border-color: rgba(196, 160, 90, 0.35);
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
.hl-context-menu {
|
|
2598
|
+
position: fixed;
|
|
2599
|
+
z-index: 9999;
|
|
2600
|
+
min-width: 160px;
|
|
2601
|
+
padding: 4px 0;
|
|
2602
|
+
background: var(--bg-secondary);
|
|
2603
|
+
border: 1px solid var(--border-visible);
|
|
2604
|
+
border-radius: var(--radius-md);
|
|
2605
|
+
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
.hl-context-item {
|
|
2609
|
+
display: block;
|
|
2610
|
+
width: 100%;
|
|
2611
|
+
padding: 6px 12px;
|
|
2612
|
+
font-size: 11.5px;
|
|
2613
|
+
color: var(--text-secondary);
|
|
2614
|
+
background: transparent;
|
|
2615
|
+
border: none;
|
|
2616
|
+
cursor: pointer;
|
|
2617
|
+
text-align: left;
|
|
2618
|
+
transition: background var(--duration-fast) var(--ease-in-out);
|
|
2619
|
+
}
|
|
2620
|
+
|
|
2621
|
+
.hl-context-item:hover {
|
|
2622
|
+
background: rgba(255, 255, 255, 0.06);
|
|
2623
|
+
color: var(--text-primary);
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
.hl-context-danger:hover {
|
|
2627
|
+
color: #e06060;
|
|
2628
|
+
background: rgba(224, 96, 96, 0.08);
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2536
2631
|
.sidebar-input-area {
|
|
2537
2632
|
display: flex;
|
|
2538
2633
|
gap: 6px;
|