browser-debugger-cli 0.12.0 → 0.14.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/.claude/skills/bdg/SKILL.md +100 -186
- package/README.md +5 -4
- package/dist/commands/cdp.d.ts +22 -1
- package/dist/commands/cdp.js +100 -43
- package/dist/commands/console.d.ts +12 -0
- package/dist/commands/console.js +67 -13
- package/dist/commands/dom/DomElementResolver.d.ts +3 -1
- package/dist/commands/dom/DomElementResolver.js +10 -3
- package/dist/commands/dom/a11y.d.ts +1 -1
- package/dist/commands/dom/a11y.js +23 -22
- package/dist/commands/dom/eval.d.ts +4 -2
- package/dist/commands/dom/eval.js +31 -7
- package/dist/commands/dom/form.js +10 -9
- package/dist/commands/dom/formInteraction.js +9 -8
- package/dist/commands/dom/get.js +32 -14
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/query.d.ts +27 -3
- package/dist/commands/dom/helpers/query.js +152 -64
- package/dist/commands/dom/helpers/screenshot.js +13 -13
- package/dist/commands/dom/index.js +10 -3
- package/dist/commands/dom/query.d.ts +20 -2
- package/dist/commands/dom/query.js +39 -6
- package/dist/commands/dom/screenshot.js +3 -1
- package/dist/commands/dom/semanticUtils.d.ts +3 -2
- package/dist/commands/dom/semanticUtils.js +40 -9
- package/dist/commands/helpJson.d.ts +82 -19
- package/dist/commands/helpJson.js +112 -41
- package/dist/commands/helpTopic.d.ts +16 -1
- package/dist/commands/helpTopic.js +59 -1
- package/dist/commands/installSkill.d.ts +15 -5
- package/dist/commands/installSkill.js +86 -16
- package/dist/commands/network/list.js +65 -12
- package/dist/commands/optionBehaviors.d.ts +25 -2
- package/dist/commands/optionBehaviors.js +81 -46
- package/dist/commands/peek.js +3 -0
- package/dist/commands/shared/CommandRunner.js +13 -13
- package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
- package/dist/commands/shared/daemonErrorHandler.js +21 -10
- package/dist/commands/shared/dataFetcher.d.ts +14 -4
- package/dist/commands/shared/dataFetcher.js +20 -4
- package/dist/commands/shared/followMode.d.ts +9 -1
- package/dist/commands/shared/followMode.js +22 -4
- package/dist/commands/shared/handleValidationError.js +3 -3
- package/dist/commands/shared/optionTypes.d.ts +17 -3
- package/dist/commands/shared/outputFile.js +6 -1
- package/dist/commands/shared/startHelpers.js +3 -3
- package/dist/commands/start.d.ts +7 -5
- package/dist/commands/start.js +65 -21
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.js +24 -1
- package/dist/commands.js +1 -1
- package/dist/connection/cdp.d.ts +7 -0
- package/dist/connection/cdp.js +9 -0
- package/dist/connection/chromeIdentity.d.ts +8 -2
- package/dist/connection/chromeIdentity.js +85 -13
- package/dist/connection/launcher.js +3 -2
- package/dist/constants.d.ts +29 -1
- package/dist/constants.js +35 -1
- package/dist/daemon/SessionController.js +8 -1
- package/dist/daemon/launcher.d.ts +3 -2
- package/dist/daemon/launcher.js +47 -3
- package/dist/daemon/session/Session.d.ts +5 -1
- package/dist/daemon/session/Session.js +42 -3
- package/dist/daemon/session/TelemetryStore.d.ts +15 -1
- package/dist/daemon/session/TelemetryStore.js +19 -1
- package/dist/daemon/session/commandRegistry.js +52 -18
- package/dist/daemon/session/interactions.d.ts +2 -1
- package/dist/daemon/session/interactions.js +13 -1
- package/dist/daemon/session/matchedStylesReset.d.ts +26 -0
- package/dist/daemon/session/matchedStylesReset.js +46 -0
- package/dist/daemon/session/plugins.js +17 -2
- package/dist/daemon/session/teardown.js +1 -1
- package/dist/daemon/session/triggeredRequests.d.ts +0 -5
- package/dist/daemon/session/triggeredRequests.js +13 -7
- package/dist/daemon.js +2385 -1229
- package/dist/errors/messages.d.ts +62 -11
- package/dist/errors/messages.js +119 -22
- package/dist/index.js +14995 -9866
- package/dist/ipc/client.d.ts +18 -2
- package/dist/ipc/client.js +26 -5
- package/dist/ipc/protocol/auditTypes.d.ts +8 -2
- package/dist/ipc/protocol/commands.d.ts +16 -0
- package/dist/ipc/protocol/domTypes.d.ts +12 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +7 -2
- package/dist/ipc/session/types.d.ts +7 -1
- package/dist/program.d.ts +14 -0
- package/dist/program.js +53 -0
- package/dist/runtime/dom/actionEffects.d.ts +5 -1
- package/dist/runtime/dom/actionEffects.js +26 -14
- package/dist/runtime/dom/audit.js +3 -2
- package/dist/runtime/dom/auditModel.js +6 -1
- package/dist/runtime/dom/auditScripts.d.ts +9 -3
- package/dist/runtime/dom/auditScripts.js +41 -5
- package/dist/runtime/dom/elementGeometry.d.ts +33 -3
- package/dist/runtime/dom/elementGeometry.js +44 -19
- package/dist/runtime/dom/elementInfo.d.ts +76 -18
- package/dist/runtime/dom/elementInfo.js +190 -40
- package/dist/runtime/dom/evalHelpers.d.ts +12 -2
- package/dist/runtime/dom/evalHelpers.js +67 -7
- package/dist/runtime/dom/formDiscovery.d.ts +6 -2
- package/dist/runtime/dom/formDiscovery.js +20 -3
- package/dist/runtime/dom/formFillHelpers/fill.js +7 -11
- package/dist/runtime/dom/formFillHelpers/pressKey.js +2 -2
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +16 -10
- package/dist/runtime/dom/formFillHelpers/shared.js +19 -52
- package/dist/runtime/dom/formSubmitHelpers.js +4 -3
- package/dist/runtime/dom/frameLayout.js +1 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +7 -0
- package/dist/runtime/dom/frameScopedConnection.js +2 -2
- package/dist/runtime/dom/inspect.d.ts +17 -3
- package/dist/runtime/dom/inspect.js +45 -32
- package/dist/runtime/dom/inspectAllStyles.js +1 -0
- package/dist/runtime/dom/inspectHints.d.ts +1 -1
- package/dist/runtime/dom/inspectModel.d.ts +5 -4
- package/dist/runtime/dom/inspectModel.js +7 -3
- package/dist/runtime/dom/inspectPaintModel.d.ts +2 -0
- package/dist/runtime/dom/inspectPaintModel.js +3 -1
- package/dist/runtime/dom/inspectRules.d.ts +29 -3
- package/dist/runtime/dom/inspectRules.js +205 -11
- package/dist/runtime/dom/inspectScripts.d.ts +29 -2
- package/dist/runtime/dom/inspectScripts.js +49 -10
- package/dist/runtime/dom/layout.d.ts +0 -2
- package/dist/runtime/dom/layout.js +10 -9
- package/dist/runtime/dom/reactEventHelpers.d.ts +17 -4
- package/dist/runtime/dom/reactEventHelpers.js +71 -28
- package/dist/runtime/dom/targetNode.d.ts +27 -10
- package/dist/runtime/dom/targetNode.js +283 -16
- package/dist/runtime/dom/wait.js +2 -1
- package/dist/runtime/page/bdgWorld.d.ts +57 -0
- package/dist/runtime/page/bdgWorld.js +180 -0
- package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
- package/dist/runtime/page/replacedBuiltins.js +136 -0
- package/dist/session/QueryCacheManager.d.ts +4 -1
- package/dist/session/QueryCacheManager.js +5 -2
- package/dist/session/chrome.d.ts +4 -1
- package/dist/session/chrome.js +7 -1
- package/dist/session/cleanup/staleSession.d.ts +21 -4
- package/dist/session/cleanup/staleSession.js +79 -9
- package/dist/session/cleanup/userCommands.d.ts +4 -1
- package/dist/session/cleanup/userCommands.js +10 -5
- package/dist/session/daemonSocket.d.ts +10 -0
- package/dist/session/daemonSocket.js +22 -0
- package/dist/session/lastSession.d.ts +6 -3
- package/dist/session/lastSession.js +11 -5
- package/dist/session/paths.d.ts +3 -1
- package/dist/session/paths.js +5 -5
- package/dist/session/portClaims.js +4 -3
- package/dist/session/sessionList.d.ts +13 -5
- package/dist/session/sessionList.js +31 -7
- package/dist/telemetry/a11y.d.ts +15 -1
- package/dist/telemetry/a11y.js +85 -2
- package/dist/telemetry/console.d.ts +2 -1
- package/dist/telemetry/console.js +30 -21
- package/dist/telemetry/har/builder.js +1 -1
- package/dist/telemetry/network.d.ts +13 -16
- package/dist/telemetry/network.js +30 -52
- package/dist/telemetry/networkRetention.d.ts +83 -0
- package/dist/telemetry/networkRetention.js +117 -0
- package/dist/telemetry/pageCrash.d.ts +26 -0
- package/dist/telemetry/pageCrash.js +53 -0
- package/dist/types.d.ts +42 -0
- package/dist/ui/OutputBuilder.d.ts +10 -0
- package/dist/ui/OutputBuilder.js +12 -0
- package/dist/ui/formatters/a11y.d.ts +5 -7
- package/dist/ui/formatters/a11y.js +7 -61
- package/dist/ui/formatters/audit.js +14 -5
- package/dist/ui/formatters/cdp.d.ts +138 -0
- package/dist/ui/formatters/cdp.js +131 -0
- package/dist/ui/formatters/console/chronological.js +7 -5
- package/dist/ui/formatters/console/follow.d.ts +5 -2
- package/dist/ui/formatters/console/follow.js +7 -4
- package/dist/ui/formatters/console/json.d.ts +4 -7
- package/dist/ui/formatters/console/json.js +16 -14
- package/dist/ui/formatters/console/shared.d.ts +47 -2
- package/dist/ui/formatters/console/shared.js +33 -0
- package/dist/ui/formatters/console/summarize.d.ts +9 -2
- package/dist/ui/formatters/console/summarize.js +57 -11
- package/dist/ui/formatters/console.d.ts +3 -2
- package/dist/ui/formatters/console.js +8 -10
- package/dist/ui/formatters/details.js +4 -2
- package/dist/ui/formatters/dom.d.ts +14 -5
- package/dist/ui/formatters/dom.js +30 -13
- package/dist/ui/formatters/helpFormatters.js +1 -1
- package/dist/ui/formatters/inspect.js +9 -3
- package/dist/ui/formatters/installSkill.d.ts +9 -1
- package/dist/ui/formatters/installSkill.js +32 -6
- package/dist/ui/formatters/layout.js +4 -2
- package/dist/ui/formatters/longValues.d.ts +14 -0
- package/dist/ui/formatters/longValues.js +23 -0
- package/dist/ui/formatters/networkList.d.ts +8 -2
- package/dist/ui/formatters/networkList.js +11 -3
- package/dist/ui/formatters/preview.d.ts +6 -1
- package/dist/ui/formatters/preview.js +67 -15
- package/dist/ui/formatters/sessions.d.ts +2 -2
- package/dist/ui/formatters/sessions.js +9 -2
- package/dist/ui/formatters/status.js +7 -0
- package/dist/ui/formatters/triggeredRequests.js +2 -1
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/chrome.d.ts +20 -1
- package/dist/ui/messages/chrome.js +29 -3
- package/dist/ui/messages/commands.d.ts +153 -12
- package/dist/ui/messages/commands.js +198 -15
- package/dist/ui/messages/consoleMessages.d.ts +24 -0
- package/dist/ui/messages/consoleMessages.js +32 -0
- package/dist/ui/messages/networkMessages.d.ts +24 -0
- package/dist/ui/messages/networkMessages.js +45 -0
- package/dist/ui/messages/preview.d.ts +6 -0
- package/dist/ui/messages/preview.js +9 -1
- package/dist/ui/messages/session.d.ts +13 -2
- package/dist/ui/messages/session.js +22 -3
- package/dist/utils/directories.d.ts +34 -0
- package/dist/utils/directories.js +88 -0
- package/dist/utils/display.d.ts +16 -0
- package/dist/utils/display.js +42 -0
- package/dist/utils/exitCodes.d.ts +1 -0
- package/dist/utils/exitCodes.js +6 -0
- package/dist/utils/http.d.ts +9 -2
- package/dist/utils/http.js +4 -3
- package/dist/utils/process.d.ts +12 -0
- package/dist/utils/process.js +25 -0
- package/dist/utils/strings.d.ts +19 -0
- package/dist/utils/strings.js +16 -0
- package/package.json +2 -2
|
@@ -9,7 +9,7 @@ import { writeOutputFile } from '../../shared/outputFile.js';
|
|
|
9
9
|
import { CDPConnectionError } from '../../../connection/errors.js';
|
|
10
10
|
import { CommandError } from '../../../errors/index.js';
|
|
11
11
|
import { noNodesFoundError, elementNotVisibleError, elementZeroDimensionsError, } from '../../../errors/messages.js';
|
|
12
|
-
import { callCDP } from '../../../ipc/client.js';
|
|
12
|
+
import { callBdgScript, callCDP } from '../../../ipc/client.js';
|
|
13
13
|
import { DEEP_QUERY_JS, selectorArgsJS } from '../../../runtime/dom/targetNode.js';
|
|
14
14
|
import { viewportOverride } from '../../../runtime/page/emulation.js';
|
|
15
15
|
import { readSessionMetadata } from '../../../session/metadata.js';
|
|
@@ -26,7 +26,7 @@ const STABILITY_CHECK_INTERVAL_MS = 50;
|
|
|
26
26
|
*/
|
|
27
27
|
async function waitForPostScrollStability() {
|
|
28
28
|
const deadline = Date.now() + POST_SCROLL_MAX_WAIT_MS;
|
|
29
|
-
await
|
|
29
|
+
await callBdgScript('Runtime.evaluate', {
|
|
30
30
|
expression: `
|
|
31
31
|
(() => {
|
|
32
32
|
window.__bdg_scrollStability = {
|
|
@@ -66,7 +66,7 @@ async function waitForPostScrollStability() {
|
|
|
66
66
|
});
|
|
67
67
|
try {
|
|
68
68
|
while (Date.now() < deadline) {
|
|
69
|
-
const checkResult = await
|
|
69
|
+
const checkResult = await callBdgScript('Runtime.evaluate', {
|
|
70
70
|
expression: `
|
|
71
71
|
(() => {
|
|
72
72
|
const state = window.__bdg_scrollStability;
|
|
@@ -91,7 +91,7 @@ async function waitForPostScrollStability() {
|
|
|
91
91
|
log.debug('Post-scroll stability timeout, proceeding anyway');
|
|
92
92
|
}
|
|
93
93
|
finally {
|
|
94
|
-
await
|
|
94
|
+
await callBdgScript('Runtime.evaluate', {
|
|
95
95
|
expression: `
|
|
96
96
|
(() => {
|
|
97
97
|
const state = window.__bdg_scrollStability;
|
|
@@ -111,7 +111,7 @@ async function waitForPostScrollStability() {
|
|
|
111
111
|
* position so it can be restored afterwards.
|
|
112
112
|
*/
|
|
113
113
|
async function scrollToElement(selector) {
|
|
114
|
-
const result = await
|
|
114
|
+
const result = await callBdgScript('Runtime.evaluate', {
|
|
115
115
|
expression: `
|
|
116
116
|
(() => {
|
|
117
117
|
const el = (${DEEP_QUERY_JS})(${selectorArgsJS(selector)})[0];
|
|
@@ -133,7 +133,7 @@ async function scrollToElement(selector) {
|
|
|
133
133
|
return { x: value.originalX ?? 0, y: value.originalY ?? 0 };
|
|
134
134
|
}
|
|
135
135
|
async function restoreScrollPosition(position) {
|
|
136
|
-
await
|
|
136
|
+
await callBdgScript('Runtime.evaluate', {
|
|
137
137
|
expression: `window.scrollTo(${position.x}, ${position.y})`,
|
|
138
138
|
returnByValue: true,
|
|
139
139
|
});
|
|
@@ -147,7 +147,7 @@ async function restoreScrollPosition(position) {
|
|
|
147
147
|
* @returns Width and height in CSS px
|
|
148
148
|
*/
|
|
149
149
|
async function windowSize(viewport) {
|
|
150
|
-
const response = await
|
|
150
|
+
const response = await callBdgScript('Runtime.evaluate', {
|
|
151
151
|
expression: '[window.innerWidth, window.innerHeight]',
|
|
152
152
|
returnByValue: true,
|
|
153
153
|
});
|
|
@@ -245,7 +245,7 @@ export async function capturePageScreenshot(outputPath, options = {}) {
|
|
|
245
245
|
if (options.scroll) {
|
|
246
246
|
originalScrollPosition = await scrollToElement(options.scroll);
|
|
247
247
|
}
|
|
248
|
-
const dprResponse = await
|
|
248
|
+
const dprResponse = await callBdgScript('Runtime.evaluate', {
|
|
249
249
|
expression: 'window.devicePixelRatio',
|
|
250
250
|
returnByValue: true,
|
|
251
251
|
});
|
|
@@ -266,7 +266,7 @@ export async function capturePageScreenshot(outputPath, options = {}) {
|
|
|
266
266
|
const restoreMetrics = await useUnitPixelRatio(devicePixelRatio, viewport);
|
|
267
267
|
if (devicePixelRatio !== 1) {
|
|
268
268
|
if (options.scroll) {
|
|
269
|
-
await
|
|
269
|
+
await callBdgScript('Runtime.evaluate', {
|
|
270
270
|
expression: `(${DEEP_QUERY_JS})(${selectorArgsJS(options.scroll)})[0]?.scrollIntoView({ block: 'center', behavior: 'instant' })`,
|
|
271
271
|
returnByValue: true,
|
|
272
272
|
});
|
|
@@ -461,7 +461,7 @@ async function measureInView(ref, padding) {
|
|
|
461
461
|
const scrolledFrom = await scrollPosition();
|
|
462
462
|
const dx = bounds.x + bounds.width / 2 - view.width / 2;
|
|
463
463
|
const dy = bounds.y + bounds.height / 2 - view.height / 2;
|
|
464
|
-
await
|
|
464
|
+
await callBdgScript('Runtime.evaluate', { expression: `window.scrollBy(${dx}, ${dy})` });
|
|
465
465
|
try {
|
|
466
466
|
box = await getElementBounds(ref);
|
|
467
467
|
bounds = await captureArea(ref, box, padding);
|
|
@@ -501,7 +501,7 @@ async function restoreViewport() {
|
|
|
501
501
|
* @returns Scroll offsets in CSS px
|
|
502
502
|
*/
|
|
503
503
|
async function scrollPosition() {
|
|
504
|
-
const response = await
|
|
504
|
+
const response = await callBdgScript('Runtime.evaluate', {
|
|
505
505
|
expression: '[window.scrollX, window.scrollY]',
|
|
506
506
|
returnByValue: true,
|
|
507
507
|
});
|
|
@@ -544,7 +544,7 @@ async function captureArea(ref, bounds, padding) {
|
|
|
544
544
|
async function paintedArea(ref, bounds) {
|
|
545
545
|
const objectGroup = `bdg-shot-${process.pid}`;
|
|
546
546
|
try {
|
|
547
|
-
const resolved = await
|
|
547
|
+
const resolved = await callBdgScript('DOM.resolveNode', { ...ref, objectGroup });
|
|
548
548
|
const objectId = resolved.data?.result?.object
|
|
549
549
|
.objectId;
|
|
550
550
|
if (!objectId)
|
|
@@ -586,7 +586,7 @@ export async function captureElementScreenshot(outputPath, ref, options = {}) {
|
|
|
586
586
|
const format = options.format ?? 'png';
|
|
587
587
|
const quality = format === 'jpeg' ? (options.quality ?? 90) : undefined;
|
|
588
588
|
const noResize = options.noResize ?? false;
|
|
589
|
-
const dprResponse = await
|
|
589
|
+
const dprResponse = await callBdgScript('Runtime.evaluate', {
|
|
590
590
|
expression: 'window.devicePixelRatio',
|
|
591
591
|
returnByValue: true,
|
|
592
592
|
});
|
|
@@ -17,19 +17,23 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { Option } from 'commander';
|
|
19
19
|
import { registerA11yCommands } from './a11y.js';
|
|
20
|
+
import { registerAuditCommand } from './audit.js';
|
|
20
21
|
import { handleDomEval } from './eval.js';
|
|
21
22
|
import { registerFormCommand } from './form.js';
|
|
22
23
|
import { handleDomFrames } from './frames.js';
|
|
23
24
|
import { DOM_GET_DEFAULT_SELECTOR, handleDomGet } from './get.js';
|
|
25
|
+
import { QUERY_CACHE_LIMIT } from './helpers/query.js';
|
|
24
26
|
import { registerInspectCommand } from './inspect.js';
|
|
25
|
-
import { registerAuditCommand } from './audit.js';
|
|
26
27
|
import { registerLayoutCommand } from './layout.js';
|
|
27
28
|
import { registerListenersCommand } from './listeners.js';
|
|
28
|
-
import { handleDomQuery } from './query.js';
|
|
29
|
+
import { handleDomQuery, QUERY_LIST_LIMIT } from './query.js';
|
|
29
30
|
import { handleDomScreenshot } from './screenshot.js';
|
|
30
31
|
import { registerWaitCommand } from './wait.js';
|
|
31
32
|
import { SELECTOR_OR_INDEX_ARGUMENT, SELECTOR_SCOPE_HELP, } from '../shared/commonOptions.js';
|
|
32
33
|
import { integerOption, screenshotFormatOption } from '../shared/validation.js';
|
|
34
|
+
import { MAX_VALUE_LENGTH, QUERY_JSON_LIST_LIMIT } from '../../constants.js';
|
|
35
|
+
/** Help of `--full` on `dom eval` and the `eval` shortcut */
|
|
36
|
+
const EVAL_FULL_HELP = `Print the whole value (default: the first ${MAX_VALUE_LENGTH} characters; a string result in JSON too)`;
|
|
33
37
|
/**
|
|
34
38
|
* Register DOM telemetry commands on the root Commander program.
|
|
35
39
|
*/
|
|
@@ -49,6 +53,7 @@ export function registerDomCommands(program) {
|
|
|
49
53
|
.command('query')
|
|
50
54
|
.description('Find elements by CSS selector')
|
|
51
55
|
.argument('<selector>', 'CSS selector (e.g., ".error", "#app", "button")')
|
|
56
|
+
.option('--limit <n>', `Matches to list (default: ${QUERY_LIST_LIMIT}, ${QUERY_JSON_LIST_LIMIT} with --json; 0 = all); the first ${QUERY_CACHE_LIMIT} (or more with a higher limit) are indexed`, integerOption(0))
|
|
52
57
|
.option('-j, --json', 'Output as JSON')
|
|
53
58
|
.addHelpText('after', SELECTOR_SCOPE_HELP)
|
|
54
59
|
.action(async (selector, options) => {
|
|
@@ -59,6 +64,7 @@ export function registerDomCommands(program) {
|
|
|
59
64
|
.description('Evaluate JavaScript expression in the page context')
|
|
60
65
|
.argument('<script>', 'JavaScript to execute (e.g., "document.title", "window.location.href")')
|
|
61
66
|
.option('--frame <frame>', 'Evaluate in an iframe, cross-origin ones included: index (from dom frames; 87 when stale), name/id attribute, or part of the name, id or URL')
|
|
67
|
+
.option('--full', EVAL_FULL_HELP)
|
|
62
68
|
.option('-j, --json', 'Output as JSON')
|
|
63
69
|
.action(async (script, options) => {
|
|
64
70
|
await handleDomEval(script, options);
|
|
@@ -68,6 +74,7 @@ export function registerDomCommands(program) {
|
|
|
68
74
|
.description('Shortcut for: bdg dom eval')
|
|
69
75
|
.argument('<script>', 'JavaScript to execute')
|
|
70
76
|
.option('--frame <frame>', 'Evaluate in an iframe (see dom frames)')
|
|
77
|
+
.option('--full', EVAL_FULL_HELP)
|
|
71
78
|
.option('-j, --json', 'Output as JSON')
|
|
72
79
|
.action(async (script, options) => {
|
|
73
80
|
await handleDomEval(script, options);
|
|
@@ -84,7 +91,7 @@ export function registerDomCommands(program) {
|
|
|
84
91
|
.description('Get semantic accessibility structure (default) or raw HTML (--raw)')
|
|
85
92
|
.argument('[selectorOrIndex]', `${SELECTOR_OR_INDEX_ARGUMENT} (e.g. ".error", "#app", 0); default: ${DOM_GET_DEFAULT_SELECTOR}`)
|
|
86
93
|
.option('--raw', 'Output raw HTML with all filtering options')
|
|
87
|
-
.option('--full',
|
|
94
|
+
.option('--full', `Show all of the element text (default: the first 500 characters); with --raw, all of the HTML (default: the first ${MAX_VALUE_LENGTH} characters)`)
|
|
88
95
|
.option('--all', 'Get all matches (only with --raw)')
|
|
89
96
|
.option('--index <n>', 'Element index if selector matches multiple (0-based)', integerOption(0))
|
|
90
97
|
.addOption(new Option('--nth <n>', 'Alias of --index').argParser(integerOption(0)).hideHelp())
|
|
@@ -2,13 +2,31 @@
|
|
|
2
2
|
* `bdg dom query` — find elements by CSS selector and populate the query cache.
|
|
3
3
|
*/
|
|
4
4
|
import type { DomQueryCommandOptions } from '../shared/optionTypes.js';
|
|
5
|
+
import type { DomQueryResult } from '../../types.js';
|
|
6
|
+
/** Matches `dom query` lists without `--limit` (human output) */
|
|
7
|
+
export declare const QUERY_LIST_LIMIT = 50;
|
|
5
8
|
/**
|
|
6
9
|
* Handle `bdg dom query <selector>`.
|
|
7
10
|
*
|
|
8
|
-
* Runs the selector, caches the
|
|
9
|
-
* elements by index, and
|
|
11
|
+
* Runs the selector, caches the described matches so later commands can
|
|
12
|
+
* reference elements by index, and lists the first `--limit` of them (50,
|
|
13
|
+
* or {@link QUERY_JSON_LIST_LIMIT} with `--json`; 0 = all) with the total
|
|
14
|
+
* count. The first {@link QUERY_CACHE_LIMIT} are indexed whatever is listed.
|
|
10
15
|
* No match exits 83, like `dom get` and `dom a11y`, and clears the cache so
|
|
11
16
|
* indices of an earlier query are not used by mistake.
|
|
12
17
|
*/
|
|
13
18
|
export declare function handleDomQuery(selector: string, options: DomQueryCommandOptions): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* The matches to list: the first `limit` (all with 0), with how many were
|
|
21
|
+
* left out and, when not every match was described, how many can be used by
|
|
22
|
+
* index. Nothing is added when the limit cut nothing (a match that could not
|
|
23
|
+
* be described is just missing, as before). When more than
|
|
24
|
+
* {@link VIEWPORT_HINT_LIMIT} are listed, `viewportChecked` says that only
|
|
25
|
+
* the first ones have a viewport position.
|
|
26
|
+
*
|
|
27
|
+
* @param result - Query result with every described match
|
|
28
|
+
* @param limit - Matches to list (0 = all)
|
|
29
|
+
* @returns Result to output
|
|
30
|
+
*/
|
|
31
|
+
export declare function listedMatches(result: DomQueryResult, limit: number): DomQueryResult;
|
|
14
32
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `bdg dom query` — find elements by CSS selector and populate the query cache.
|
|
3
3
|
*/
|
|
4
|
-
import { noMatchesError, queryDOMElements } from './helpers/index.js';
|
|
4
|
+
import { noMatchesError, pageDocumentId, queryDOMElements } from './helpers/index.js';
|
|
5
|
+
import { VIEWPORT_HINT_LIMIT } from './helpers/query.js';
|
|
5
6
|
import { runCommand } from '../shared/CommandRunner.js';
|
|
7
|
+
import { QUERY_JSON_LIST_LIMIT } from '../../constants.js';
|
|
6
8
|
import { QueryCacheManager } from '../../session/QueryCacheManager.js';
|
|
7
9
|
import { formatDomQuery } from '../../ui/formatters/dom.js';
|
|
8
10
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
11
|
+
/** Matches `dom query` lists without `--limit` (human output) */
|
|
12
|
+
export const QUERY_LIST_LIMIT = 50;
|
|
9
13
|
/**
|
|
10
14
|
* Handle `bdg dom query <selector>`.
|
|
11
15
|
*
|
|
12
|
-
* Runs the selector, caches the
|
|
13
|
-
* elements by index, and
|
|
16
|
+
* Runs the selector, caches the described matches so later commands can
|
|
17
|
+
* reference elements by index, and lists the first `--limit` of them (50,
|
|
18
|
+
* or {@link QUERY_JSON_LIST_LIMIT} with `--json`; 0 = all) with the total
|
|
19
|
+
* count. The first {@link QUERY_CACHE_LIMIT} are indexed whatever is listed.
|
|
14
20
|
* No match exits 83, like `dom get` and `dom a11y`, and clears the cache so
|
|
15
21
|
* indices of an earlier query are not used by mistake.
|
|
16
22
|
*/
|
|
17
23
|
export async function handleDomQuery(selector, options) {
|
|
24
|
+
const limit = options.limit ?? (options.json ? QUERY_JSON_LIST_LIMIT : QUERY_LIST_LIMIT);
|
|
18
25
|
await runCommand(async () => {
|
|
19
|
-
const
|
|
26
|
+
const document = await pageDocumentId();
|
|
27
|
+
const result = await queryDOMElements(selector, limit);
|
|
20
28
|
const cache = QueryCacheManager.getInstance();
|
|
21
29
|
if (result.count === 0) {
|
|
22
30
|
await cache.clear();
|
|
@@ -28,8 +36,33 @@ export async function handleDomQuery(selector, options) {
|
|
|
28
36
|
errorContext: { suggestion: err.suggestion },
|
|
29
37
|
};
|
|
30
38
|
}
|
|
31
|
-
await cache.set(result);
|
|
32
|
-
return { success: true, data: result };
|
|
39
|
+
await cache.set(result, document);
|
|
40
|
+
return { success: true, data: listedMatches(result, limit) };
|
|
33
41
|
}, options, formatDomQuery);
|
|
34
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* The matches to list: the first `limit` (all with 0), with how many were
|
|
45
|
+
* left out and, when not every match was described, how many can be used by
|
|
46
|
+
* index. Nothing is added when the limit cut nothing (a match that could not
|
|
47
|
+
* be described is just missing, as before). When more than
|
|
48
|
+
* {@link VIEWPORT_HINT_LIMIT} are listed, `viewportChecked` says that only
|
|
49
|
+
* the first ones have a viewport position.
|
|
50
|
+
*
|
|
51
|
+
* @param result - Query result with every described match
|
|
52
|
+
* @param limit - Matches to list (0 = all)
|
|
53
|
+
* @returns Result to output
|
|
54
|
+
*/
|
|
55
|
+
export function listedMatches(result, limit) {
|
|
56
|
+
const listed = limit === 0 || result.count <= limit
|
|
57
|
+
? result
|
|
58
|
+
: {
|
|
59
|
+
...result,
|
|
60
|
+
nodes: result.nodes.slice(0, limit),
|
|
61
|
+
omitted: result.count - Math.min(limit, result.nodes.length),
|
|
62
|
+
...(result.nodes.length < result.count && { indexed: result.nodes.length }),
|
|
63
|
+
};
|
|
64
|
+
return listed.nodes.length > VIEWPORT_HINT_LIMIT
|
|
65
|
+
? { ...listed, viewportChecked: VIEWPORT_HINT_LIMIT }
|
|
66
|
+
: listed;
|
|
67
|
+
}
|
|
35
68
|
//# sourceMappingURL=query.js.map
|
|
@@ -14,6 +14,7 @@ import { OutputBuilder, buildSuccessResponse } from '../../ui/OutputBuilder.js';
|
|
|
14
14
|
import { formatDomScreenshot } from '../../ui/formatters/dom.js';
|
|
15
15
|
import { createLogger } from '../../ui/logging/index.js';
|
|
16
16
|
import { delay } from '../../utils/async.js';
|
|
17
|
+
import { makeDirectory } from '../../utils/directories.js';
|
|
17
18
|
import { getErrorMessage } from '../../utils/errors.js';
|
|
18
19
|
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
19
20
|
import { filterDefined } from '../../utils/objects.js';
|
|
@@ -110,7 +111,7 @@ function ensureDirectory(dirPath, fs) {
|
|
|
110
111
|
throw new CommandError(`--follow needs a directory, but ${dirPath} is a file`, { suggestion: 'Give a directory for the frames, e.g. bdg dom screenshot ./frames --follow' }, EXIT_CODES.INVALID_ARGUMENTS);
|
|
111
112
|
}
|
|
112
113
|
try {
|
|
113
|
-
|
|
114
|
+
makeDirectory(dirPath);
|
|
114
115
|
}
|
|
115
116
|
catch (error) {
|
|
116
117
|
throw outputPathError(dirPath, error);
|
|
@@ -188,6 +189,7 @@ async function handleSequenceCapture(outputDir, options) {
|
|
|
188
189
|
/**
|
|
189
190
|
* End a capture sequence on an error (e.g. the element disappeared): print
|
|
190
191
|
* it (one JSON line with `--json`, like the frames) and exit with its code.
|
|
192
|
+
* It stays compact on a terminal too, since it ends the NDJSON frame stream.
|
|
191
193
|
*
|
|
192
194
|
* @param error - Capture error
|
|
193
195
|
* @param captured - Frames captured before it
|
|
@@ -21,10 +21,11 @@ export interface SemanticNodeWithContext {
|
|
|
21
21
|
* link's href, a field's type and name), like `dom query` does, and is
|
|
22
22
|
* followed by up to 500 characters of the element's text
|
|
23
23
|
* (all of it with `dom get --full`) when it is longer than the one-line
|
|
24
|
-
* preview
|
|
24
|
+
* preview or the role line shows an accessible name other than the text,
|
|
25
|
+
* or, for an element without text or name, what it holds.
|
|
25
26
|
*
|
|
26
27
|
* @param data - Accessibility node and optional DOM context
|
|
27
|
-
* @returns Role line, plus a text line for elements with longer text
|
|
28
|
+
* @returns Role line, plus a text line for elements with longer or differently named text
|
|
28
29
|
*/
|
|
29
30
|
export declare function formatSemanticNodeWithContext(data: SemanticNodeWithContext): string;
|
|
30
31
|
/**
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* their surrounding DOM context and to fall back gracefully when only one
|
|
6
6
|
* of the two data sources is available.
|
|
7
7
|
*/
|
|
8
|
-
import { MASKED_VALUE } from '../../runtime/dom/elementInfo.js';
|
|
8
|
+
import { MASKED_VALUE, isLabelClass } from '../../runtime/dom/elementInfo.js';
|
|
9
9
|
import { synthesizeA11yNode } from '../../telemetry/roleInference.js';
|
|
10
10
|
import { keyAttributeItems } from '../../ui/formatters/keyAttributes.js';
|
|
11
11
|
import { joinLines } from '../../ui/formatting.js';
|
|
@@ -29,9 +29,8 @@ function buildContextText(node, domContext) {
|
|
|
29
29
|
}
|
|
30
30
|
if (domContext) {
|
|
31
31
|
const tagPart = `<${domContext.tag}`;
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
: '';
|
|
32
|
+
const classes = (domContext.classes ?? []).filter(isLabelClass).slice(0, 3);
|
|
33
|
+
const classPart = classes.length > 0 ? `.${classes.join('.')}` : '';
|
|
35
34
|
const previewPart = domContext.preview && !domContext.text ? ` "${domContext.preview}"` : '';
|
|
36
35
|
return ` ${tagPart}${classPart}>${previewPart}`;
|
|
37
36
|
}
|
|
@@ -86,10 +85,11 @@ function buildPropertiesText(node) {
|
|
|
86
85
|
* link's href, a field's type and name), like `dom query` does, and is
|
|
87
86
|
* followed by up to 500 characters of the element's text
|
|
88
87
|
* (all of it with `dom get --full`) when it is longer than the one-line
|
|
89
|
-
* preview
|
|
88
|
+
* preview or the role line shows an accessible name other than the text,
|
|
89
|
+
* or, for an element without text or name, what it holds.
|
|
90
90
|
*
|
|
91
91
|
* @param data - Accessibility node and optional DOM context
|
|
92
|
-
* @returns Role line, plus a text line for elements with longer text
|
|
92
|
+
* @returns Role line, plus a text line for elements with longer or differently named text
|
|
93
93
|
*/
|
|
94
94
|
export function formatSemanticNodeWithContext(data) {
|
|
95
95
|
const { node, domContext } = data;
|
|
@@ -99,13 +99,44 @@ export function formatSemanticNodeWithContext(data) {
|
|
|
99
99
|
const propsText = buildPropertiesText(node);
|
|
100
100
|
const inferredText = node.inferred ? ' (inferred from DOM)' : '';
|
|
101
101
|
const line = `${roleText}${contextText}${keysText}${propsText}${inferredText}`;
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
const text = textNotOnRoleLine(node, domContext);
|
|
103
|
+
if (text)
|
|
104
|
+
return joinLines(line, elementTextLine(text));
|
|
104
105
|
if (domContext?.childCount !== undefined && !node.name) {
|
|
105
|
-
return joinLines(line, emptyElementLine(domContext.children ?? [], domContext.childCount));
|
|
106
|
+
return joinLines(line, emptyElementLine(domContext.children ?? [], domContext.childCount, domContext.shadowChildren));
|
|
106
107
|
}
|
|
107
108
|
return line;
|
|
108
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The element's text when the role line does not show it: text longer than
|
|
112
|
+
* the one-line preview, or the visible text of an element whose accessible
|
|
113
|
+
* name is something else (an editor named by its aria-label), unless its
|
|
114
|
+
* name or value shows that text (a long heading with inline children is
|
|
115
|
+
* named by all of it). Texts are compared ignoring case and whitespace.
|
|
116
|
+
* A sensitive field's text is never shown.
|
|
117
|
+
*
|
|
118
|
+
* @param node - Accessibility node
|
|
119
|
+
* @param domContext - DOM context with the text
|
|
120
|
+
* @returns Text for the text line, or undefined
|
|
121
|
+
*/
|
|
122
|
+
function textNotOnRoleLine(node, domContext) {
|
|
123
|
+
if (domContext?.sensitive)
|
|
124
|
+
return undefined;
|
|
125
|
+
const text = domContext?.text ?? (node.name ? domContext?.preview : undefined);
|
|
126
|
+
if (!text)
|
|
127
|
+
return undefined;
|
|
128
|
+
const shown = [node.name, node.value].map((value) => comparableText(value ?? ''));
|
|
129
|
+
return shown.includes(comparableText(text)) ? undefined : text;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Text in the form texts are compared in.
|
|
133
|
+
*
|
|
134
|
+
* @param text - Text
|
|
135
|
+
* @returns Lowercased text with whitespace collapsed
|
|
136
|
+
*/
|
|
137
|
+
function comparableText(text) {
|
|
138
|
+
return text.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
139
|
+
}
|
|
109
140
|
/**
|
|
110
141
|
* Resolve an a11y node, falling back to a DOM-synthesized one when only
|
|
111
142
|
* DOM context is available. Returns null when neither source can produce one.
|
|
@@ -78,9 +78,30 @@ export interface CommandMetadata {
|
|
|
78
78
|
arguments: ArgumentMetadata[];
|
|
79
79
|
/** Command options */
|
|
80
80
|
options: OptionMetadata[];
|
|
81
|
+
/** Text shown after the options in `--help` (examples, output legend) */
|
|
82
|
+
helpText?: string;
|
|
81
83
|
/** Subcommands */
|
|
82
84
|
subcommands: CommandMetadata[];
|
|
83
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Command summary for the compact root help: one-line description, arguments
|
|
88
|
+
* and flags with their descriptions (behaviors, defaults and choices are in
|
|
89
|
+
* `bdg <command> --help --json`).
|
|
90
|
+
*/
|
|
91
|
+
export interface CompactCommand {
|
|
92
|
+
/** Command name */
|
|
93
|
+
name: string;
|
|
94
|
+
/** Command aliases (only when it has some) */
|
|
95
|
+
aliases?: readonly string[];
|
|
96
|
+
/** First line of the description */
|
|
97
|
+
description: string;
|
|
98
|
+
/** Arguments as in usage, e.g. "<selector> [index]" (only when it takes some) */
|
|
99
|
+
arguments?: string;
|
|
100
|
+
/** Visible options: flags to description */
|
|
101
|
+
options?: Record<string, string>;
|
|
102
|
+
/** Subcommands (only for command groups) */
|
|
103
|
+
subcommands?: CompactCommand[];
|
|
104
|
+
}
|
|
84
105
|
/**
|
|
85
106
|
* Runtime state information for dynamic command availability.
|
|
86
107
|
*/
|
|
@@ -112,7 +133,7 @@ export interface Capabilities {
|
|
|
112
133
|
};
|
|
113
134
|
}
|
|
114
135
|
/**
|
|
115
|
-
* Root machine-readable help structure.
|
|
136
|
+
* Root machine-readable help structure (`bdg --help --json --full`).
|
|
116
137
|
*/
|
|
117
138
|
export interface MachineReadableHelp {
|
|
118
139
|
/** CLI name */
|
|
@@ -142,10 +163,34 @@ export interface MachineReadableHelp {
|
|
|
142
163
|
capabilities: Capabilities;
|
|
143
164
|
}
|
|
144
165
|
/**
|
|
145
|
-
*
|
|
166
|
+
* Compact root help (`bdg --help --json`): the full help with a command tree
|
|
167
|
+
* of names, one-line descriptions and flags.
|
|
168
|
+
*/
|
|
169
|
+
export interface CompactHelp extends Omit<MachineReadableHelp, 'command'> {
|
|
170
|
+
/** Where the details are */
|
|
171
|
+
details: string;
|
|
172
|
+
/** Root command summary */
|
|
173
|
+
command: CompactCommand;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Help for one command (`bdg <command> --help --json`): its full metadata
|
|
177
|
+
* (option behaviors, defaults, choices, help text), its subcommands in compact
|
|
178
|
+
* form, and the exit codes.
|
|
179
|
+
*/
|
|
180
|
+
export interface CommandHelp extends Pick<MachineReadableHelp, 'name' | 'version' | 'description' | 'exitCodes'> {
|
|
181
|
+
/** Full command path, e.g. "bdg dom query" */
|
|
182
|
+
path: string;
|
|
183
|
+
/** Command metadata; subcommands summarized (ask each for its details) */
|
|
184
|
+
command: Omit<CommandMetadata, 'subcommands'> & {
|
|
185
|
+
subcommands: CompactCommand[];
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Generates the full machine-readable help from a Commander program
|
|
190
|
+
* (`bdg --help --json --full`).
|
|
146
191
|
*
|
|
147
192
|
* Includes comprehensive metadata for agent discovery:
|
|
148
|
-
* - Command structure and options
|
|
193
|
+
* - Command structure and options with behaviors
|
|
149
194
|
* - Exit codes with semantic meanings
|
|
150
195
|
* - Task-to-command mappings with CDP alternatives
|
|
151
196
|
* - Runtime state and command availability
|
|
@@ -154,34 +199,52 @@ export interface MachineReadableHelp {
|
|
|
154
199
|
*
|
|
155
200
|
* @param program - Commander program instance
|
|
156
201
|
* @returns Machine-readable help structure
|
|
202
|
+
*/
|
|
203
|
+
export declare function generateMachineReadableHelp(program: Command): MachineReadableHelp;
|
|
204
|
+
/**
|
|
205
|
+
* Generates the compact root help (`bdg --help --json`): the full help with
|
|
206
|
+
* the command tree reduced to names, one-line descriptions and flags.
|
|
207
|
+
*
|
|
208
|
+
* @param program - Commander program instance
|
|
209
|
+
* @returns Compact help structure
|
|
210
|
+
*/
|
|
211
|
+
export declare function generateCompactHelp(program: Command): CompactHelp;
|
|
212
|
+
/**
|
|
213
|
+
* The command a command line addresses: follows the words that name
|
|
214
|
+
* subcommands and skips the others (option values, arguments), stopping at a
|
|
215
|
+
* command without subcommands.
|
|
216
|
+
*
|
|
217
|
+
* @param program - Root Commander program instance
|
|
218
|
+
* @param words - Command-line words, e.g. ['dom', 'query', '.item']
|
|
219
|
+
* @returns The addressed command (the program when no word names one)
|
|
157
220
|
*
|
|
158
221
|
* @example
|
|
159
222
|
* ```typescript
|
|
160
|
-
*
|
|
161
|
-
* import { generateMachineReadableHelp } from './help/machineReadableHelp.js';
|
|
162
|
-
*
|
|
163
|
-
* const help = generateMachineReadableHelp(program);
|
|
164
|
-
* console.log(JSON.stringify(help, null, 2));
|
|
223
|
+
* resolveCommand(program, ['--session', 'a', 'dom', 'query', '.item']).name(); // 'query'
|
|
165
224
|
* ```
|
|
166
225
|
*/
|
|
167
|
-
export declare function
|
|
226
|
+
export declare function resolveCommand(program: Command, words: string[]): Command;
|
|
168
227
|
/**
|
|
169
|
-
*
|
|
228
|
+
* Full command path, e.g. "bdg dom query".
|
|
170
229
|
*
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
|
|
230
|
+
* @param command - Commander command instance
|
|
231
|
+
* @returns Names from the program down to the command
|
|
232
|
+
*/
|
|
233
|
+
export declare function commandPath(command: Command): string;
|
|
234
|
+
/**
|
|
235
|
+
* Generates machine-readable help for one command: its full metadata,
|
|
236
|
+
* compact subcommands (a group lists them like the root help does) and the
|
|
237
|
+
* exit codes.
|
|
174
238
|
*
|
|
175
239
|
* @param program - Root Commander program instance
|
|
176
|
-
* @param
|
|
177
|
-
* @returns
|
|
240
|
+
* @param command - The command (from {@link resolveCommand})
|
|
241
|
+
* @returns Help for the command
|
|
178
242
|
*
|
|
179
243
|
* @example
|
|
180
244
|
* ```typescript
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* console.log(help.command.name); // 'query'
|
|
245
|
+
* const help = generateCommandHelp(program, resolveCommand(program, ['dom', 'query']));
|
|
246
|
+
* console.log(help.path); // 'bdg dom query'
|
|
184
247
|
* ```
|
|
185
248
|
*/
|
|
186
|
-
export declare function
|
|
249
|
+
export declare function generateCommandHelp(program: Command, command: Command): CommandHelp;
|
|
187
250
|
//# sourceMappingURL=helpJson.d.ts.map
|