@reticlehq/browser 2.14.0 → 3.2.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/actions/actions-dom.d.ts +9 -0
- package/dist/actions/actions-dom.js +81 -28
- package/dist/actions/actions-press.d.ts +4 -0
- package/dist/actions/actions-press.js +46 -0
- package/dist/actions/actions.d.ts +1 -0
- package/dist/actions/actions.js +50 -13
- package/dist/actions/appeared-text.js +6 -0
- package/dist/actions/scroll.d.ts +8 -1
- package/dist/actions/scroll.js +28 -10
- package/dist/commands/commands.js +10 -3
- package/dist/dom/a11y.js +2 -2
- package/dist/dom/desktop-capture.js +1 -1
- package/dist/dom/dom-ignore.js +1 -1
- package/dist/dom/occlusion.js +31 -5
- package/dist/dom/paint-context.d.ts +6 -0
- package/dist/dom/paint-context.js +38 -0
- package/dist/dom/query.js +24 -7
- package/dist/dom/snapshot.js +1 -1
- package/dist/edit-epoch.d.ts +1 -1
- package/dist/edit-epoch.js +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +3 -5
- package/dist/observers/animation.js +1 -1
- package/dist/observers/blind-spots.js +1 -1
- package/dist/observers/departure.js +16 -8
- package/dist/observers/dialogs.js +1 -1
- package/dist/observers/dom.js +28 -8
- package/dist/observers/download.js +1 -1
- package/dist/observers/health.js +1 -1
- package/dist/observers/{network-body.js → net-detail/network-body.js} +2 -2
- package/dist/observers/network-stream.js +2 -2
- package/dist/observers/network.d.ts +1 -1
- package/dist/observers/network.js +51 -10
- package/dist/observers/scroll.js +2 -2
- package/dist/presenter/chrome/layers.d.ts +2 -0
- package/dist/presenter/chrome/layers.js +2 -0
- package/dist/presenter/chrome/log-kinds.d.ts +12 -0
- package/dist/presenter/chrome/log-kinds.js +7 -0
- package/dist/presenter/{presenter-effects.js → chrome/presenter-effects.js} +1 -1
- package/dist/presenter/{presenter-log.d.ts → chrome/presenter-log.d.ts} +3 -12
- package/dist/presenter/{presenter-log.js → chrome/presenter-log.js} +4 -9
- package/dist/presenter/chrome/presenter-safe-html.d.ts +2 -0
- package/dist/presenter/chrome/presenter-safe-html.js +16 -0
- package/dist/presenter/{presenter-tally.js → chrome/presenter-tally.js} +1 -1
- package/dist/presenter/{presenter-heroicons-data.d.ts → icons/presenter-heroicons-data.d.ts} +1 -0
- package/dist/presenter/{presenter-heroicons-data.js → icons/presenter-heroicons-data.js} +1 -0
- package/dist/presenter/{presenter-icons.d.ts → icons/presenter-icons.d.ts} +1 -0
- package/dist/presenter/{presenter-icons.js → icons/presenter-icons.js} +1 -0
- package/dist/presenter/presenter-account-styles.d.ts +1 -0
- package/dist/presenter/presenter-account-styles.js +99 -0
- package/dist/presenter/presenter-account.d.ts +40 -0
- package/dist/presenter/presenter-account.js +178 -0
- package/dist/presenter/presenter-config.d.ts +9 -2
- package/dist/presenter/presenter-config.js +3 -1
- package/dist/presenter/presenter-controls.d.ts +1 -6
- package/dist/presenter/presenter-controls.js +7 -2
- package/dist/presenter/presenter-dock-layout.js +1 -1
- package/dist/presenter/presenter-drag.d.ts +1 -19
- package/dist/presenter/presenter-drag.js +3 -50
- package/dist/presenter/presenter-glow.js +1 -1
- package/dist/presenter/presenter-hud-position.d.ts +18 -0
- package/dist/presenter/presenter-hud-position.js +50 -0
- package/dist/presenter/presenter-offer.d.ts +25 -0
- package/dist/presenter/presenter-offer.js +87 -0
- package/dist/presenter/presenter-report-styles.js +20 -1
- package/dist/presenter/presenter-report.d.ts +2 -1
- package/dist/presenter/presenter-report.js +31 -23
- package/dist/presenter/presenter-run-state.d.ts +1 -1
- package/dist/presenter/presenter-run-state.js +1 -1
- package/dist/presenter/presenter-settings-styles.js +2 -1
- package/dist/presenter/presenter-settings.d.ts +8 -0
- package/dist/presenter/presenter-settings.js +58 -3
- package/dist/presenter/presenter-shell-styles.js +33 -15
- package/dist/presenter/presenter-shell.d.ts +8 -0
- package/dist/presenter/presenter-shell.js +47 -4
- package/dist/presenter/presenter-styles.d.ts +2 -1
- package/dist/presenter/presenter-styles.js +8 -3
- package/dist/presenter/presenter-workspace.d.ts +4 -0
- package/dist/presenter/presenter-workspace.js +29 -2
- package/dist/presenter/presenter.d.ts +3 -3
- package/dist/presenter/presenter.js +28 -14
- package/dist/presenter/tour/tour-view.d.ts +33 -0
- package/dist/presenter/tour/tour-view.js +192 -0
- package/dist/presenter/tour/tour.d.ts +25 -0
- package/dist/presenter/tour/tour.js +264 -0
- package/dist/recorder/recorder.js +6 -0
- package/dist/registry/declared-channels.d.ts +2 -0
- package/dist/registry/declared-channels.js +14 -0
- package/dist/registry/declared-platform.d.ts +4 -0
- package/dist/registry/declared-platform.js +34 -0
- package/dist/registry/emitter.js +1 -1
- package/dist/registry/store-adapters.js +1 -1
- package/dist/registry/stores.js +1 -1
- package/dist/reticle-presenter-helpers.js +10 -6
- package/dist/reticle-singleton.d.ts +2 -0
- package/dist/reticle-singleton.js +3 -0
- package/dist/reticle.js +99 -35
- package/dist/review/annotator-styles.js +1 -1
- package/dist/review/annotator.js +2 -2
- package/dist/review/mark-anchor.js +3 -3
- package/dist/transport/transport.js +2 -2
- package/package.json +5 -4
- package/dist/presenter/presenter-test-helpers.d.ts +0 -14
- package/dist/presenter/presenter-test-helpers.js +0 -39
- /package/dist/actions/{synthetic-input.d.ts → synthetic/synthetic-input.d.ts} +0 -0
- /package/dist/actions/{synthetic-input.js → synthetic/synthetic-input.js} +0 -0
- /package/dist/dom/{auto-anchor.d.ts → addressing/auto-anchor.d.ts} +0 -0
- /package/dist/dom/{auto-anchor.js → addressing/auto-anchor.js} +0 -0
- /package/dist/dom/{refs.d.ts → addressing/refs.d.ts} +0 -0
- /package/dist/dom/{refs.js → addressing/refs.js} +0 -0
- /package/dist/dom/{source.d.ts → addressing/source.d.ts} +0 -0
- /package/dist/dom/{source.js → addressing/source.js} +0 -0
- /package/dist/observers/{network-body.d.ts → net-detail/network-body.d.ts} +0 -0
- /package/dist/observers/{network-redact.d.ts → net-detail/network-redact.d.ts} +0 -0
- /package/dist/observers/{network-redact.js → net-detail/network-redact.js} +0 -0
- /package/dist/presenter/{overlay.d.ts → chrome/overlay.d.ts} +0 -0
- /package/dist/presenter/{overlay.js → chrome/overlay.js} +0 -0
- /package/dist/presenter/{presenter-brand.d.ts → chrome/presenter-brand.d.ts} +0 -0
- /package/dist/presenter/{presenter-brand.js → chrome/presenter-brand.js} +0 -0
- /package/dist/presenter/{presenter-effects.d.ts → chrome/presenter-effects.d.ts} +0 -0
- /package/dist/presenter/{presenter-hud-chrome.d.ts → chrome/presenter-hud-chrome.d.ts} +0 -0
- /package/dist/presenter/{presenter-hud-chrome.js → chrome/presenter-hud-chrome.js} +0 -0
- /package/dist/presenter/{presenter-report-copy.d.ts → chrome/presenter-report-copy.d.ts} +0 -0
- /package/dist/presenter/{presenter-report-copy.js → chrome/presenter-report-copy.js} +0 -0
- /package/dist/presenter/{presenter-tally.d.ts → chrome/presenter-tally.d.ts} +0 -0
- /package/dist/presenter/{presenter-verbs.d.ts → chrome/presenter-verbs.d.ts} +0 -0
- /package/dist/presenter/{presenter-verbs.js → chrome/presenter-verbs.js} +0 -0
- /package/dist/registry/{adapters.d.ts → stores/adapters.d.ts} +0 -0
- /package/dist/registry/{adapters.js → stores/adapters.js} +0 -0
- /package/dist/timers/{native-console.d.ts → console/native-console.d.ts} +0 -0
- /package/dist/timers/{native-console.js → console/native-console.js} +0 -0
- /package/dist/timers/{native-timers.d.ts → native/native-timers.d.ts} +0 -0
- /package/dist/timers/{native-timers.js → native/native-timers.js} +0 -0
package/dist/dom/query.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { DATA_RETICLE_SOURCE_ATTR, ElementState, QueryBy, REDACTED_VALUE, TRANSPORT_LIMITS, } from '@reticlehq/core';
|
|
2
|
-
import { isFrame, isHtmlElement, isInput, isSelect, isTextArea } from './realm.js';
|
|
2
|
+
import { isElement, isFrame, isHtmlElement, isInput, isSelect, isTextArea } from './realm.js';
|
|
3
3
|
import { capturedRootOf } from './shadow-registry.js';
|
|
4
4
|
import { getAccessibleName, getRole, describe, getStates, isInViewport, isVisible, } from './a11y.js';
|
|
5
5
|
import { isIgnored, isReticleOverlay } from './dom-ignore.js';
|
|
6
6
|
import { isSensitiveKey } from '../security/serialization.js';
|
|
7
7
|
import { declaredTestids } from '../registry/capabilities.js';
|
|
8
|
-
import { identifyComponent } from '../registry/adapters.js';
|
|
9
|
-
import { refs } from './refs.js';
|
|
8
|
+
import { identifyComponent } from '../registry/stores/adapters.js';
|
|
9
|
+
import { refs } from './addressing/refs.js';
|
|
10
10
|
const TESTID_ATTR = 'data-testid';
|
|
11
11
|
const SOURCE_ATTR = DATA_RETICLE_SOURCE_ATTR;
|
|
12
12
|
const MAX_PRESENT_TESTIDS = 12;
|
|
@@ -27,20 +27,35 @@ function fuzzyVisibleText(actual, expected) {
|
|
|
27
27
|
function exactVisibleText(actual, expected) {
|
|
28
28
|
return normaliseVisibleText(actual) === normaliseVisibleText(expected);
|
|
29
29
|
}
|
|
30
|
+
const NON_RENDERED_TAGS = ['script', 'style', 'template', 'noscript'];
|
|
31
|
+
function isNonRendered(el) {
|
|
32
|
+
return NON_RENDERED_TAGS.includes(el.tagName.toLowerCase());
|
|
33
|
+
}
|
|
30
34
|
function directText(el) {
|
|
31
35
|
if (isInput(el)) {
|
|
32
36
|
const type = el.type.toLowerCase();
|
|
33
37
|
if ('submit' === type || 'button' === type || 'reset' === type)
|
|
34
38
|
return el.value;
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
if ('script' === tag || 'style' === tag)
|
|
40
|
+
if (isNonRendered(el))
|
|
38
41
|
return '';
|
|
39
42
|
return Array.from(el.childNodes)
|
|
40
43
|
.filter((node) => Node.TEXT_NODE === node.nodeType)
|
|
41
44
|
.map((node) => node.textContent ?? '')
|
|
42
45
|
.join('');
|
|
43
46
|
}
|
|
47
|
+
function visibleTextOf(el, memo) {
|
|
48
|
+
if (isNonRendered(el) || isIgnored(el) || !isVisible(el, memo))
|
|
49
|
+
return '';
|
|
50
|
+
let text = '';
|
|
51
|
+
for (const node of Array.from(el.childNodes)) {
|
|
52
|
+
if (Node.TEXT_NODE === node.nodeType)
|
|
53
|
+
text += node.textContent ?? '';
|
|
54
|
+
else if (isElement(node))
|
|
55
|
+
text += visibleTextOf(node, memo);
|
|
56
|
+
}
|
|
57
|
+
return text;
|
|
58
|
+
}
|
|
44
59
|
function semanticNameTarget(el) {
|
|
45
60
|
if (isInput(el) || isTextArea(el) || isSelect(el))
|
|
46
61
|
return true;
|
|
@@ -205,7 +220,8 @@ function findCandidates(query) {
|
|
|
205
220
|
if (true === query.self) {
|
|
206
221
|
if (query.scope === undefined)
|
|
207
222
|
return { candidates: [], scopeMissing };
|
|
208
|
-
if (query.text !== undefined &&
|
|
223
|
+
if (query.text !== undefined &&
|
|
224
|
+
!fuzzyVisibleText(visibleTextOf(container, new Map()), query.text)) {
|
|
209
225
|
return { candidates: [], scopeMissing };
|
|
210
226
|
}
|
|
211
227
|
return { candidates: isIgnored(container) ? [] : [container], scopeMissing };
|
|
@@ -342,10 +358,11 @@ function buildPresentRegions(query) {
|
|
|
342
358
|
function splitTextOwner(container, wanted) {
|
|
343
359
|
let best;
|
|
344
360
|
let bestDepth = -1;
|
|
361
|
+
const memo = new Map();
|
|
345
362
|
for (const el of elementsUnder(container)) {
|
|
346
363
|
if (isIgnored(el))
|
|
347
364
|
continue;
|
|
348
|
-
if (!fuzzyVisibleText(el
|
|
365
|
+
if (!fuzzyVisibleText(visibleTextOf(el, memo), wanted))
|
|
349
366
|
continue;
|
|
350
367
|
let depth = 0;
|
|
351
368
|
for (let parent = el.parentElement; parent !== null; parent = parent.parentElement)
|
package/dist/dom/snapshot.js
CHANGED
|
@@ -2,7 +2,7 @@ import { ElementState, SnapshotMode } from '@reticlehq/core';
|
|
|
2
2
|
import { capturedRootOf } from './shadow-registry.js';
|
|
3
3
|
import { isFrame } from './realm.js';
|
|
4
4
|
import { getAccessibleName, getRole, getStates, getValue, isVisible } from './a11y.js';
|
|
5
|
-
import { refs } from './refs.js';
|
|
5
|
+
import { refs } from './addressing/refs.js';
|
|
6
6
|
import { isIgnored, isReticleOverlay } from './dom-ignore.js';
|
|
7
7
|
const INTERACTIVE = new Set([
|
|
8
8
|
'button',
|
package/dist/edit-epoch.d.ts
CHANGED
package/dist/edit-epoch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NO_EDITS_OBSERVED } from '@reticlehq/core';
|
|
2
|
-
import { echoRef, refs } from './dom/refs.js';
|
|
2
|
+
import { echoRef, refs } from './dom/addressing/refs.js';
|
|
3
3
|
const HOT_UPDATE_APPLIED = 'vite:afterUpdate';
|
|
4
4
|
const MAX_NAMED_FILES = 3;
|
|
5
5
|
const STALE_REF_REFUSAL = 'no longer resolves to an element';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const reticle: Reticle;
|
|
1
|
+
export { reticle } from './reticle-singleton.js';
|
|
3
2
|
export { Reticle } from './reticle.js';
|
|
4
3
|
export type { ReticleConnectOptions } from './reticle.js';
|
|
5
4
|
export { SESSION_AUTO } from '@reticlehq/core';
|
|
6
5
|
export { setIgnoreSelectors } from './dom/dom-ignore.js';
|
|
7
|
-
export { registerAdapter, identifyComponent, readComponentState, elementHasHoverHandlers, adapterNames, } from './registry/adapters.js';
|
|
8
|
-
export type { ReticleAdapter, ComponentInfo, ComponentSource } from './registry/adapters.js';
|
|
6
|
+
export { registerAdapter, identifyComponent, readComponentState, elementHasHoverHandlers, adapterNames, } from './registry/stores/adapters.js';
|
|
7
|
+
export type { ReticleAdapter, ComponentInfo, ComponentSource } from './registry/stores/adapters.js';
|
|
9
8
|
export { registerStore, unregisterStore, storeNames, readStores, readStoresWithTruncation, sourceOwner, markAdapterSource, } from './registry/stores.js';
|
|
10
9
|
export type { StoreGetter, StoreLike, StoreSubscribe } from './registry/stores.js';
|
|
11
10
|
export { tanstackQueryStore, jotaiStore, xstateStore, valtioStore, mobxStore, recoilStore, svelteStore, piniaStore, pushStore, } from './registry/store-adapters.js';
|
|
@@ -23,6 +22,6 @@ export type { ChartReport, ChartFinding, CanvasChartData } from './dom/chart.js'
|
|
|
23
22
|
export { matchQuery, runQuery } from './dom/query.js';
|
|
24
23
|
export { executeAction, executeSequence } from './actions/actions.js';
|
|
25
24
|
export { describe, getRole, getAccessibleName, getStates, isVisible } from './dom/a11y.js';
|
|
26
|
-
export { refs, RefRegistry } from './dom/refs.js';
|
|
25
|
+
export { refs, RefRegistry } from './dom/addressing/refs.js';
|
|
27
26
|
export { Annotator, installAnnotator, type AnnotatorDeps } from './review/annotator.js';
|
|
28
27
|
export { resolveMarkAnchor, type MarkAnchor } from './review/mark-anchor.js';
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const globalStore = globalThis;
|
|
3
|
-
export const reticle = (globalStore.__reticleInstance ??= new Reticle());
|
|
1
|
+
export { reticle } from './reticle-singleton.js';
|
|
4
2
|
export { Reticle } from './reticle.js';
|
|
5
3
|
export { SESSION_AUTO } from '@reticlehq/core';
|
|
6
4
|
export { setIgnoreSelectors } from './dom/dom-ignore.js';
|
|
7
|
-
export { registerAdapter, identifyComponent, readComponentState, elementHasHoverHandlers, adapterNames, } from './registry/adapters.js';
|
|
5
|
+
export { registerAdapter, identifyComponent, readComponentState, elementHasHoverHandlers, adapterNames, } from './registry/stores/adapters.js';
|
|
8
6
|
export { registerStore, unregisterStore, storeNames, readStores, readStoresWithTruncation, sourceOwner, markAdapterSource, } from './registry/stores.js';
|
|
9
7
|
export { tanstackQueryStore, jotaiStore, xstateStore, valtioStore, mobxStore, recoilStore, svelteStore, piniaStore, pushStore, } from './registry/store-adapters.js';
|
|
10
8
|
export { registerCapabilities, getCapabilities, hasCapabilities, setCapabilitiesListener, } from './registry/capabilities.js';
|
|
@@ -16,6 +14,6 @@ export { inspectChart, canvasChartData } from './dom/chart.js';
|
|
|
16
14
|
export { matchQuery, runQuery } from './dom/query.js';
|
|
17
15
|
export { executeAction, executeSequence } from './actions/actions.js';
|
|
18
16
|
export { describe, getRole, getAccessibleName, getStates, isVisible } from './dom/a11y.js';
|
|
19
|
-
export { refs, RefRegistry } from './dom/refs.js';
|
|
17
|
+
export { refs, RefRegistry } from './dom/addressing/refs.js';
|
|
20
18
|
export { Annotator, installAnnotator } from './review/annotator.js';
|
|
21
19
|
export { resolveMarkAnchor } from './review/mark-anchor.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventType } from '@reticlehq/core';
|
|
2
|
-
import { refs } from '../dom/refs.js';
|
|
2
|
+
import { refs } from '../dom/addressing/refs.js';
|
|
3
3
|
import { isReticleOverlay } from '../dom/dom-ignore.js';
|
|
4
4
|
export function installAnimation(emit) {
|
|
5
5
|
const ac = new AbortController();
|
|
@@ -2,7 +2,7 @@ import { EventType, BlindSpotKind } from '@reticlehq/core';
|
|
|
2
2
|
import { countUnmountedRows } from '../dom/virtualized.js';
|
|
3
3
|
import { isCaptured } from '../dom/shadow-registry.js';
|
|
4
4
|
import { sameOriginFrameBodies } from './frames.js';
|
|
5
|
-
import { nativeClearTimeout, nativeSetTimeout } from '../timers/native-timers.js';
|
|
5
|
+
import { nativeClearTimeout, nativeSetTimeout } from '../timers/native/native-timers.js';
|
|
6
6
|
export function countClosedShadowRoots() {
|
|
7
7
|
let count = 0;
|
|
8
8
|
for (const el of document.querySelectorAll('*')) {
|
|
@@ -35,15 +35,23 @@ export function installDeparture(emit) {
|
|
|
35
35
|
return;
|
|
36
36
|
const href = anchor.getAttribute('href') ?? '';
|
|
37
37
|
const here = document.location.href;
|
|
38
|
-
|
|
38
|
+
const download = anchor.hasAttribute('download');
|
|
39
|
+
if (!isDeparture(href, download, here))
|
|
39
40
|
return;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
const url = new URL(href, here).toString();
|
|
42
|
+
queueMicrotask(() => {
|
|
43
|
+
observeSafely(() => {
|
|
44
|
+
if (event.defaultPrevented)
|
|
45
|
+
return;
|
|
46
|
+
seq += 1;
|
|
47
|
+
emit(EventType.NET_PENDING, {
|
|
48
|
+
id: `nav-${String(seq)}`,
|
|
49
|
+
method: 'GET',
|
|
50
|
+
url,
|
|
51
|
+
initiator: NetInitiator.NAVIGATION,
|
|
52
|
+
...(download ? { download: true } : {}),
|
|
53
|
+
});
|
|
54
|
+
});
|
|
47
55
|
});
|
|
48
56
|
});
|
|
49
57
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventType } from '@reticlehq/core';
|
|
2
2
|
import { observeSafely } from './types.js';
|
|
3
|
-
import { isSyntheticInput } from '../actions/synthetic-input.js';
|
|
3
|
+
import { isSyntheticInput } from '../actions/synthetic/synthetic-input.js';
|
|
4
4
|
const DECLINED = { alert: undefined, confirm: false, prompt: null };
|
|
5
5
|
const KINDS = ['alert', 'confirm', 'prompt'];
|
|
6
6
|
export function installDialogs(emit) {
|
package/dist/observers/dom.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventType, TruncationChannel } from '@reticlehq/core';
|
|
2
2
|
import { getAccessibleName, getRole, isVisible } from '../dom/a11y.js';
|
|
3
|
-
import { refs } from '../dom/refs.js';
|
|
3
|
+
import { refs } from '../dom/addressing/refs.js';
|
|
4
4
|
function regionKeyOf(target) {
|
|
5
5
|
const el = isElement(target) ? target : null;
|
|
6
6
|
if (null === el)
|
|
@@ -39,6 +39,26 @@ const MAX_PER_BATCH = 40;
|
|
|
39
39
|
function isMeaningful(role, name) {
|
|
40
40
|
return role !== 'generic' || name.length > 0;
|
|
41
41
|
}
|
|
42
|
+
const MOUNT_SCAN_LIMIT = 40;
|
|
43
|
+
function describeMount(node) {
|
|
44
|
+
const role = getRole(node);
|
|
45
|
+
const name = getAccessibleName(node);
|
|
46
|
+
if (isMeaningful(role, name))
|
|
47
|
+
return { role, name, el: node };
|
|
48
|
+
let scanned = 0;
|
|
49
|
+
for (const child of node.querySelectorAll('*')) {
|
|
50
|
+
if (scanned >= MOUNT_SCAN_LIMIT)
|
|
51
|
+
return undefined;
|
|
52
|
+
scanned += 1;
|
|
53
|
+
if (isReticleOverlay(child))
|
|
54
|
+
continue;
|
|
55
|
+
const childRole = getRole(child);
|
|
56
|
+
const childName = getAccessibleName(child);
|
|
57
|
+
if (isMeaningful(childRole, childName))
|
|
58
|
+
return { role: childRole, name: childName, el: child };
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
42
62
|
const TEXT_NODE = 3;
|
|
43
63
|
function textOf(nodes) {
|
|
44
64
|
let out = '';
|
|
@@ -112,12 +132,12 @@ export function installDom(emit) {
|
|
|
112
132
|
}
|
|
113
133
|
if (isReticleOverlay(node))
|
|
114
134
|
continue;
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
if (!isMeaningful(role, name))
|
|
135
|
+
const mounted = describeMount(node);
|
|
136
|
+
if (mounted === undefined)
|
|
118
137
|
continue;
|
|
138
|
+
const { role, name } = mounted;
|
|
119
139
|
added += 1;
|
|
120
|
-
const ref = refs.refFor(
|
|
140
|
+
const ref = refs.refFor(mounted.el);
|
|
121
141
|
emit(EventType.DOM_ADDED, { role, name, region: regionKeyOf(record.target) }, ref);
|
|
122
142
|
if (DIALOG_ROLES.has(role) ||
|
|
123
143
|
LIVE_ROLES.has(role) ||
|
|
@@ -135,10 +155,10 @@ export function installDom(emit) {
|
|
|
135
155
|
}
|
|
136
156
|
if (isReticleOverlay(node))
|
|
137
157
|
continue;
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
if (!isMeaningful(role, name))
|
|
158
|
+
const gone = describeMount(node);
|
|
159
|
+
if (gone === undefined)
|
|
141
160
|
continue;
|
|
161
|
+
const { role, name } = gone;
|
|
142
162
|
removed += 1;
|
|
143
163
|
emit(EventType.DOM_REMOVED, { role, name, region: regionKeyOf(record.target) });
|
|
144
164
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventType } from '@reticlehq/core';
|
|
2
2
|
import { captureMethod } from '../patching/capture-method.js';
|
|
3
|
-
import { projectBody } from './network-body.js';
|
|
3
|
+
import { projectBody } from './net-detail/network-body.js';
|
|
4
4
|
import { observeSafely, observeValue } from './types.js';
|
|
5
5
|
const TEXTUAL = /text\/|json|csv|xml|ndjson|javascript/i;
|
|
6
6
|
const PREVIEW_CHARS = 2000;
|
package/dist/observers/health.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BrowserBrand, EventType, HealthReason, RETICLE_IPC_GLOBAL, SESSION_HEALTH, } from '@reticlehq/core';
|
|
2
|
-
import { nativeSetInterval } from '../timers/native-timers.js';
|
|
2
|
+
import { nativeSetInterval } from '../timers/native/native-timers.js';
|
|
3
3
|
function detectRuntime() {
|
|
4
4
|
const w = window;
|
|
5
5
|
if (w['__TAURI_INTERNALS__'] !== undefined || w['__TAURI__'] !== undefined)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { REDACTED_VALUE } from '@reticlehq/core';
|
|
2
|
-
import { isSensitiveKey, safeStringify, scrubKnownSecrets } from '
|
|
3
|
-
import { nativeClearTimeout, nativeSetTimeout } from '
|
|
2
|
+
import { isSensitiveKey, safeStringify, scrubKnownSecrets } from '../../security/serialization.js';
|
|
3
|
+
import { nativeClearTimeout, nativeSetTimeout } from '../../timers/native/native-timers.js';
|
|
4
4
|
const CAPTURABLE_CONTENT = /application\/json|text\/|application\/xml|x-www-form-urlencoded|graphql/i;
|
|
5
5
|
const STREAMING_CONTENT = /event-stream|x-ndjson|application\/stream/i;
|
|
6
6
|
const ENDLESS_BY_DESIGN = /event-stream/i;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventType, StreamDirection, StreamTransport } from '@reticlehq/core';
|
|
2
|
-
import { isStreamingBody } from './network-body.js';
|
|
3
|
-
import { nativeClearTimeout, nativeSetTimeout } from '../timers/native-timers.js';
|
|
2
|
+
import { isStreamingBody } from './net-detail/network-body.js';
|
|
3
|
+
import { nativeClearTimeout, nativeSetTimeout } from '../timers/native/native-timers.js';
|
|
4
4
|
const STREAM_WATCH_MS = 10_000;
|
|
5
5
|
export function watchStreamedBody(emit, res, id, url, contentType, contentLength) {
|
|
6
6
|
if (!isStreamingBody(contentType, contentLength))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Emit, type Teardown } from './types.js';
|
|
2
|
-
import { redactUrl, netUrlFields } from './network-redact.js';
|
|
2
|
+
import { redactUrl, netUrlFields } from './net-detail/network-redact.js';
|
|
3
3
|
export { redactUrl, netUrlFields };
|
|
4
4
|
type NetResponseReinterpreter = (url: string, header: (name: string) => string | null) => Record<string, unknown> | undefined;
|
|
5
5
|
interface NetworkOptions {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BlindSpotKind, EventType, RETICLE_WS_PATH, StreamTransport, StreamDirection, } from '@reticlehq/core';
|
|
1
|
+
import { BlindSpotKind, EventType, REQUEST_SHAPE_FIELD, REQUEST_SHAPE_NONE, RETICLE_WS_PATH, StreamTransport, StreamDirection, fnv1a, } from '@reticlehq/core';
|
|
2
2
|
import { captureMethod } from '../patching/capture-method.js';
|
|
3
3
|
import { observeSafely, observeValue } from './types.js';
|
|
4
|
-
import { isCapturableType, projectBody, projectErrorBody, shouldCaptureErrorBody, withBodyDeadline, } from './network-body.js';
|
|
5
|
-
import { redactUrl, netUrlFields } from './network-redact.js';
|
|
4
|
+
import { isCapturableType, projectBody, projectErrorBody, shouldCaptureErrorBody, withBodyDeadline, } from './net-detail/network-body.js';
|
|
5
|
+
import { redactUrl, netUrlFields } from './net-detail/network-redact.js';
|
|
6
6
|
import { watchStreamedBody } from './network-stream.js';
|
|
7
7
|
import { requireCapturedMethod } from '../util/captured-method.js';
|
|
8
8
|
export { redactUrl, netUrlFields };
|
|
@@ -31,26 +31,66 @@ function frameFields(data, captureBodies) {
|
|
|
31
31
|
}
|
|
32
32
|
return out;
|
|
33
33
|
}
|
|
34
|
+
const ShapeToken = { NULL: '0', STRING: 's', NUMBER: 'n', BOOLEAN: 'b', OTHER: '?' };
|
|
35
|
+
function shapeOf(value) {
|
|
36
|
+
if (null === value)
|
|
37
|
+
return ShapeToken.NULL;
|
|
38
|
+
if (Array.isArray(value))
|
|
39
|
+
return `[${value.map(shapeOf).join(',')}]`;
|
|
40
|
+
if ('object' === typeof value) {
|
|
41
|
+
const fields = value;
|
|
42
|
+
return `{${Object.keys(fields)
|
|
43
|
+
.sort()
|
|
44
|
+
.map((key) => `${key}:${shapeOf(fields[key])}`)
|
|
45
|
+
.join(',')}}`;
|
|
46
|
+
}
|
|
47
|
+
if ('string' === typeof value)
|
|
48
|
+
return ShapeToken.STRING;
|
|
49
|
+
if ('number' === typeof value)
|
|
50
|
+
return ShapeToken.NUMBER;
|
|
51
|
+
if ('boolean' === typeof value)
|
|
52
|
+
return ShapeToken.BOOLEAN;
|
|
53
|
+
return ShapeToken.OTHER;
|
|
54
|
+
}
|
|
55
|
+
function fingerprintBody(shape, length) {
|
|
56
|
+
return fnv1a(`${shape}#${String(length)}`);
|
|
57
|
+
}
|
|
58
|
+
function jsonShape(text) {
|
|
59
|
+
try {
|
|
60
|
+
return shapeOf(JSON.parse(text));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return ShapeToken.OTHER;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
34
66
|
function projectRequestBody(body, captureBodies) {
|
|
35
|
-
if (!captureBodies)
|
|
36
|
-
return {};
|
|
37
67
|
let text;
|
|
38
68
|
let contentType = 'application/json';
|
|
69
|
+
let shape = REQUEST_SHAPE_NONE;
|
|
39
70
|
if ('string' === typeof body) {
|
|
40
71
|
text = body;
|
|
72
|
+
if (text.length > 0)
|
|
73
|
+
shape = fingerprintBody(jsonShape(text), text.length);
|
|
41
74
|
}
|
|
42
75
|
else if (typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams) {
|
|
43
76
|
text = body.toString();
|
|
44
77
|
contentType = 'application/x-www-form-urlencoded';
|
|
78
|
+
if (text.length > 0) {
|
|
79
|
+
const fields = Object.fromEntries(new URLSearchParams(text));
|
|
80
|
+
shape = fingerprintBody(shapeOf(fields), text.length);
|
|
81
|
+
}
|
|
45
82
|
}
|
|
46
83
|
else if (body !== undefined && body !== null) {
|
|
47
|
-
const
|
|
48
|
-
return { requestBodyType:
|
|
84
|
+
const kind = body.constructor?.name ?? typeof body;
|
|
85
|
+
return captureBodies ? { requestBodyType: kind } : {};
|
|
49
86
|
}
|
|
50
|
-
|
|
51
|
-
|
|
87
|
+
const fields = { [REQUEST_SHAPE_FIELD]: shape };
|
|
88
|
+
if (!captureBodies || text === undefined || 0 === text.length)
|
|
89
|
+
return fields;
|
|
52
90
|
const { body: out, truncated } = projectBody(text, contentType);
|
|
53
|
-
return truncated
|
|
91
|
+
return truncated
|
|
92
|
+
? { ...fields, requestBody: out, requestBodyTruncated: true }
|
|
93
|
+
: { ...fields, requestBody: out };
|
|
54
94
|
}
|
|
55
95
|
function statusIsOk(status) {
|
|
56
96
|
return status >= 200 && status < 400;
|
|
@@ -428,6 +468,7 @@ export function installNetwork(emit, opts = {}) {
|
|
|
428
468
|
durationMs: 0,
|
|
429
469
|
initiator: 'beacon',
|
|
430
470
|
...(initiatorStack === undefined ? {} : { initiatorStack }),
|
|
471
|
+
...projectRequestBody(data, false),
|
|
431
472
|
});
|
|
432
473
|
});
|
|
433
474
|
return sent;
|
package/dist/observers/scroll.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EventType, ScrollDirection } from '@reticlehq/core';
|
|
2
|
-
import { refs } from '../dom/refs.js';
|
|
3
|
-
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native-timers.js';
|
|
2
|
+
import { refs } from '../dom/addressing/refs.js';
|
|
3
|
+
import { nativeSetTimeout, nativeClearTimeout } from '../timers/native/native-timers.js';
|
|
4
4
|
const THROTTLE_MS = 100;
|
|
5
5
|
const REVEAL_SELECTOR = '[data-reticle-reveal], [data-reveal], section';
|
|
6
6
|
export function installScroll(emit) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const LOG_KIND: {
|
|
2
|
+
readonly READ: "read";
|
|
3
|
+
readonly ACT: "act";
|
|
4
|
+
readonly NARRATION: "narration";
|
|
5
|
+
readonly HUMAN: "human";
|
|
6
|
+
};
|
|
7
|
+
export type LogKind = (typeof LOG_KIND)[keyof typeof LOG_KIND];
|
|
8
|
+
export declare const LOG_RESULT: {
|
|
9
|
+
readonly PASS: "pass";
|
|
10
|
+
readonly FAIL: "fail";
|
|
11
|
+
};
|
|
12
|
+
export type LogResult = (typeof LOG_RESULT)[keyof typeof LOG_RESULT];
|
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
import { PresenterMode } from '@reticlehq/core';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
readonly NARRATION: "narration";
|
|
6
|
-
readonly HUMAN: "human";
|
|
7
|
-
};
|
|
8
|
-
export type LogKind = (typeof LOG_KIND)[keyof typeof LOG_KIND];
|
|
9
|
-
export declare const LOG_RESULT: {
|
|
10
|
-
readonly PASS: "pass";
|
|
11
|
-
readonly FAIL: "fail";
|
|
12
|
-
};
|
|
13
|
-
export type LogResult = (typeof LOG_RESULT)[keyof typeof LOG_RESULT];
|
|
2
|
+
import { LOG_KIND, LOG_RESULT, type LogKind, type LogResult } from './log-kinds.js';
|
|
3
|
+
export { LOG_KIND, LOG_RESULT };
|
|
4
|
+
export type { LogKind, LogResult };
|
|
14
5
|
export declare const CHIP_LABEL: Record<PresenterMode, string>;
|
|
15
6
|
export declare const DATA_RETICLE_LOG = "data-reticle-log";
|
|
16
7
|
export declare const LOG_TIME_ATTR = "data-reticle-log-time";
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { PresenterMode } from '@reticlehq/core';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { LOG_KIND, LOG_RESULT } from './log-kinds.js';
|
|
3
|
+
import { nativeSetTimeout } from '../../timers/native/native-timers.js';
|
|
4
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon, } from '../icons/presenter-icons.js';
|
|
4
5
|
const DEFAULT_LOG_MAX = 50;
|
|
5
|
-
export
|
|
6
|
-
READ: 'read',
|
|
7
|
-
ACT: 'act',
|
|
8
|
-
NARRATION: 'narration',
|
|
9
|
-
HUMAN: 'human',
|
|
10
|
-
};
|
|
11
|
-
export const LOG_RESULT = { PASS: 'pass', FAIL: 'fail' };
|
|
6
|
+
export { LOG_KIND, LOG_RESULT };
|
|
12
7
|
const LOG_CHIP = { read: 'READ', act: 'ACT', narration: '', human: '' };
|
|
13
8
|
const LOG_CHIP_ICON = {
|
|
14
9
|
read: PresenterIcon.VIEW,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function esc(value) {
|
|
2
|
+
return value
|
|
3
|
+
.replace(/&/g, '&')
|
|
4
|
+
.replace(/</g, '<')
|
|
5
|
+
.replace(/>/g, '>')
|
|
6
|
+
.replace(/"/g, '"');
|
|
7
|
+
}
|
|
8
|
+
export function isSafeDashboardUrl(raw) {
|
|
9
|
+
try {
|
|
10
|
+
const scheme = new URL(raw).protocol;
|
|
11
|
+
return 'https:' === scheme || 'http:' === scheme;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LOG_RESULT } from './presenter-log.js';
|
|
2
|
-
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon } from '
|
|
2
|
+
import { PresenterIcon, PRESENTER_ICON_SIZE, hiIcon } from '../icons/presenter-icons.js';
|
|
3
3
|
export function renderTally(el, runLog, prev) {
|
|
4
4
|
const next = countVerdicts(runLog);
|
|
5
5
|
if (el === undefined)
|
|
@@ -18,6 +18,7 @@ const BODIES = {
|
|
|
18
18
|
help: '<path d="M8.228 9c.549-1.165 2.03-2 3.772-2c2.21 0 4 1.343 4 3c0 1.4-1.278 2.575-3.006 2.907c-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 1 1-18 0a9 9 0 0 1 18 0"/>',
|
|
19
19
|
'caret-right': '<path d="m9 5l7 7l-7 7"/>',
|
|
20
20
|
annotate: '<path d="m16.862 4.487l1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10"/>',
|
|
21
|
+
sync: '<path d="M4.5 12c0-1.232.046-2.453.138-3.662a4.006 4.006 0 0 1 3.7-3.7a48.678 48.678 0 0 1 7.324 0a4.006 4.006 0 0 1 3.7 3.7c.017.22.032.441.046.662M4.5 12l-3-3m3 3l3-3m12 3c0 1.232-.046 2.453-.138 3.662a4.006 4.006 0 0 1-3.7 3.7a48.657 48.657 0 0 1-7.324 0a4.006 4.006 0 0 1-3.7-3.7c-.017-.22-.032-.441-.046-.662M19.5 12l-3 3m3-3l3 3"/>',
|
|
21
22
|
};
|
|
22
23
|
export const HERO_ICON_BODIES = BODIES;
|
|
23
24
|
const SOLID_BODIES = {
|
|
@@ -19,6 +19,7 @@ export declare const PresenterIcon: {
|
|
|
19
19
|
readonly HELP: "help";
|
|
20
20
|
readonly CARET_RIGHT: "caret-right";
|
|
21
21
|
readonly ANNOTATE: "annotate";
|
|
22
|
+
readonly SYNC: "sync";
|
|
22
23
|
};
|
|
23
24
|
export type PresenterIconName = (typeof PresenterIcon)[keyof typeof PresenterIcon];
|
|
24
25
|
export declare const PRESENTER_ICON_SIZE: {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ACCOUNT_CSS: string;
|