browser-debugger-cli 0.9.0 → 0.11.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 +268 -0
- package/README.md +15 -1
- package/dist/commands/dom/a11y.js +2 -1
- package/dist/commands/dom/formInteraction.js +56 -25
- package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
- package/dist/commands/dom/helpers/keyAttributes.js +54 -0
- package/dist/commands/dom/helpers/query.d.ts +1 -1
- package/dist/commands/dom/helpers/query.js +66 -19
- package/dist/commands/dom/helpers/runElementCommand.js +4 -3
- package/dist/commands/dom/helpers/screenshot.js +85 -12
- package/dist/commands/dom/index.d.ts +1 -0
- package/dist/commands/dom/index.js +8 -3
- package/dist/commands/dom/inspect.d.ts +15 -0
- package/dist/commands/dom/inspect.js +82 -0
- package/dist/commands/dom/layout.js +2 -2
- package/dist/commands/dom/listeners.js +2 -2
- package/dist/commands/dom/semanticUtils.d.ts +14 -1
- package/dist/commands/dom/semanticUtils.js +44 -3
- package/dist/commands/installSkill.d.ts +20 -0
- package/dist/commands/installSkill.js +87 -0
- package/dist/commands/network/list.js +13 -2
- package/dist/commands/optionBehaviors.js +48 -6
- package/dist/commands/page.d.ts +1 -1
- package/dist/commands/page.js +62 -3
- package/dist/commands/shared/commonOptions.d.ts +4 -0
- package/dist/commands/shared/commonOptions.js +9 -0
- package/dist/commands/shared/optionTypes.d.ts +21 -0
- package/dist/commands/shared/startHelpers.d.ts +66 -0
- package/dist/commands/shared/startHelpers.js +91 -10
- package/dist/commands/shared/validation.d.ts +11 -0
- package/dist/commands/shared/validation.js +16 -0
- package/dist/commands.js +3 -0
- package/dist/daemon/launcher.d.ts +8 -1
- package/dist/daemon/launcher.js +3 -1
- package/dist/daemon/session/Session.d.ts +7 -0
- package/dist/daemon/session/Session.js +23 -1
- package/dist/daemon/session/commandRegistry.d.ts +14 -1
- package/dist/daemon/session/commandRegistry.js +65 -9
- package/dist/daemon/session/interactions.d.ts +18 -5
- package/dist/daemon/session/interactions.js +22 -12
- package/dist/daemon.js +3565 -329
- package/dist/errors/messages.d.ts +85 -0
- package/dist/errors/messages.js +128 -1
- package/dist/index.js +2151 -960
- package/dist/ipc/client.d.ts +9 -0
- package/dist/ipc/client.js +13 -0
- package/dist/ipc/protocol/commands.d.ts +56 -1
- package/dist/ipc/protocol/commands.js +2 -0
- package/dist/ipc/protocol/domTypes.d.ts +35 -2
- package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
- package/dist/ipc/protocol/inspectTypes.js +10 -0
- package/dist/runtime/dom/actionEffects.d.ts +94 -15
- package/dist/runtime/dom/actionEffects.js +173 -27
- package/dist/runtime/dom/actionEffectsScripts.d.ts +52 -14
- package/dist/runtime/dom/actionEffectsScripts.js +224 -32
- package/dist/runtime/dom/elementInfo.d.ts +26 -0
- package/dist/runtime/dom/elementInfo.js +65 -0
- package/dist/runtime/dom/eventListeners.js +14 -4
- package/dist/runtime/dom/formFillHelpers/fill.d.ts +3 -4
- package/dist/runtime/dom/formFillHelpers/fill.js +77 -28
- package/dist/runtime/dom/frameSelection.d.ts +11 -0
- package/dist/runtime/dom/frameSelection.js +20 -1
- package/dist/runtime/dom/frames.d.ts +38 -5
- package/dist/runtime/dom/frames.js +136 -21
- package/dist/runtime/dom/inspect.d.ts +28 -0
- package/dist/runtime/dom/inspect.js +557 -0
- package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
- package/dist/runtime/dom/inspectAllStyles.js +385 -0
- package/dist/runtime/dom/inspectCascade.d.ts +94 -0
- package/dist/runtime/dom/inspectCascade.js +371 -0
- package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
- package/dist/runtime/dom/inspectCascadeModel.js +232 -0
- package/dist/runtime/dom/inspectHints.d.ts +62 -0
- package/dist/runtime/dom/inspectHints.js +305 -0
- package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
- package/dist/runtime/dom/inspectLayoutModel.js +346 -0
- package/dist/runtime/dom/inspectModel.d.ts +74 -0
- package/dist/runtime/dom/inspectModel.js +184 -0
- package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
- package/dist/runtime/dom/inspectPaintModel.js +461 -0
- package/dist/runtime/dom/inspectRules.d.ts +37 -0
- package/dist/runtime/dom/inspectRules.js +101 -0
- package/dist/runtime/dom/inspectScripts.d.ts +132 -0
- package/dist/runtime/dom/inspectScripts.js +263 -0
- package/dist/runtime/dom/inspectTree.d.ts +40 -0
- package/dist/runtime/dom/inspectTree.js +134 -0
- package/dist/runtime/dom/inspectVariables.d.ts +33 -0
- package/dist/runtime/dom/inspectVariables.js +94 -0
- package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
- package/dist/runtime/dom/inspectWhyModel.js +134 -0
- package/dist/runtime/dom/layout.d.ts +5 -1
- package/dist/runtime/dom/layout.js +10 -3
- package/dist/runtime/dom/listenerPageScripts.d.ts +11 -5
- package/dist/runtime/dom/listenerPageScripts.js +95 -9
- package/dist/runtime/dom/listenerSummary.d.ts +4 -0
- package/dist/runtime/dom/listenerSummary.js +26 -9
- package/dist/runtime/dom/reactEventHelpers.d.ts +5 -0
- package/dist/runtime/dom/reactEventHelpers.js +12 -4
- package/dist/runtime/page/emulation.d.ts +20 -0
- package/dist/runtime/page/emulation.js +37 -0
- package/dist/telemetry/a11y.d.ts +10 -0
- package/dist/telemetry/a11y.js +78 -1
- package/dist/telemetry/console.d.ts +1 -0
- package/dist/telemetry/console.js +100 -5
- package/dist/telemetry/network.js +3 -1
- package/dist/types.d.ts +40 -0
- package/dist/ui/formatters/details.d.ts +8 -0
- package/dist/ui/formatters/details.js +59 -3
- package/dist/ui/formatters/dom.d.ts +2 -1
- package/dist/ui/formatters/dom.js +25 -9
- package/dist/ui/formatters/inspect.d.ts +39 -0
- package/dist/ui/formatters/inspect.js +596 -0
- package/dist/ui/formatters/installSkill.d.ts +11 -0
- package/dist/ui/formatters/installSkill.js +31 -0
- package/dist/ui/formatters/keyAttributes.d.ts +19 -0
- package/dist/ui/formatters/keyAttributes.js +84 -0
- package/dist/ui/formatters/layout.js +2 -2
- package/dist/ui/formatters/networkHeaders.d.ts +13 -0
- package/dist/ui/formatters/networkHeaders.js +23 -3
- package/dist/ui/formatters/networkList.d.ts +29 -1
- package/dist/ui/formatters/networkList.js +86 -20
- package/dist/ui/formatters/status.js +1 -1
- package/dist/ui/formatting.d.ts +9 -0
- package/dist/ui/formatting.js +6 -3
- package/dist/ui/messages/commands.d.ts +123 -7
- package/dist/ui/messages/commands.js +181 -10
- package/dist/ui/messages/networkMessages.d.ts +14 -0
- package/dist/ui/messages/networkMessages.js +18 -0
- package/dist/ui/messages/session.d.ts +14 -0
- package/dist/ui/messages/session.js +20 -0
- package/dist/utils/async.d.ts +9 -0
- package/dist/utils/async.js +17 -0
- package/dist/utils/color.d.ts +84 -0
- package/dist/utils/color.js +376 -0
- package/dist/utils/cssValues.d.ts +109 -0
- package/dist/utils/cssValues.js +236 -0
- package/dist/utils/selectorFilters.d.ts +12 -0
- package/dist/utils/selectorFilters.js +29 -0
- package/package.json +2 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Key attributes of an element (`KeyAttributes`) shortened for one line of
|
|
3
|
+
* human output: `dom query` shows them in the element's tag, `dom get` after
|
|
4
|
+
* its role. `--json` has the full values.
|
|
5
|
+
*/
|
|
6
|
+
import { cutMiddle, escapeControlChars, truncateUrl } from '../formatting.js';
|
|
7
|
+
import { safeParseUrl } from '../../utils/url.js';
|
|
8
|
+
/** Longest value shown (longer ones are cut in the middle) */
|
|
9
|
+
const MAX_VALUE_LENGTH = 40;
|
|
10
|
+
/**
|
|
11
|
+
* An image URL as its file name, after `…/` when it had a path or host
|
|
12
|
+
* before it (`…/sl-404.168b1cce.jpg`); data: URLs keep their start.
|
|
13
|
+
*
|
|
14
|
+
* @param src - `src` attribute
|
|
15
|
+
* @returns Short form
|
|
16
|
+
*/
|
|
17
|
+
function fileName(src) {
|
|
18
|
+
if (/^(data|blob):/i.test(src))
|
|
19
|
+
return src;
|
|
20
|
+
const path = src.split(/[?#]/)[0] ?? src;
|
|
21
|
+
const name = path.substring(path.lastIndexOf('/') + 1);
|
|
22
|
+
return name && name !== path ? `…/${name}` : src;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* An iframe URL as its host, with `/…` when it has a path or query
|
|
26
|
+
* (`//pay.example/…`); others (about:blank, relative URLs) as given.
|
|
27
|
+
*
|
|
28
|
+
* @param src - `src` attribute
|
|
29
|
+
* @returns Short form
|
|
30
|
+
*/
|
|
31
|
+
function hostOf(src) {
|
|
32
|
+
const parsed = /^https?:/i.test(src) ? safeParseUrl(src) : null;
|
|
33
|
+
if (!parsed)
|
|
34
|
+
return src;
|
|
35
|
+
const more = parsed.pathname.length > 1 || parsed.search ? '/…' : '';
|
|
36
|
+
return `//${parsed.host}${more}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A link or form target: an absolute web URL as `//host/path`, cut in the
|
|
40
|
+
* middle of the path (`//` keeps it from reading as a relative path).
|
|
41
|
+
*
|
|
42
|
+
* @param url - `href` or `action` attribute
|
|
43
|
+
* @returns Short form
|
|
44
|
+
*/
|
|
45
|
+
function shortUrl(url) {
|
|
46
|
+
return /^https?:/i.test(url) ? `//${truncateUrl(url, MAX_VALUE_LENGTH - 2)}` : url;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* One value shortened for display.
|
|
50
|
+
*
|
|
51
|
+
* @param tag - Element tag
|
|
52
|
+
* @param name - Attribute name
|
|
53
|
+
* @param value - Full value
|
|
54
|
+
* @returns Short value on one line
|
|
55
|
+
*/
|
|
56
|
+
function shortValue(tag, name, value) {
|
|
57
|
+
let short = value;
|
|
58
|
+
if (name === 'src')
|
|
59
|
+
short = tag === 'iframe' ? hostOf(value) : fileName(value);
|
|
60
|
+
else if (name === 'href' || name === 'action')
|
|
61
|
+
short = shortUrl(value);
|
|
62
|
+
return cutMiddle(escapeControlChars(short.replace(/\s+/g, ' ').trim()), MAX_VALUE_LENGTH);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Key attributes as `name="value"` items, values shortened: an image's
|
|
66
|
+
* file name, an iframe's host, links without their scheme, the rest cut in
|
|
67
|
+
* the middle at 40 characters. `checked` is shown as a bare word, and left
|
|
68
|
+
* out when false.
|
|
69
|
+
*
|
|
70
|
+
* @param tag - Element tag
|
|
71
|
+
* @param attributes - Key attributes
|
|
72
|
+
* @param leaveOut - Names not to show (already shown elsewhere)
|
|
73
|
+
* @returns Items in attribute order, e.g. `['src="…/logo.png"', 'alt="Logo"']`
|
|
74
|
+
*/
|
|
75
|
+
export function keyAttributeItems(tag, attributes, leaveOut = new Set()) {
|
|
76
|
+
return Object.entries(attributes ?? {}).flatMap(([name, value]) => {
|
|
77
|
+
if (leaveOut.has(name) || value === false)
|
|
78
|
+
return [];
|
|
79
|
+
if (value === true)
|
|
80
|
+
return [name];
|
|
81
|
+
return [`${name}="${shortValue(tag, name, value)}"`];
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=keyAttributes.js.map
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { indexSourceText } from '../../errors/messages.js';
|
|
5
5
|
import { OutputFormatter } from '../formatting.js';
|
|
6
|
-
import { indexLayoutHeadline, layoutHeadline, layoutPositionLabel, moreMatchesNote, pageLayoutLine, } from '../messages/commands.js';
|
|
6
|
+
import { coverText, indexLayoutHeadline, layoutHeadline, layoutPositionLabel, moreMatchesNote, pageLayoutLine, } from '../messages/commands.js';
|
|
7
7
|
/** Elements listed in human output (JSON has up to 100) */
|
|
8
8
|
const LAYOUT_DISPLAY_LIMIT = 20;
|
|
9
9
|
/**
|
|
@@ -23,7 +23,7 @@ export function layoutLine(element, viewport) {
|
|
|
23
23
|
`[${element.index}] ${element.element}${element.text ? ` "${element.text}"` : ''}`,
|
|
24
24
|
element.inViewport !== 'hidden' && `${bounds.x},${bounds.y} ${bounds.width}×${bounds.height}`,
|
|
25
25
|
layoutPositionLabel(element, viewport),
|
|
26
|
-
element.coveredBy &&
|
|
26
|
+
element.coveredBy && coverText(element.coveredBy, element.coverTransparent),
|
|
27
27
|
element.inert && 'inert',
|
|
28
28
|
element.invisible,
|
|
29
29
|
element.context && element.context !== element.clippedBy && `in ${element.context}`,
|
|
@@ -11,4 +11,17 @@ import type { SessionNetworkHeadersData } from '../../ipc/protocol/commands.js';
|
|
|
11
11
|
* @returns Formatted string for console output
|
|
12
12
|
*/
|
|
13
13
|
export declare function formatNetworkHeaders(data: SessionNetworkHeadersData): string;
|
|
14
|
+
/**
|
|
15
|
+
* The values of a header, one per line. A header sent several times reaches
|
|
16
|
+
* CDP as one value with the values joined by newlines (`Set-Cookie`, or a
|
|
17
|
+
* server repeating `Strict-Transport-Security`); a value sent more than once
|
|
18
|
+
* is listed once, saying how often it was sent. `Set-Cookie` lines are all
|
|
19
|
+
* kept: each one sets a cookie, and repeating one is not the same as sending
|
|
20
|
+
* it once.
|
|
21
|
+
*
|
|
22
|
+
* @param name - Header name
|
|
23
|
+
* @param value - Header value as CDP reports it
|
|
24
|
+
* @returns e.g. `['max-age=63072000 (sent 2 times)']`
|
|
25
|
+
*/
|
|
26
|
+
export declare function headerValueLines(name: string, value: string): string[];
|
|
14
27
|
//# sourceMappingURL=networkHeaders.d.ts.map
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { formatRequestStatus } from './requestStatus.js';
|
|
7
7
|
import { OutputFormatter } from '../formatting.js';
|
|
8
|
+
import { headerRepeatedNote } from '../messages/networkMessages.js';
|
|
8
9
|
/**
|
|
9
10
|
* Format network request headers for display.
|
|
10
11
|
*
|
|
@@ -33,11 +34,30 @@ export function formatNetworkHeaders(data) {
|
|
|
33
34
|
fmt.text(`Request ID: ${data.requestId}`);
|
|
34
35
|
return fmt.build();
|
|
35
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* The values of a header, one per line. A header sent several times reaches
|
|
39
|
+
* CDP as one value with the values joined by newlines (`Set-Cookie`, or a
|
|
40
|
+
* server repeating `Strict-Transport-Security`); a value sent more than once
|
|
41
|
+
* is listed once, saying how often it was sent. `Set-Cookie` lines are all
|
|
42
|
+
* kept: each one sets a cookie, and repeating one is not the same as sending
|
|
43
|
+
* it once.
|
|
44
|
+
*
|
|
45
|
+
* @param name - Header name
|
|
46
|
+
* @param value - Header value as CDP reports it
|
|
47
|
+
* @returns e.g. `['max-age=63072000 (sent 2 times)']`
|
|
48
|
+
*/
|
|
49
|
+
export function headerValueLines(name, value) {
|
|
50
|
+
if (name.toLowerCase() === 'set-cookie')
|
|
51
|
+
return value.split('\n');
|
|
52
|
+
const counts = new Map();
|
|
53
|
+
for (const line of value.split('\n'))
|
|
54
|
+
counts.set(line, (counts.get(line) ?? 0) + 1);
|
|
55
|
+
return [...counts].map(([line, count]) => count > 1 ? `${line} ${headerRepeatedNote(count)}` : line);
|
|
56
|
+
}
|
|
36
57
|
/**
|
|
37
58
|
* Format a section of headers with consistent formatting.
|
|
38
59
|
*
|
|
39
|
-
* Repeated headers
|
|
40
|
-
* are printed one per line.
|
|
60
|
+
* Repeated headers are printed one value per line ({@link headerValueLines}).
|
|
41
61
|
*
|
|
42
62
|
* @param fmt - Output formatter instance
|
|
43
63
|
* @param headers - Headers to format
|
|
@@ -46,7 +66,7 @@ function formatHeaderSection(fmt, headers) {
|
|
|
46
66
|
const entries = Object.entries(headers).sort(([a], [b]) => a.localeCompare(b));
|
|
47
67
|
const keyWidth = Math.max(...entries.map(([k]) => k.length)) + 4;
|
|
48
68
|
entries.forEach(([key, value]) => {
|
|
49
|
-
value
|
|
69
|
+
headerValueLines(key, value).forEach((line) => fmt.keyValue(` ${key}`, line, keyWidth));
|
|
50
70
|
});
|
|
51
71
|
}
|
|
52
72
|
/**
|
|
@@ -7,22 +7,50 @@
|
|
|
7
7
|
import type { NetworkRequest } from '../../types.js';
|
|
8
8
|
export interface NetworkListOptions {
|
|
9
9
|
verbose?: boolean;
|
|
10
|
+
/** Start of the current page, which the START column counts from ({@link pageStartOf}) */
|
|
11
|
+
pageStart?: PageStart;
|
|
10
12
|
last?: number;
|
|
11
13
|
totalCount?: number;
|
|
12
14
|
/** Requests matching the filters, before --last (defaults to totalCount) */
|
|
13
15
|
filteredCount?: number;
|
|
14
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* When the current page started loading: the request of its document, in
|
|
19
|
+
* Chrome's monotonic time (`sentTime`, seconds) and wall-clock time
|
|
20
|
+
* (`timestamp`, epoch ms).
|
|
21
|
+
*/
|
|
22
|
+
export type PageStart = Pick<NetworkRequest, 'sentTime' | 'timestamp'>;
|
|
23
|
+
/**
|
|
24
|
+
* The start of the current page: the earliest document request of the
|
|
25
|
+
* latest navigation among the requests (its earliest request when its
|
|
26
|
+
* document was not captured).
|
|
27
|
+
*
|
|
28
|
+
* @param requests - All captured requests (before filters, so the document is among them)
|
|
29
|
+
* @returns Its times, or undefined when there are no requests
|
|
30
|
+
*/
|
|
31
|
+
export declare function pageStartOf(requests: NetworkRequest[]): PageStart | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Format a request's start for the START column, relative to the current
|
|
34
|
+
* page's start: tenths of a second up to 100 s, then whole seconds, then
|
|
35
|
+
* minutes.
|
|
36
|
+
*
|
|
37
|
+
* @param request - Request
|
|
38
|
+
* @param pageStart - Start of the current page (none: `-`)
|
|
39
|
+
* @returns e.g. "+0.0s", "+1.2s", "+250s", "+17m", "-35.2s" (earlier page)
|
|
40
|
+
*/
|
|
41
|
+
export declare function formatStartOffset(request: NetworkRequest, pageStart: PageStart | undefined): string;
|
|
15
42
|
/**
|
|
16
43
|
* Rows of the network stream: requests that finished since the last poll,
|
|
17
44
|
* with the column header the first time.
|
|
18
45
|
*
|
|
19
46
|
* @param requests - Newly finished requests
|
|
20
|
-
* @param options - `header` the first time; `verbose` for full URLs
|
|
47
|
+
* @param options - `header` the first time; `verbose` for full URLs; the page start for START
|
|
21
48
|
* @returns Text to print (empty when there is nothing new)
|
|
22
49
|
*/
|
|
23
50
|
export declare function formatNetworkFollowRows(requests: NetworkRequest[], options?: {
|
|
24
51
|
header?: boolean;
|
|
25
52
|
verbose?: boolean;
|
|
53
|
+
pageStart?: PageStart;
|
|
26
54
|
}): string;
|
|
27
55
|
/**
|
|
28
56
|
* Format network requests for display.
|
|
@@ -39,32 +39,99 @@ function formatDuration(ms) {
|
|
|
39
39
|
return ms < 1000 ? `${Math.round(ms)}ms` : `${(ms / 1000).toFixed(1)}s`;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
42
|
+
* The start of the current page: the earliest document request of the
|
|
43
|
+
* latest navigation among the requests (its earliest request when its
|
|
44
|
+
* document was not captured).
|
|
43
45
|
*
|
|
44
|
-
* @param
|
|
46
|
+
* @param requests - All captured requests (before filters, so the document is among them)
|
|
47
|
+
* @returns Its times, or undefined when there are no requests
|
|
48
|
+
*/
|
|
49
|
+
export function pageStartOf(requests) {
|
|
50
|
+
const navigationIds = requests.flatMap((r) => r.navigationId === undefined ? [] : [r.navigationId]);
|
|
51
|
+
const current = navigationIds.length > 0 ? Math.max(...navigationIds) : undefined;
|
|
52
|
+
const page = requests.filter((r) => r.navigationId === current);
|
|
53
|
+
const documents = page.filter((r) => r.resourceType === 'Document');
|
|
54
|
+
const first = (documents.length > 0 ? documents : page).reduce((earliest, r) => (earliest === undefined || r.timestamp < earliest.timestamp ? r : earliest), undefined);
|
|
55
|
+
return (first && {
|
|
56
|
+
timestamp: first.timestamp,
|
|
57
|
+
...(first.sentTime !== undefined && { sentTime: first.sentTime }),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Milliseconds from the page start to a request's start, in Chrome's time
|
|
62
|
+
* when both have it (precise), else in wall-clock time.
|
|
63
|
+
*
|
|
64
|
+
* @param request - Request
|
|
65
|
+
* @param pageStart - Start of the current page
|
|
66
|
+
* @returns Offset (negative for requests of earlier pages)
|
|
67
|
+
*/
|
|
68
|
+
function startOffsetMs(request, pageStart) {
|
|
69
|
+
if (request.sentTime !== undefined && pageStart.sentTime !== undefined) {
|
|
70
|
+
return (request.sentTime - pageStart.sentTime) * 1000;
|
|
71
|
+
}
|
|
72
|
+
return request.timestamp - pageStart.timestamp;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Format a request's start for the START column, relative to the current
|
|
76
|
+
* page's start: tenths of a second up to 100 s, then whole seconds, then
|
|
77
|
+
* minutes.
|
|
78
|
+
*
|
|
79
|
+
* @param request - Request
|
|
80
|
+
* @param pageStart - Start of the current page (none: `-`)
|
|
81
|
+
* @returns e.g. "+0.0s", "+1.2s", "+250s", "+17m", "-35.2s" (earlier page)
|
|
82
|
+
*/
|
|
83
|
+
export function formatStartOffset(request, pageStart) {
|
|
84
|
+
if (!pageStart)
|
|
85
|
+
return '-';
|
|
86
|
+
const ms = startOffsetMs(request, pageStart);
|
|
87
|
+
const seconds = Math.abs(ms) / 1000;
|
|
88
|
+
const sign = ms < -50 ? '-' : '+';
|
|
89
|
+
if (seconds < 99.95)
|
|
90
|
+
return `${sign}${seconds.toFixed(1)}s`;
|
|
91
|
+
if (seconds < 999.5)
|
|
92
|
+
return `${sign}${Math.round(seconds)}s`;
|
|
93
|
+
return `${sign}${Math.floor(seconds / 60)}m`;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Column header aligned to the widest request id and method in the list.
|
|
97
|
+
*
|
|
98
|
+
* @param widths - Column widths
|
|
45
99
|
* @returns Header line
|
|
46
100
|
*/
|
|
47
|
-
function formatColumnHeader(
|
|
48
|
-
return `${'[ID]'.padEnd(
|
|
101
|
+
function formatColumnHeader(widths) {
|
|
102
|
+
return `${'[ID]'.padEnd(widths.id)} ${'START'.padStart(6)} STS ${'METH'.padEnd(widths.method)} TYP ${'SIZE'.padStart(8)} ${'TIME'.padStart(6)} URL`;
|
|
49
103
|
}
|
|
50
104
|
/**
|
|
51
105
|
* Format one request as a table row.
|
|
52
106
|
*
|
|
53
107
|
* @param request - Network request
|
|
54
|
-
* @param
|
|
55
|
-
* @param
|
|
108
|
+
* @param options - Show full URLs (`verbose`), the page start for START
|
|
109
|
+
* @param widths - Column widths (ids and methods vary in length)
|
|
56
110
|
* @returns Row text
|
|
57
111
|
*/
|
|
58
|
-
function formatRequestLine(request,
|
|
59
|
-
const id = `[${request.requestId}]`.padEnd(
|
|
112
|
+
function formatRequestLine(request, options, widths) {
|
|
113
|
+
const id = `[${request.requestId}]`.padEnd(widths.id);
|
|
114
|
+
const start = formatStartOffset(request, options.pageStart).padStart(6);
|
|
60
115
|
const status = formatStatus(request).padEnd(3);
|
|
61
|
-
const method = request.method.padEnd(
|
|
116
|
+
const method = request.method.padEnd(widths.method);
|
|
62
117
|
const type = getResourceTypeAbbr(request.resourceType, request.mimeType).padEnd(3);
|
|
63
118
|
const size = formatSize(request.encodedDataLength).padStart(8);
|
|
64
119
|
const time = formatDuration(request.duration).padStart(6);
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
120
|
+
const url = options.verbose ? request.url : truncateUrl(request.url, 50);
|
|
121
|
+
return `${id} ${start} ${status} ${method} ${type} ${size} ${time} ${url}`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Column widths fitting the rows.
|
|
125
|
+
*
|
|
126
|
+
* @param requests - Rows
|
|
127
|
+
* @param minIdWidth - Narrowest id column
|
|
128
|
+
* @returns Widths
|
|
129
|
+
*/
|
|
130
|
+
function columnWidths(requests, minIdWidth) {
|
|
131
|
+
return {
|
|
132
|
+
id: Math.max(minIdWidth, ...requests.map((r) => r.requestId.length + 2)),
|
|
133
|
+
method: Math.max('METH'.length, ...requests.map((r) => r.method.length)),
|
|
134
|
+
};
|
|
68
135
|
}
|
|
69
136
|
/**
|
|
70
137
|
* Header line with how many requests are shown.
|
|
@@ -91,12 +158,11 @@ function formatNetworkListHuman(requests, options) {
|
|
|
91
158
|
fmt.text('No matching requests found.');
|
|
92
159
|
return fmt.build();
|
|
93
160
|
}
|
|
94
|
-
const
|
|
95
|
-
fmt.text(formatColumnHeader(
|
|
161
|
+
const widths = columnWidths(requests, '[ID]'.length);
|
|
162
|
+
fmt.text(formatColumnHeader(widths));
|
|
96
163
|
fmt.separator('─', SEPARATOR_WIDTH);
|
|
97
|
-
const verbose = options.verbose ?? false;
|
|
98
164
|
for (const request of requests) {
|
|
99
|
-
fmt.text(formatRequestLine(request,
|
|
165
|
+
fmt.text(formatRequestLine(request, options, widths));
|
|
100
166
|
}
|
|
101
167
|
return fmt.build();
|
|
102
168
|
}
|
|
@@ -107,19 +173,19 @@ const FOLLOW_ID_WIDTH = 14;
|
|
|
107
173
|
* with the column header the first time.
|
|
108
174
|
*
|
|
109
175
|
* @param requests - Newly finished requests
|
|
110
|
-
* @param options - `header` the first time; `verbose` for full URLs
|
|
176
|
+
* @param options - `header` the first time; `verbose` for full URLs; the page start for START
|
|
111
177
|
* @returns Text to print (empty when there is nothing new)
|
|
112
178
|
*/
|
|
113
179
|
export function formatNetworkFollowRows(requests, options = {}) {
|
|
114
180
|
const fmt = new OutputFormatter();
|
|
115
|
-
const
|
|
181
|
+
const widths = columnWidths(requests, FOLLOW_ID_WIDTH);
|
|
116
182
|
if (options.header) {
|
|
117
183
|
fmt.text('Streaming network requests... (Ctrl+C to stop)');
|
|
118
|
-
fmt.text(formatColumnHeader(
|
|
184
|
+
fmt.text(formatColumnHeader(widths));
|
|
119
185
|
fmt.separator('─', SEPARATOR_WIDTH);
|
|
120
186
|
}
|
|
121
187
|
for (const request of requests)
|
|
122
|
-
fmt.text(formatRequestLine(request, options
|
|
188
|
+
fmt.text(formatRequestLine(request, options, widths));
|
|
123
189
|
return fmt.build();
|
|
124
190
|
}
|
|
125
191
|
/**
|
|
@@ -98,7 +98,7 @@ export function appearanceLines(metadata, pageState) {
|
|
|
98
98
|
? [
|
|
99
99
|
[
|
|
100
100
|
'Viewport',
|
|
101
|
-
`${viewport.width}×${viewport.height}${metadata.viewport ? ` (
|
|
101
|
+
`${viewport.width}×${viewport.height}${metadata.viewport ? ` (emulated ${metadata.viewport.width}x${metadata.viewport.height})` : ''}`,
|
|
102
102
|
],
|
|
103
103
|
]
|
|
104
104
|
: []),
|
package/dist/ui/formatting.d.ts
CHANGED
|
@@ -72,6 +72,15 @@ export declare function truncateText(text: string, maxLines?: number): string;
|
|
|
72
72
|
* @returns Shortened URL; non-web URLs (data:, blob:) cut at the end
|
|
73
73
|
*/
|
|
74
74
|
export declare function truncateUrl(url: string, maxLength?: number): string;
|
|
75
|
+
/**
|
|
76
|
+
* Cut text in the middle, marking the cut with "…" (text that fits is
|
|
77
|
+
* returned as is).
|
|
78
|
+
*
|
|
79
|
+
* @param text - Text
|
|
80
|
+
* @param maxLength - Maximum length
|
|
81
|
+
* @returns Text, or its start and end around "…"
|
|
82
|
+
*/
|
|
83
|
+
export declare function cutMiddle(text: string, maxLength: number): string;
|
|
75
84
|
export declare function pluralize(count: number, singular: string, plural?: string): string;
|
|
76
85
|
export declare function formatDuration(ms: number): string;
|
|
77
86
|
//# sourceMappingURL=formatting.d.ts.map
|
package/dist/ui/formatting.js
CHANGED
|
@@ -167,13 +167,16 @@ export function truncateUrl(url, maxLength = 60) {
|
|
|
167
167
|
/** Characters of path and query a shortened URL keeps at least besides its host */
|
|
168
168
|
const MIN_URL_END_SHOWN = 12;
|
|
169
169
|
/**
|
|
170
|
-
* Cut text in the middle, marking the cut with "…"
|
|
170
|
+
* Cut text in the middle, marking the cut with "…" (text that fits is
|
|
171
|
+
* returned as is).
|
|
171
172
|
*
|
|
172
173
|
* @param text - Text
|
|
173
174
|
* @param maxLength - Maximum length
|
|
174
|
-
* @returns
|
|
175
|
+
* @returns Text, or its start and end around "…"
|
|
175
176
|
*/
|
|
176
|
-
function cutMiddle(text, maxLength) {
|
|
177
|
+
export function cutMiddle(text, maxLength) {
|
|
178
|
+
if (text.length <= maxLength)
|
|
179
|
+
return text;
|
|
177
180
|
const head = Math.ceil((maxLength - 1) / 2);
|
|
178
181
|
return `${text.substring(0, head)}…${text.substring(text.length - (maxLength - 1 - head))}`;
|
|
179
182
|
}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* cleaning up stale files, and validating command arguments.
|
|
6
6
|
*/
|
|
7
7
|
import type { DomFrame, PageLoadingState, PendingRequestInfo } from '../../ipc/protocol/commands.js';
|
|
8
|
-
import type { ElementLayout, FillValueMismatch, LayoutSize, NewMessage, PageLayout, PageNavigation } from '../../ipc/protocol/domTypes.js';
|
|
8
|
+
import type { ElementLayout, FillValueMismatch, LayoutSize, NewMessage, PageLayout, PageNavigation, PendingChanges, ShownElement } from '../../ipc/protocol/domTypes.js';
|
|
9
|
+
import type { InspectVisibility } from '../../ipc/protocol/inspectTypes.js';
|
|
9
10
|
import type { DelegationNote } from '../../runtime/dom/listenerSummary.js';
|
|
10
11
|
import type { WaitCondition, WaitSnapshot } from '../../runtime/dom/waitCondition.js';
|
|
11
12
|
import type { DocumentRequestState, ViewportPosition } from '../../types.js';
|
|
@@ -58,12 +59,33 @@ export declare const NO_VISIBLE_EFFECT = "no visible effect observed: no DOM cha
|
|
|
58
59
|
* Status line of a DOM action: a check mark only for a clean success.
|
|
59
60
|
*
|
|
60
61
|
* @param done - What was done, e.g. "Element Clicked"
|
|
61
|
-
* @param
|
|
62
|
-
*
|
|
63
|
-
* @returns e.g. "✓ Element Clicked", "⚠ Element Clicked (with warnings)"
|
|
62
|
+
* @param state - Whether the action has warnings (shown right below), had no
|
|
63
|
+
* visible effect, or returned while the page was still changing
|
|
64
|
+
* @returns e.g. "✓ Element Clicked", "⚠ Element Clicked (with warnings)",
|
|
65
|
+
* "⚠ Element Clicked (page still changing)" or
|
|
64
66
|
* "⚠ Element Clicked (no visible effect observed: no DOM change, requests or navigation within 300 ms)"
|
|
65
67
|
*/
|
|
66
|
-
export declare function actionStatusLine(done: string,
|
|
68
|
+
export declare function actionStatusLine(done: string, state: {
|
|
69
|
+
warned: boolean;
|
|
70
|
+
noEffect?: boolean;
|
|
71
|
+
stillChanging?: boolean;
|
|
72
|
+
}): string;
|
|
73
|
+
/**
|
|
74
|
+
* Note under the status line of an action that returned while the page was
|
|
75
|
+
* still changing.
|
|
76
|
+
*
|
|
77
|
+
* @param action - What returned, e.g. "click", "key press"
|
|
78
|
+
* @param pending - What the page was still working on
|
|
79
|
+
* @returns e.g. "The page was still changing when the click returned (2 requests pending); wait for the result with bdg dom wait <selector>"
|
|
80
|
+
*/
|
|
81
|
+
export declare function stillChangingNote(action: string, pending: PendingChanges): string;
|
|
82
|
+
/**
|
|
83
|
+
* An element an action showed, for its `Shown:` rows.
|
|
84
|
+
*
|
|
85
|
+
* @param element - Shown element
|
|
86
|
+
* @returns e.g. `div.figcaption "name: user2 View profile"`
|
|
87
|
+
*/
|
|
88
|
+
export declare function shownElementText(element: ShownElement): string;
|
|
67
89
|
/**
|
|
68
90
|
* How an action changed the page's location, for its `Page:` row.
|
|
69
91
|
*
|
|
@@ -191,7 +213,7 @@ export declare function layoutPositionLabel(element: LabelledLayout, viewport?:
|
|
|
191
213
|
* comes from.
|
|
192
214
|
*
|
|
193
215
|
* @param scheme - Light or dark
|
|
194
|
-
* @param emulated - Set with `--color-scheme` (otherwise the system setting)
|
|
216
|
+
* @param emulated - Set with `--color-scheme` or `page emulate` (otherwise the system setting)
|
|
195
217
|
* @returns e.g. `prefers-color-scheme: dark (from the system setting)`
|
|
196
218
|
*/
|
|
197
219
|
export declare function colorSchemeLabel(scheme: string, emulated: boolean): string;
|
|
@@ -229,6 +251,48 @@ export declare function layoutHeadline(count: number, listed: number, selector:
|
|
|
229
251
|
* @returns e.g. `Element at index 0 of the last dom query "h3" (page x,y and size in CSS px):`
|
|
230
252
|
*/
|
|
231
253
|
export declare function indexLayoutHeadline(target: string): string;
|
|
254
|
+
/** Help text explaining `bdg dom inspect`'s output notation */
|
|
255
|
+
export declare const INSPECT_OUTPUT_LEGEND = "\nOutput notation:\n WxH @x,y rendered border box size and page position (CSS px, no unit)\n m / p / b margin / padding / border widths, 1-4 values in CSS order (top right bottom left)\n in-parent distances to the parent's content edges (l t r b); sib: gaps to the sibling on each side\n scroll WxH the content (pseudo-elements too) is larger than the box\n 16/24 font size / line height; 'webfont loaded' = drawn with a downloaded font;\n (rendered \"X\") = drawn with another font than declared (a fallback)\n contrast 4.47 WCAG ratio, rounded down, against the background behind the text\n (+N not rendered) children with display: none (or not in the layout)\n hints declarations on this element that have no effect, why, the fix and where they are\n ('none': checked, nothing found)\n \u2190 sel (file:N) --rules: the declaration that sets the value (file:line, or file:line:column in\n minified files); 'over X': rules it beats; '= v': the value of a var() expression\n \u2713 / \u2717 --why: the winning declaration / ones it beats, highest precedence first;\n [0,2,0]: selector specificity (ids, classes, types); indented --name lines: where\n the winner's custom properties are set\nSessions follow the system color scheme; start with --color-scheme light|dark to choose.";
|
|
256
|
+
/**
|
|
257
|
+
* What covers an element: a cover that paints nothing at that point (a
|
|
258
|
+
* transparent box over it) does not hide it, but takes its clicks.
|
|
259
|
+
*
|
|
260
|
+
* @param cover - Description of the covering element
|
|
261
|
+
* @param transparent - The cover paints nothing there
|
|
262
|
+
* @returns e.g. `covered by div#modal`, `under transparent ul.filters (clicks land on it)`
|
|
263
|
+
*/
|
|
264
|
+
export declare function coverText(cover: string, transparent: boolean | undefined): string;
|
|
265
|
+
/**
|
|
266
|
+
* Note when `bdg dom inspect` could not read the element's matched rules, so
|
|
267
|
+
* no hints, rules or why were computed.
|
|
268
|
+
*
|
|
269
|
+
* @param reason - `timeout` (very large stylesheets) or `failed` (Chrome reported an error)
|
|
270
|
+
* @returns Note
|
|
271
|
+
*/
|
|
272
|
+
export declare function inspectCascadeNote(reason: 'timeout' | 'failed'): string;
|
|
273
|
+
/**
|
|
274
|
+
* Header badge of `bdg dom inspect` when the page is shown in its dark theme
|
|
275
|
+
* because the session follows the system's dark preference: the colors are
|
|
276
|
+
* the dark theme's, not what a light-mode visitor sees.
|
|
277
|
+
*
|
|
278
|
+
* @returns Badge
|
|
279
|
+
*/
|
|
280
|
+
export declare function inspectDarkThemeBadge(): string;
|
|
281
|
+
/**
|
|
282
|
+
* Header badges of `bdg dom inspect` for what keeps an element from being seen.
|
|
283
|
+
*
|
|
284
|
+
* @param visibility - Not rendered, hidden, offscreen, covered
|
|
285
|
+
* @returns e.g. `[not rendered: display: none]`, `[offscreen: below]`, `[covered by div#modal]`
|
|
286
|
+
*/
|
|
287
|
+
export declare function inspectVisibilityBadges(visibility: InspectVisibility): string[];
|
|
288
|
+
/**
|
|
289
|
+
* What `bdg dom inspect` did when several elements matched and no --index was given.
|
|
290
|
+
*
|
|
291
|
+
* @param picked - How the match was chosen
|
|
292
|
+
* @param index - Index of the inspected match
|
|
293
|
+
* @returns e.g. "inspected the first visible one ([2])"
|
|
294
|
+
*/
|
|
295
|
+
export declare function inspectedMatchAction(picked: 'first-visible' | 'first', index: number): string;
|
|
232
296
|
/**
|
|
233
297
|
* Warning when a selector matched several elements and no --index was given.
|
|
234
298
|
*
|
|
@@ -327,6 +391,13 @@ export declare const POINTER_ACTION_DONE: {
|
|
|
327
391
|
readonly right: "Right-clicked";
|
|
328
392
|
readonly hover: "Hovered";
|
|
329
393
|
};
|
|
394
|
+
/** What each pointer action is called in notes ("when the click returned") */
|
|
395
|
+
export declare const POINTER_ACTION_NOUN: {
|
|
396
|
+
readonly click: "click";
|
|
397
|
+
readonly double: "double-click";
|
|
398
|
+
readonly right: "right-click";
|
|
399
|
+
readonly hover: "hover";
|
|
400
|
+
};
|
|
330
401
|
/** Headline of each `bdg page` action */
|
|
331
402
|
export declare const PAGE_ACTION_DONE: {
|
|
332
403
|
readonly navigate: "Navigated";
|
|
@@ -334,9 +405,11 @@ export declare const PAGE_ACTION_DONE: {
|
|
|
334
405
|
readonly back: "Went back";
|
|
335
406
|
readonly forward: "Went forward";
|
|
336
407
|
};
|
|
337
|
-
/** Help text of the `bdg page` history commands */
|
|
338
408
|
/** Description of `bdg page info` */
|
|
339
409
|
export declare const PAGE_INFO_DESCRIPTION = "Show the URL and title of the session page";
|
|
410
|
+
/** Description of `bdg page emulate` */
|
|
411
|
+
export declare const PAGE_EMULATE_DESCRIPTION = "Change the viewport or color scheme mid-session (like --viewport and --color-scheme at start), or --reset both";
|
|
412
|
+
/** Help text of the `bdg page` history commands */
|
|
340
413
|
export declare const PAGE_ACTION_DESCRIPTIONS: {
|
|
341
414
|
readonly reload: "Reload the page";
|
|
342
415
|
readonly back: "Go back one page (like the browser button)";
|
|
@@ -562,5 +635,48 @@ export declare function sessionStillActiveSuggestion(session: string | null): st
|
|
|
562
635
|
* @returns Multi-line help message with examples
|
|
563
636
|
* */
|
|
564
637
|
export declare function startCommandHelpMessage(): string;
|
|
638
|
+
/**
|
|
639
|
+
* `bdg page emulate` without anything to change.
|
|
640
|
+
*
|
|
641
|
+
* @returns Message and suggestion
|
|
642
|
+
*/
|
|
643
|
+
export declare function pageEmulateNothingError(): {
|
|
644
|
+
message: string;
|
|
645
|
+
suggestion: string;
|
|
646
|
+
};
|
|
647
|
+
/**
|
|
648
|
+
* Lines of `bdg page emulate`: what is emulated and what the page now has.
|
|
649
|
+
*
|
|
650
|
+
* @param result - Emulation and page appearance
|
|
651
|
+
* @returns Label/value pairs
|
|
652
|
+
*/
|
|
653
|
+
export declare function pageEmulationLines(result: {
|
|
654
|
+
emulated: {
|
|
655
|
+
viewport?: {
|
|
656
|
+
width: number;
|
|
657
|
+
height: number;
|
|
658
|
+
};
|
|
659
|
+
colorScheme?: string;
|
|
660
|
+
};
|
|
661
|
+
viewport?: {
|
|
662
|
+
width: number;
|
|
663
|
+
height: number;
|
|
664
|
+
};
|
|
665
|
+
colorScheme?: string;
|
|
666
|
+
}): Array<[string, string]>;
|
|
667
|
+
/**
|
|
668
|
+
* Header badge of `bdg dom inspect` while CSS transitions or animations run
|
|
669
|
+
* on the element: the values read are mid-way.
|
|
670
|
+
*
|
|
671
|
+
* @param animating - Transitioned properties and animation names
|
|
672
|
+
* @returns e.g. `[animating: background-color; values are mid-way, inspect again]`
|
|
673
|
+
*/
|
|
674
|
+
export declare function inspectAnimatingBadge(animating: readonly string[]): string;
|
|
675
|
+
/**
|
|
676
|
+
* `--why` note on a computed value read during its transition.
|
|
677
|
+
*
|
|
678
|
+
* @returns Note
|
|
679
|
+
*/
|
|
680
|
+
export declare function inspectMidTransitionNote(): string;
|
|
565
681
|
export {};
|
|
566
682
|
//# sourceMappingURL=commands.d.ts.map
|