browser-debugger-cli 0.11.0 → 0.13.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 +4 -4
- package/README.md +143 -79
- 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 +62 -12
- package/dist/commands/css.d.ts +13 -0
- package/dist/commands/css.js +53 -0
- package/dist/commands/dom/DomElementResolver.d.ts +3 -1
- package/dist/commands/dom/DomElementResolver.js +10 -3
- package/dist/commands/dom/a11y.js +3 -2
- package/dist/commands/dom/audit.d.ts +14 -0
- package/dist/commands/dom/audit.js +87 -0
- package/dist/commands/dom/eval.d.ts +3 -2
- package/dist/commands/dom/eval.js +11 -5
- package/dist/commands/dom/form.js +10 -9
- package/dist/commands/dom/formInteraction.js +42 -11
- package/dist/commands/dom/get.js +8 -8
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/keyAttributes.d.ts +3 -2
- package/dist/commands/dom/helpers/keyAttributes.js +6 -4
- 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.d.ts +1 -0
- package/dist/commands/dom/helpers/screenshot.js +169 -49
- package/dist/commands/dom/index.js +7 -2
- package/dist/commands/dom/query.d.ts +19 -2
- package/dist/commands/dom/query.js +37 -6
- package/dist/commands/dom/screenshot.js +12 -7
- package/dist/commands/dom/semanticUtils.d.ts +3 -2
- package/dist/commands/dom/semanticUtils.js +40 -9
- package/dist/commands/dom/wait.js +5 -3
- 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 +22 -12
- package/dist/commands/optionBehaviors.js +53 -16
- package/dist/commands/page.js +7 -4
- package/dist/commands/peek.d.ts +7 -0
- package/dist/commands/peek.js +65 -23
- package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
- package/dist/commands/shared/daemonErrorHandler.js +20 -9
- package/dist/commands/shared/dataFetcher.d.ts +12 -4
- package/dist/commands/shared/dataFetcher.js +12 -4
- package/dist/commands/shared/followMode.d.ts +9 -1
- package/dist/commands/shared/followMode.js +22 -4
- package/dist/commands/shared/optionTypes.d.ts +9 -2
- package/dist/commands/shared/outputFile.js +6 -1
- package/dist/commands/start.d.ts +20 -5
- package/dist/commands/start.js +84 -23
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.js +24 -1
- package/dist/commands/tail.d.ts +7 -1
- package/dist/commands/tail.js +13 -62
- package/dist/commands.js +2 -0
- package/dist/connection/cdp.d.ts +7 -0
- package/dist/connection/cdp.js +9 -0
- package/dist/connection/launcher.js +3 -2
- package/dist/daemon/SessionController.js +6 -1
- package/dist/daemon/launcher.d.ts +3 -2
- package/dist/daemon/launcher.js +47 -3
- package/dist/daemon/session/Session.d.ts +4 -1
- package/dist/daemon/session/Session.js +33 -2
- package/dist/daemon/session/TelemetryStore.d.ts +8 -1
- package/dist/daemon/session/TelemetryStore.js +13 -1
- package/dist/daemon/session/commandRegistry.js +36 -14
- package/dist/daemon/session/interactions.d.ts +2 -1
- package/dist/daemon/session/interactions.js +13 -1
- package/dist/daemon/session/plugins.js +19 -53
- package/dist/daemon/session/teardown.js +1 -1
- package/dist/daemon.js +9234 -7222
- package/dist/errors/messages.d.ts +88 -15
- package/dist/errors/messages.js +177 -27
- package/dist/index.js +19322 -13961
- package/dist/ipc/client.d.ts +22 -2
- package/dist/ipc/client.js +34 -5
- package/dist/ipc/protocol/auditTypes.d.ts +135 -0
- package/dist/ipc/protocol/auditTypes.js +6 -0
- package/dist/ipc/protocol/commands.d.ts +35 -0
- package/dist/ipc/protocol/commands.js +2 -0
- package/dist/ipc/protocol/domTypes.d.ts +16 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +73 -8
- package/dist/ipc/session/types.d.ts +2 -0
- package/dist/runtime/css/search.d.ts +39 -0
- package/dist/runtime/css/search.js +122 -0
- package/dist/runtime/dom/actionEffects.d.ts +9 -2
- package/dist/runtime/dom/actionEffects.js +30 -14
- package/dist/runtime/dom/audit.d.ts +19 -0
- package/dist/runtime/dom/audit.js +37 -0
- package/dist/runtime/dom/auditModel.d.ts +45 -0
- package/dist/runtime/dom/auditModel.js +220 -0
- package/dist/runtime/dom/auditScripts.d.ts +113 -0
- package/dist/runtime/dom/auditScripts.js +148 -0
- package/dist/runtime/dom/elementGeometry.d.ts +16 -3
- package/dist/runtime/dom/elementGeometry.js +49 -10
- package/dist/runtime/dom/elementInfo.d.ts +74 -17
- package/dist/runtime/dom/elementInfo.js +187 -34
- 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 +8 -12
- 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/inspect.d.ts +7 -0
- package/dist/runtime/dom/inspect.js +92 -28
- package/dist/runtime/dom/inspectAllStyles.d.ts +16 -4
- package/dist/runtime/dom/inspectAllStyles.js +90 -7
- package/dist/runtime/dom/inspectCascade.d.ts +19 -2
- package/dist/runtime/dom/inspectCascade.js +214 -44
- package/dist/runtime/dom/inspectCascadeModel.d.ts +8 -0
- package/dist/runtime/dom/inspectCascadeModel.js +108 -34
- package/dist/runtime/dom/inspectHints.d.ts +26 -3
- package/dist/runtime/dom/inspectHints.js +125 -9
- package/dist/runtime/dom/inspectModel.d.ts +5 -1
- package/dist/runtime/dom/inspectModel.js +37 -10
- package/dist/runtime/dom/inspectPaintModel.d.ts +50 -22
- package/dist/runtime/dom/inspectPaintModel.js +182 -68
- package/dist/runtime/dom/inspectRules.d.ts +19 -0
- package/dist/runtime/dom/inspectRules.js +21 -5
- package/dist/runtime/dom/inspectScripts.d.ts +112 -12
- package/dist/runtime/dom/inspectScripts.js +357 -32
- package/dist/runtime/dom/inspectTree.js +10 -2
- package/dist/runtime/dom/inspectWhyModel.d.ts +2 -1
- package/dist/runtime/dom/inspectWhyModel.js +52 -10
- package/dist/runtime/dom/layout.js +40 -16
- package/dist/runtime/dom/reactEventHelpers.d.ts +21 -4
- package/dist/runtime/dom/reactEventHelpers.js +90 -36
- package/dist/runtime/dom/targetNode.d.ts +18 -5
- package/dist/runtime/dom/targetNode.js +268 -8
- 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/emulation.d.ts +13 -4
- package/dist/runtime/page/emulation.js +69 -4
- package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
- package/dist/runtime/page/replacedBuiltins.js +136 -0
- package/dist/runtime/page/userAgent.d.ts +17 -0
- package/dist/runtime/page/userAgent.js +57 -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.js +2 -2
- package/dist/telemetry/console.d.ts +2 -1
- package/dist/telemetry/console.js +30 -21
- package/dist/telemetry/pageCrash.d.ts +26 -0
- package/dist/telemetry/pageCrash.js +53 -0
- package/dist/types.d.ts +20 -0
- package/dist/ui/formatters/audit.d.ts +19 -0
- package/dist/ui/formatters/audit.js +115 -0
- package/dist/ui/formatters/cdp.d.ts +138 -0
- package/dist/ui/formatters/cdp.js +131 -0
- package/dist/ui/formatters/console/chronological.js +3 -1
- package/dist/ui/formatters/console/follow.d.ts +2 -1
- package/dist/ui/formatters/console/follow.js +2 -2
- package/dist/ui/formatters/console/json.d.ts +2 -2
- package/dist/ui/formatters/console/json.js +11 -5
- package/dist/ui/formatters/console/shared.d.ts +30 -0
- package/dist/ui/formatters/console/shared.js +16 -0
- package/dist/ui/formatters/console/summarize.d.ts +9 -2
- package/dist/ui/formatters/console/summarize.js +40 -9
- package/dist/ui/formatters/console.d.ts +2 -1
- package/dist/ui/formatters/console.js +7 -5
- package/dist/ui/formatters/details.js +3 -1
- package/dist/ui/formatters/dom.d.ts +2 -2
- package/dist/ui/formatters/dom.js +10 -8
- package/dist/ui/formatters/helpFormatters.js +1 -1
- package/dist/ui/formatters/inspect.js +50 -17
- package/dist/ui/formatters/installSkill.d.ts +9 -1
- package/dist/ui/formatters/installSkill.js +32 -6
- package/dist/ui/formatters/layout.js +2 -1
- package/dist/ui/formatters/networkList.d.ts +1 -1
- package/dist/ui/formatters/networkList.js +1 -2
- package/dist/ui/formatters/preview.d.ts +2 -0
- package/dist/ui/formatters/preview.js +17 -7
- package/dist/ui/formatters/sessions.d.ts +2 -2
- package/dist/ui/formatters/sessions.js +9 -2
- package/dist/ui/formatters/status.js +1 -1
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/commands.d.ts +168 -11
- package/dist/ui/messages/commands.js +245 -18
- package/dist/ui/messages/consoleMessages.d.ts +24 -0
- package/dist/ui/messages/consoleMessages.js +32 -0
- package/dist/ui/messages/preview.d.ts +12 -0
- package/dist/ui/messages/preview.js +18 -2
- package/dist/ui/messages/session.d.ts +13 -2
- package/dist/ui/messages/session.js +22 -3
- package/dist/utils/cssValues.js +36 -4
- package/dist/utils/decisionTrees.js +0 -5
- 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/process.d.ts +12 -0
- package/dist/utils/process.js +25 -0
- package/dist/utils/suggestions.d.ts +4 -2
- package/dist/utils/suggestions.js +7 -5
- package/dist/utils/taskMappings.js +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bdg css search <text>`: find text in the page's stylesheets, cross-origin
|
|
3
|
+
* ones included (CDP reads every stylesheet's text), and show the rule
|
|
4
|
+
* around each match with its `file:line`.
|
|
5
|
+
*/
|
|
6
|
+
import { enableStyleDomains } from '../dom/inspect.js';
|
|
7
|
+
import { stylesheetPositionLabel, styleSheetHeaders } from '../dom/inspectRules.js';
|
|
8
|
+
import { createLogger } from '../../ui/logging/index.js';
|
|
9
|
+
import { getErrorMessage } from '../../utils/errors.js';
|
|
10
|
+
const log = createLogger('dom');
|
|
11
|
+
/** Matches listed without `--limit` */
|
|
12
|
+
export const DEFAULT_CSS_SEARCH_LIMIT = 20;
|
|
13
|
+
/** Characters of a rule shown around a match */
|
|
14
|
+
const RULE_CONTEXT = 240;
|
|
15
|
+
/**
|
|
16
|
+
* Search the stylesheets for a text (case-insensitive).
|
|
17
|
+
*
|
|
18
|
+
* @param cdp - CDP connection
|
|
19
|
+
* @param params - Text and limit
|
|
20
|
+
* @returns Matches with their place
|
|
21
|
+
*/
|
|
22
|
+
export async function searchStyleSheets(cdp, params) {
|
|
23
|
+
await enableStyleDomains(cdp);
|
|
24
|
+
const headers = [...styleSheetHeaders(cdp)].filter((header) => header.origin !== 'user-agent');
|
|
25
|
+
const limit = params.limit ?? DEFAULT_CSS_SEARCH_LIMIT;
|
|
26
|
+
const texts = await Promise.all(headers.map((header) => sheetText(cdp, header.styleSheetId)));
|
|
27
|
+
const matches = [];
|
|
28
|
+
let total = 0;
|
|
29
|
+
headers.forEach((header, i) => {
|
|
30
|
+
const found = findInSheet(texts[i] ?? '', params.query, Number.POSITIVE_INFINITY);
|
|
31
|
+
const seen = new Set();
|
|
32
|
+
for (const match of found.matches) {
|
|
33
|
+
if (seen.has(match.rule))
|
|
34
|
+
continue;
|
|
35
|
+
seen.add(match.rule);
|
|
36
|
+
total++;
|
|
37
|
+
if (matches.length >= limit)
|
|
38
|
+
continue;
|
|
39
|
+
matches.push({
|
|
40
|
+
source: stylesheetPositionLabel(header, match.line, match.column),
|
|
41
|
+
text: match.rule,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
return { query: params.query, sheets: headers.length, total, matches };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A stylesheet's text; empty when Chrome cannot give it.
|
|
49
|
+
*
|
|
50
|
+
* @param cdp - CDP connection
|
|
51
|
+
* @param styleSheetId - Stylesheet
|
|
52
|
+
* @returns Text
|
|
53
|
+
*/
|
|
54
|
+
async function sheetText(cdp, styleSheetId) {
|
|
55
|
+
try {
|
|
56
|
+
const response = (await cdp.send('CSS.getStyleSheetText', {
|
|
57
|
+
styleSheetId,
|
|
58
|
+
}));
|
|
59
|
+
return response.text;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
log.debug(`No text for stylesheet ${styleSheetId}: ${getErrorMessage(error)}`);
|
|
63
|
+
return '';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Where a text occurs in a stylesheet (case-insensitive): how many times,
|
|
68
|
+
* and for the first `limit` matches the 0-based line and column and the
|
|
69
|
+
* rule around it (from the end of the previous rule to the end of this one,
|
|
70
|
+
* whitespace collapsed, at most {@link RULE_CONTEXT} characters each side).
|
|
71
|
+
* Lines are counted as the search moves on, so a big sheet is read once.
|
|
72
|
+
*
|
|
73
|
+
* @param text - Stylesheet text
|
|
74
|
+
* @param query - Text to find
|
|
75
|
+
* @param limit - Matches described at most
|
|
76
|
+
* @returns Match count and the described matches
|
|
77
|
+
*/
|
|
78
|
+
export function findInSheet(text, query, limit = Number.POSITIVE_INFINITY) {
|
|
79
|
+
const matches = [];
|
|
80
|
+
const haystack = text.toLowerCase();
|
|
81
|
+
const needle = query.toLowerCase();
|
|
82
|
+
if (needle === '')
|
|
83
|
+
return { total: 0, matches };
|
|
84
|
+
let total = 0;
|
|
85
|
+
let line = 0;
|
|
86
|
+
let lineStart = 0;
|
|
87
|
+
let scanned = 0;
|
|
88
|
+
for (let at = haystack.indexOf(needle); at >= 0; at = haystack.indexOf(needle, at + needle.length)) {
|
|
89
|
+
total++;
|
|
90
|
+
if (matches.length >= limit)
|
|
91
|
+
continue;
|
|
92
|
+
for (let i = text.indexOf('\n', scanned); i >= 0 && i < at; i = text.indexOf('\n', i + 1)) {
|
|
93
|
+
line++;
|
|
94
|
+
lineStart = i + 1;
|
|
95
|
+
}
|
|
96
|
+
scanned = at;
|
|
97
|
+
matches.push({ line, column: at - lineStart, rule: ruleAround(text, at) });
|
|
98
|
+
}
|
|
99
|
+
return { total, matches };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The rule around a position: whole when short, else its selector and the
|
|
103
|
+
* declarations near the position (`.btn { … color: var(--brand); … }`),
|
|
104
|
+
* whitespace collapsed.
|
|
105
|
+
*
|
|
106
|
+
* @param text - Stylesheet text
|
|
107
|
+
* @param at - Position of the match
|
|
108
|
+
* @returns Rule text
|
|
109
|
+
*/
|
|
110
|
+
function ruleAround(text, at) {
|
|
111
|
+
const ruleStart = text.lastIndexOf('}', at) + 1;
|
|
112
|
+
const open = text.indexOf('{', ruleStart);
|
|
113
|
+
const close = text.indexOf('}', at);
|
|
114
|
+
const ruleEnd = close < 0 ? text.length : close + 1;
|
|
115
|
+
const collapse = (part) => part.replace(/\s+/g, ' ').trim();
|
|
116
|
+
if (ruleEnd - ruleStart <= 2 * RULE_CONTEXT || open < 0 || open > at) {
|
|
117
|
+
return collapse(text.slice(Math.max(ruleStart, at - RULE_CONTEXT), Math.min(ruleEnd, at + RULE_CONTEXT)));
|
|
118
|
+
}
|
|
119
|
+
const near = collapse(text.slice(Math.max(open + 1, at - RULE_CONTEXT / 2), Math.min(ruleEnd - 1, at + RULE_CONTEXT / 2)));
|
|
120
|
+
return `${collapse(text.slice(ruleStart, open))} { … ${near} … }`;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -65,6 +65,8 @@ export interface OtherActivity {
|
|
|
65
65
|
dialogs: number;
|
|
66
66
|
/** A window, tab or download was opened */
|
|
67
67
|
opened: boolean;
|
|
68
|
+
/** Console messages logged during the action */
|
|
69
|
+
consoleMessages: number;
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
72
|
* Messages that are new after the action: all of them after a new document
|
|
@@ -81,7 +83,10 @@ export interface OtherActivity {
|
|
|
81
83
|
* @param newDocument - Whether a new document loaded
|
|
82
84
|
* @returns New messages
|
|
83
85
|
*/
|
|
84
|
-
export declare function newMessages(before: SeenMessage[], after: SeenMessage[], newDocument: boolean):
|
|
86
|
+
export declare function newMessages(before: SeenMessage[], after: SeenMessage[], newDocument: boolean): {
|
|
87
|
+
messages: NewMessage[];
|
|
88
|
+
more: number;
|
|
89
|
+
};
|
|
85
90
|
/**
|
|
86
91
|
* Elements to report as shown: those whose text is not already reported as
|
|
87
92
|
* a new message, at most {@link MAX_SHOWN_ELEMENTS}, texts cut to
|
|
@@ -144,7 +149,7 @@ export declare function pageNavigation(startHref: string | undefined, read: Read
|
|
|
144
149
|
* Whether an action had no visible effect: the page was read before and
|
|
145
150
|
* after in the same document, it counted no DOM change, nothing made the
|
|
146
151
|
* check uncertain, and no navigation, message, shown element, request,
|
|
147
|
-
* dialog
|
|
152
|
+
* dialog, new window or console message happened.
|
|
148
153
|
*
|
|
149
154
|
* @param read - Page read after the action
|
|
150
155
|
* @param effects - Navigation and messages found
|
|
@@ -156,6 +161,8 @@ export declare function hadNoEffect(read: ReadSnapshot | undefined, effects: Act
|
|
|
156
161
|
export interface CollectOptions {
|
|
157
162
|
/** Dialogs the action opened */
|
|
158
163
|
dialogs: number;
|
|
164
|
+
/** Console messages logged since the action started, so far */
|
|
165
|
+
consoleMessages: () => number;
|
|
159
166
|
/** Decide "no effect" (with a second look when nothing seemed to happen) */
|
|
160
167
|
detectNoEffect: boolean;
|
|
161
168
|
/** List the elements the action showed */
|
|
@@ -81,8 +81,6 @@ export function newMessages(before, after, newDocument) {
|
|
|
81
81
|
const reported = new Set();
|
|
82
82
|
const result = [];
|
|
83
83
|
for (const message of after) {
|
|
84
|
-
if (result.length >= MAX_NEW_MESSAGES)
|
|
85
|
-
break;
|
|
86
84
|
if (reported.has(message.text) || TICKING_TEXT.test(message.text))
|
|
87
85
|
continue;
|
|
88
86
|
if (!isNew(message))
|
|
@@ -90,7 +88,10 @@ export function newMessages(before, after, newDocument) {
|
|
|
90
88
|
reported.add(message.text);
|
|
91
89
|
result.push({ text: cutText(message.text), element: message.element });
|
|
92
90
|
}
|
|
93
|
-
return
|
|
91
|
+
return {
|
|
92
|
+
messages: result.slice(0, MAX_NEW_MESSAGES),
|
|
93
|
+
more: Math.max(0, result.length - MAX_NEW_MESSAGES),
|
|
94
|
+
};
|
|
94
95
|
}
|
|
95
96
|
/**
|
|
96
97
|
* Cut a text to {@link MAX_MESSAGE_LENGTH} characters, marking the cut.
|
|
@@ -207,7 +208,7 @@ export function pageNavigation(startHref, read, events) {
|
|
|
207
208
|
* Whether an action had no visible effect: the page was read before and
|
|
208
209
|
* after in the same document, it counted no DOM change, nothing made the
|
|
209
210
|
* check uncertain, and no navigation, message, shown element, request,
|
|
210
|
-
* dialog
|
|
211
|
+
* dialog, new window or console message happened.
|
|
211
212
|
*
|
|
212
213
|
* @param read - Page read after the action
|
|
213
214
|
* @param effects - Navigation and messages found
|
|
@@ -224,7 +225,8 @@ export function hadNoEffect(read, effects, activity) {
|
|
|
224
225
|
(effects.shown ?? []).length === 0 &&
|
|
225
226
|
activity.requests === 0 &&
|
|
226
227
|
activity.dialogs === 0 &&
|
|
227
|
-
!activity.opened
|
|
228
|
+
!activity.opened &&
|
|
229
|
+
activity.consoleMessages === 0);
|
|
228
230
|
}
|
|
229
231
|
/**
|
|
230
232
|
* Start watching an action's effects: listen for main-frame navigations,
|
|
@@ -264,7 +266,11 @@ async function collectEffects(watch, options) {
|
|
|
264
266
|
const reportShown = options.reportShown === true;
|
|
265
267
|
let snapshot = await readPage(watch, { stop: false, reportShown });
|
|
266
268
|
let effects = effectsOf(start, snapshot, watch.listener.events);
|
|
267
|
-
const quiet = () => hadNoEffect(snapshot, effects, {
|
|
269
|
+
const quiet = () => hadNoEffect(snapshot, effects, {
|
|
270
|
+
...watch.listener.activity(),
|
|
271
|
+
dialogs: options.dialogs,
|
|
272
|
+
consoleMessages: options.consoleMessages(),
|
|
273
|
+
});
|
|
268
274
|
if (options.detectNoEffect && quiet()) {
|
|
269
275
|
await delay(NO_EFFECT_RECHECK_MS);
|
|
270
276
|
snapshot = await readPage(watch, { stop: true, reportShown });
|
|
@@ -324,7 +330,8 @@ function pageWork(watch, snapshot, domChanging = false) {
|
|
|
324
330
|
}
|
|
325
331
|
/**
|
|
326
332
|
* Navigation, new messages and shown elements from the snapshots and CDP
|
|
327
|
-
* events.
|
|
333
|
+
* events. Snapshots a page broke (it replaced the built-ins the snapshot
|
|
334
|
+
* script uses) give the navigation only.
|
|
328
335
|
*
|
|
329
336
|
* @param start - Snapshot before the action, if taken
|
|
330
337
|
* @param snapshot - Read after the action, if taken
|
|
@@ -333,13 +340,22 @@ function pageWork(watch, snapshot, domChanging = false) {
|
|
|
333
340
|
*/
|
|
334
341
|
function effectsOf(start, snapshot, events) {
|
|
335
342
|
const navigation = pageNavigation(start?.href, snapshot, events);
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
+
try {
|
|
344
|
+
const { messages, more } = start && snapshot
|
|
345
|
+
? newMessages(start.messages, snapshot.messages, snapshot.fresh)
|
|
346
|
+
: { messages: [], more: 0 };
|
|
347
|
+
const shown = shownElements(snapshot?.shown ?? [], messages);
|
|
348
|
+
return {
|
|
349
|
+
...(navigation && { navigation }),
|
|
350
|
+
...(messages.length > 0 && { messages }),
|
|
351
|
+
...(more > 0 && { moreMessages: more }),
|
|
352
|
+
...(shown.length > 0 && { shown }),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
catch (error) {
|
|
356
|
+
log.debug(`Page effects not readable (the page replaced built-ins?): ${getErrorMessage(error)}`);
|
|
357
|
+
return { ...(navigation && { navigation }) };
|
|
358
|
+
}
|
|
343
359
|
}
|
|
344
360
|
/**
|
|
345
361
|
* Read the page after the action, unless a main-frame load is pending (the
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bdg dom audit`: page-wide checks in one page walk
|
|
3
|
+
* ({@link AUDIT_PAGE_JS}), turned into findings by {@link buildAudit}.
|
|
4
|
+
*/
|
|
5
|
+
import type { CDPConnection } from '../../connection/cdp.js';
|
|
6
|
+
import type { AuditResult } from '../../ipc/protocol/auditTypes.js';
|
|
7
|
+
import type { DomAuditCommand } from '../../ipc/protocol/commands.js';
|
|
8
|
+
/** Findings listed per check without `--limit` */
|
|
9
|
+
export declare const DEFAULT_AUDIT_LIMIT = 20;
|
|
10
|
+
/**
|
|
11
|
+
* Run the page-wide checks.
|
|
12
|
+
*
|
|
13
|
+
* @param cdp - CDP connection
|
|
14
|
+
* @param params - Checks, WCAG level and limit
|
|
15
|
+
* @returns Findings
|
|
16
|
+
* @throws CommandError (91) when the page script fails
|
|
17
|
+
*/
|
|
18
|
+
export declare function auditPage(cdp: CDPConnection, params: DomAuditCommand): Promise<AuditResult>;
|
|
19
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bdg dom audit`: page-wide checks in one page walk
|
|
3
|
+
* ({@link AUDIT_PAGE_JS}), turned into findings by {@link buildAudit}.
|
|
4
|
+
*/
|
|
5
|
+
import { CommandError } from '../../errors/index.js';
|
|
6
|
+
import { operationFailedError } from '../../errors/messages.js';
|
|
7
|
+
import { buildAudit } from './auditModel.js';
|
|
8
|
+
import { AUDIT_PAGE_JS } from './auditScripts.js';
|
|
9
|
+
import { evaluateInBdgWorld } from '../page/bdgWorld.js';
|
|
10
|
+
import { EXIT_CODES } from '../../utils/exitCodes.js';
|
|
11
|
+
/** Findings listed per check without `--limit` */
|
|
12
|
+
export const DEFAULT_AUDIT_LIMIT = 20;
|
|
13
|
+
/**
|
|
14
|
+
* Run the page-wide checks.
|
|
15
|
+
*
|
|
16
|
+
* @param cdp - CDP connection
|
|
17
|
+
* @param params - Checks, WCAG level and limit
|
|
18
|
+
* @returns Findings
|
|
19
|
+
* @throws CommandError (91) when the page script fails
|
|
20
|
+
*/
|
|
21
|
+
export async function auditPage(cdp, params) {
|
|
22
|
+
const response = await evaluateInBdgWorld(cdp, {
|
|
23
|
+
expression: `(${AUDIT_PAGE_JS})(${JSON.stringify(params.checks)})`,
|
|
24
|
+
returnByValue: true,
|
|
25
|
+
});
|
|
26
|
+
const raw = response.result.value;
|
|
27
|
+
if (response.exceptionDetails || !raw) {
|
|
28
|
+
const err = operationFailedError('audit the page', response.exceptionDetails?.exception?.description ?? 'the page script failed');
|
|
29
|
+
throw new CommandError(err.message, { suggestion: err.suggestion }, EXIT_CODES.SCRIPT_ERROR);
|
|
30
|
+
}
|
|
31
|
+
return buildAudit(raw, {
|
|
32
|
+
checks: params.checks,
|
|
33
|
+
level: params.level ?? 'AA',
|
|
34
|
+
limit: params.limit ?? DEFAULT_AUDIT_LIMIT,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bdg dom audit` results from the page-side walk ({@link AUDIT_PAGE_JS}):
|
|
3
|
+
* text below a WCAG contrast level (composited like `dom inspect`), what
|
|
4
|
+
* makes the page scroll sideways, cut-off text, scaled or distorted images,
|
|
5
|
+
* fixed and sticky layers and running animations. Pure: tested without a
|
|
6
|
+
* browser.
|
|
7
|
+
*/
|
|
8
|
+
import type { AuditContrastItem, AuditImage, AuditResult, AuditCheck } from '../../ipc/protocol/auditTypes.js';
|
|
9
|
+
import type { RawAudit, RawImage } from './auditScripts.js';
|
|
10
|
+
/** What `dom audit` was asked for */
|
|
11
|
+
export interface AuditOptions {
|
|
12
|
+
checks: AuditCheck[];
|
|
13
|
+
/** WCAG level text must reach */
|
|
14
|
+
level: 'AA' | 'AAA';
|
|
15
|
+
/** Findings listed per check */
|
|
16
|
+
limit: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The audit result.
|
|
20
|
+
*
|
|
21
|
+
* @param raw - Page-side walk
|
|
22
|
+
* @param options - Checks, level and limit
|
|
23
|
+
* @returns Result
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildAudit(raw: RawAudit, options: AuditOptions): AuditResult;
|
|
26
|
+
/**
|
|
27
|
+
* The ratio WCAG asks of a text at a level: large text (24px, or 18.66px
|
|
28
|
+
* bold) needs less.
|
|
29
|
+
*
|
|
30
|
+
* @param item - Text size and weight
|
|
31
|
+
* @param level - AA or AAA
|
|
32
|
+
* @returns Minimum ratio
|
|
33
|
+
*/
|
|
34
|
+
export declare function requiredRatio(item: Pick<AuditContrastItem, 'size' | 'weight'>, level: 'AA' | 'AAA'): number;
|
|
35
|
+
/**
|
|
36
|
+
* An image drawn with fewer pixels than the screen needs (upscaled, blurry:
|
|
37
|
+
* rendered size × pixel ratio over its own pixels) or with another aspect
|
|
38
|
+
* ratio (distorted, unless `object-fit` keeps the ratio).
|
|
39
|
+
*
|
|
40
|
+
* @param image - Page-side image
|
|
41
|
+
* @param pixelRatio - Device pixel ratio
|
|
42
|
+
* @returns Finding, or undefined when it is sharp and keeps its ratio
|
|
43
|
+
*/
|
|
44
|
+
export declare function imageFinding(image: RawImage, pixelRatio?: number): AuditImage | undefined;
|
|
45
|
+
//# sourceMappingURL=auditModel.d.ts.map
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `bdg dom audit` results from the page-side walk ({@link AUDIT_PAGE_JS}):
|
|
3
|
+
* text below a WCAG contrast level (composited like `dom inspect`), what
|
|
4
|
+
* makes the page scroll sideways, cut-off text, scaled or distorted images,
|
|
5
|
+
* fixed and sticky layers and running animations. Pure: tested without a
|
|
6
|
+
* browser.
|
|
7
|
+
*/
|
|
8
|
+
import { textContrast } from './inspectPaintModel.js';
|
|
9
|
+
import { hexColor } from '../../utils/color.js';
|
|
10
|
+
import { pxNumber, round1 } from '../../utils/cssValues.js';
|
|
11
|
+
/** Scale or aspect change (fraction) below which an image counts as drawn at its size */
|
|
12
|
+
const IMAGE_TOLERANCE = 0.05;
|
|
13
|
+
/**
|
|
14
|
+
* The audit result.
|
|
15
|
+
*
|
|
16
|
+
* @param raw - Page-side walk
|
|
17
|
+
* @param options - Checks, level and limit
|
|
18
|
+
* @returns Result
|
|
19
|
+
*/
|
|
20
|
+
export function buildAudit(raw, options) {
|
|
21
|
+
return {
|
|
22
|
+
checks: options.checks,
|
|
23
|
+
walked: raw.walked,
|
|
24
|
+
...(raw.capped && { capped: true }),
|
|
25
|
+
...(raw.texts && { contrast: contrastFindings(raw, options) }),
|
|
26
|
+
...(raw.wide && { overflow: overflowFindings(raw, options.limit) }),
|
|
27
|
+
...(raw.layers && {
|
|
28
|
+
layers: raw.layers.slice(0, options.limit).map((layer) => ({
|
|
29
|
+
element: layer.label,
|
|
30
|
+
position: layer.position,
|
|
31
|
+
zIndex: layer.zIndex,
|
|
32
|
+
rect: {
|
|
33
|
+
x: round1(layer.rect.x),
|
|
34
|
+
y: round1(layer.rect.y),
|
|
35
|
+
w: round1(layer.rect.w),
|
|
36
|
+
h: round1(layer.rect.h),
|
|
37
|
+
},
|
|
38
|
+
inView: layer.inView,
|
|
39
|
+
})),
|
|
40
|
+
}),
|
|
41
|
+
...(raw.animations && {
|
|
42
|
+
animations: grouped(raw.animations.map((animation) => ({
|
|
43
|
+
element: animation.label,
|
|
44
|
+
name: animation.name,
|
|
45
|
+
type: animation.type,
|
|
46
|
+
duration: animation.duration,
|
|
47
|
+
iterations: animation.iterations,
|
|
48
|
+
...(animation.scrollDriven && { scrollDriven: true }),
|
|
49
|
+
}))).slice(0, options.limit),
|
|
50
|
+
}),
|
|
51
|
+
...(raw.canvases && { canvases: raw.canvases }),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Text below the level, weakest first.
|
|
56
|
+
*
|
|
57
|
+
* @param raw - Page-side walk
|
|
58
|
+
* @param options - Level and limit
|
|
59
|
+
* @returns How many were checked and failed, and the weakest
|
|
60
|
+
*/
|
|
61
|
+
function contrastFindings(raw, options) {
|
|
62
|
+
const checked = (raw.texts ?? []).map((text) => contrastItem(text, raw.canvasDark));
|
|
63
|
+
const below = checked
|
|
64
|
+
.filter((item) => item !== undefined)
|
|
65
|
+
.filter((item) => item.ratio < requiredRatio(item, options.level))
|
|
66
|
+
.sort((a, b) => a.ratio - b.ratio);
|
|
67
|
+
const failing = below.filter((item) => !item.approximate);
|
|
68
|
+
const uncertain = below.length - failing.length;
|
|
69
|
+
return {
|
|
70
|
+
level: options.level,
|
|
71
|
+
checked: checked.length,
|
|
72
|
+
failing: failing.length,
|
|
73
|
+
items: failing.slice(0, options.limit),
|
|
74
|
+
...(uncertain > 0 && { uncertain }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* One text holder's contrast.
|
|
79
|
+
*
|
|
80
|
+
* @param text - Page-side text holder
|
|
81
|
+
* @param canvasDark - The page canvas is dark
|
|
82
|
+
* @returns Finding, or undefined when its color cannot be read
|
|
83
|
+
*/
|
|
84
|
+
function contrastItem(text, canvasDark) {
|
|
85
|
+
const contrast = textContrast({ color: text.color, 'font-size': text.fontSize, 'font-weight': text.fontWeight }, {
|
|
86
|
+
backgrounds: text.backgrounds,
|
|
87
|
+
canvasDark,
|
|
88
|
+
opacity: text.opacity,
|
|
89
|
+
paintRisks: text.risks,
|
|
90
|
+
});
|
|
91
|
+
if (!contrast)
|
|
92
|
+
return undefined;
|
|
93
|
+
return {
|
|
94
|
+
element: text.label,
|
|
95
|
+
text: text.text,
|
|
96
|
+
ratio: contrast.ratio,
|
|
97
|
+
color: hexColor(text.color),
|
|
98
|
+
background: contrast.background,
|
|
99
|
+
size: pxNumber(text.fontSize) ?? 16,
|
|
100
|
+
weight: Number(text.fontWeight) || 400,
|
|
101
|
+
inView: text.inView,
|
|
102
|
+
...(contrast.opacity !== undefined && { opacity: contrast.opacity }),
|
|
103
|
+
...(contrast.approximate && { approximate: contrast.approximate }),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The ratio WCAG asks of a text at a level: large text (24px, or 18.66px
|
|
108
|
+
* bold) needs less.
|
|
109
|
+
*
|
|
110
|
+
* @param item - Text size and weight
|
|
111
|
+
* @param level - AA or AAA
|
|
112
|
+
* @returns Minimum ratio
|
|
113
|
+
*/
|
|
114
|
+
export function requiredRatio(item, level) {
|
|
115
|
+
const large = item.size >= 24 || (item.size >= 18.66 && item.weight >= 700);
|
|
116
|
+
if (level === 'AAA')
|
|
117
|
+
return large ? 4.5 : 7;
|
|
118
|
+
return large ? 3 : 4.5;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* What makes the page scroll sideways, cut-off text and scaled images.
|
|
122
|
+
*
|
|
123
|
+
* @param raw - Page-side walk
|
|
124
|
+
* @param limit - Findings per list
|
|
125
|
+
* @returns Overflow findings
|
|
126
|
+
*/
|
|
127
|
+
function overflowFindings(raw, limit) {
|
|
128
|
+
const wide = [...(raw.wide ?? [])].sort((a, b) => b.right - a.right);
|
|
129
|
+
const images = grouped((raw.images ?? [])
|
|
130
|
+
.map((image) => imageFinding(image, raw.pixelRatio))
|
|
131
|
+
.filter((image) => image !== undefined));
|
|
132
|
+
return {
|
|
133
|
+
pageWidth: raw.pageWidth,
|
|
134
|
+
viewportWidth: raw.viewport.width,
|
|
135
|
+
scrollsSideways: raw.pageWidth > raw.viewport.width + 1,
|
|
136
|
+
wide: wide.slice(0, limit).map((element) => ({
|
|
137
|
+
element: element.label,
|
|
138
|
+
right: round1(element.right),
|
|
139
|
+
width: round1(element.width),
|
|
140
|
+
})),
|
|
141
|
+
truncated: grouped((raw.truncated ?? []).map((text) => ({
|
|
142
|
+
element: text.label,
|
|
143
|
+
text: text.text,
|
|
144
|
+
kind: text.kind,
|
|
145
|
+
}))).slice(0, limit),
|
|
146
|
+
images: images.slice(0, limit),
|
|
147
|
+
pixelRatio: raw.pixelRatio,
|
|
148
|
+
scrollers: (raw.scrollers ?? []).slice(0, limit).map((scroller) => ({
|
|
149
|
+
element: scroller.label,
|
|
150
|
+
scrollWidth: scroller.scrollWidth,
|
|
151
|
+
width: scroller.width,
|
|
152
|
+
})),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* How much an image's pixels are stretched on screen, by its `object-fit`:
|
|
157
|
+
* `fill` and `cover` stretch to the larger ratio, `contain` to the smaller,
|
|
158
|
+
* `none` not at all, `scale-down` at most to its own size.
|
|
159
|
+
*
|
|
160
|
+
* @param image - Page-side image
|
|
161
|
+
* @param pixelRatio - Device pixel ratio
|
|
162
|
+
* @returns Screen pixels per image pixel
|
|
163
|
+
*/
|
|
164
|
+
function drawnScale(image, pixelRatio) {
|
|
165
|
+
const across = (image.rendered.w * pixelRatio) / image.natural.w;
|
|
166
|
+
const down = (image.rendered.h * pixelRatio) / image.natural.h;
|
|
167
|
+
if (image.objectFit === 'none')
|
|
168
|
+
return pixelRatio;
|
|
169
|
+
if (image.objectFit === 'contain')
|
|
170
|
+
return Math.min(across, down);
|
|
171
|
+
if (image.objectFit === 'scale-down')
|
|
172
|
+
return Math.min(pixelRatio, Math.min(across, down));
|
|
173
|
+
return Math.max(across, down);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Findings with identical ones merged into the first, with a `count`.
|
|
177
|
+
*
|
|
178
|
+
* @param findings - Findings in page order
|
|
179
|
+
* @returns Findings, each distinct one once
|
|
180
|
+
*/
|
|
181
|
+
function grouped(findings) {
|
|
182
|
+
const byKey = new Map();
|
|
183
|
+
for (const finding of findings) {
|
|
184
|
+
const key = JSON.stringify(finding);
|
|
185
|
+
const seen = byKey.get(key);
|
|
186
|
+
if (seen)
|
|
187
|
+
seen.count = (seen.count ?? 1) + 1;
|
|
188
|
+
else
|
|
189
|
+
byKey.set(key, { ...finding });
|
|
190
|
+
}
|
|
191
|
+
return [...byKey.values()];
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* An image drawn with fewer pixels than the screen needs (upscaled, blurry:
|
|
195
|
+
* rendered size × pixel ratio over its own pixels) or with another aspect
|
|
196
|
+
* ratio (distorted, unless `object-fit` keeps the ratio).
|
|
197
|
+
*
|
|
198
|
+
* @param image - Page-side image
|
|
199
|
+
* @param pixelRatio - Device pixel ratio
|
|
200
|
+
* @returns Finding, or undefined when it is sharp and keeps its ratio
|
|
201
|
+
*/
|
|
202
|
+
export function imageFinding(image, pixelRatio = 1) {
|
|
203
|
+
const scale = drawnScale(image, pixelRatio);
|
|
204
|
+
const naturalRatio = image.natural.w / image.natural.h;
|
|
205
|
+
const renderedRatio = image.rendered.w / image.rendered.h;
|
|
206
|
+
const distorted = image.objectFit === 'fill' &&
|
|
207
|
+
Math.abs(renderedRatio - naturalRatio) / naturalRatio > IMAGE_TOLERANCE;
|
|
208
|
+
const upscaled = scale > 1 + IMAGE_TOLERANCE;
|
|
209
|
+
if (!distorted && !upscaled)
|
|
210
|
+
return undefined;
|
|
211
|
+
return {
|
|
212
|
+
element: image.label,
|
|
213
|
+
natural: image.natural,
|
|
214
|
+
rendered: { w: round1(image.rendered.w), h: round1(image.rendered.h) },
|
|
215
|
+
scale: Math.round(scale * 100) / 100,
|
|
216
|
+
...(upscaled && { upscaled: true }),
|
|
217
|
+
...(distorted && { distorted: true }),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=auditModel.js.map
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page-side part of `bdg dom audit`: one walk over the rendered elements of
|
|
3
|
+
* the page (open shadow roots and the light DOM slotted into them, at most
|
|
4
|
+
* {@link AUDIT_ELEMENT_CAP}; nothing inside a fixed element counts as making
|
|
5
|
+
* the page wider; SVG images and placeholders of 2px or less are skipped)
|
|
6
|
+
* that collects what each check needs. Colors and contrast are computed in
|
|
7
|
+
* the daemon ({@link buildAudit}), the same way `dom inspect` computes them.
|
|
8
|
+
*/
|
|
9
|
+
import { type RawBackground } from './inspectScripts.js';
|
|
10
|
+
/** Elements the walk looks at, at most */
|
|
11
|
+
export declare const AUDIT_ELEMENT_CAP = 20000;
|
|
12
|
+
/** A text holder: an element that draws text of its own */
|
|
13
|
+
export interface RawAuditText {
|
|
14
|
+
label: string;
|
|
15
|
+
text: string;
|
|
16
|
+
color: string;
|
|
17
|
+
fontSize: string;
|
|
18
|
+
fontWeight: string;
|
|
19
|
+
/** Backgrounds from the element up to the root, each with its own opacity */
|
|
20
|
+
backgrounds: RawBackground[];
|
|
21
|
+
opacity: number;
|
|
22
|
+
/**
|
|
23
|
+
* Why its contrast is approximate: blend modes and filters on it or an
|
|
24
|
+
* ancestor, an element painted behind or on top of it (in view), or that
|
|
25
|
+
* only its ancestors were checked (out of view, none of them paints)
|
|
26
|
+
*/
|
|
27
|
+
risks: string[];
|
|
28
|
+
/** Inside the viewport */
|
|
29
|
+
inView: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** An element that reaches past the right edge of the page's viewport */
|
|
32
|
+
export interface RawWideElement {
|
|
33
|
+
label: string;
|
|
34
|
+
right: number;
|
|
35
|
+
width: number;
|
|
36
|
+
}
|
|
37
|
+
/** Text cut off by its box */
|
|
38
|
+
export interface RawTruncated {
|
|
39
|
+
label: string;
|
|
40
|
+
text: string;
|
|
41
|
+
/** `ellipsis`, `clamp` or `clip` */
|
|
42
|
+
kind: string;
|
|
43
|
+
}
|
|
44
|
+
/** An image drawn at another size than its own */
|
|
45
|
+
export interface RawImage {
|
|
46
|
+
label: string;
|
|
47
|
+
natural: {
|
|
48
|
+
w: number;
|
|
49
|
+
h: number;
|
|
50
|
+
};
|
|
51
|
+
rendered: {
|
|
52
|
+
w: number;
|
|
53
|
+
h: number;
|
|
54
|
+
};
|
|
55
|
+
objectFit: string;
|
|
56
|
+
}
|
|
57
|
+
/** A fixed or sticky element */
|
|
58
|
+
export interface RawLayer {
|
|
59
|
+
label: string;
|
|
60
|
+
position: string;
|
|
61
|
+
zIndex: string;
|
|
62
|
+
rect: {
|
|
63
|
+
x: number;
|
|
64
|
+
y: number;
|
|
65
|
+
w: number;
|
|
66
|
+
h: number;
|
|
67
|
+
};
|
|
68
|
+
inView: boolean;
|
|
69
|
+
}
|
|
70
|
+
/** A running animation or transition */
|
|
71
|
+
export interface RawAnimation {
|
|
72
|
+
label: string;
|
|
73
|
+
/** Animation name, transitioned property, or `animation` for a Web Animation */
|
|
74
|
+
name: string;
|
|
75
|
+
type: string;
|
|
76
|
+
duration: number | string;
|
|
77
|
+
iterations: number | string;
|
|
78
|
+
scrollDriven: boolean;
|
|
79
|
+
}
|
|
80
|
+
/** What {@link AUDIT_PAGE_JS} returns */
|
|
81
|
+
export interface RawAudit {
|
|
82
|
+
viewport: {
|
|
83
|
+
width: number;
|
|
84
|
+
height: number;
|
|
85
|
+
};
|
|
86
|
+
/** Device pixel ratio: an image needs that many pixels per CSS px to look sharp */
|
|
87
|
+
pixelRatio: number;
|
|
88
|
+
pageWidth: number;
|
|
89
|
+
canvasDark: boolean;
|
|
90
|
+
/** Elements walked, and whether the walk stopped at the cap */
|
|
91
|
+
walked: number;
|
|
92
|
+
capped: boolean;
|
|
93
|
+
texts?: RawAuditText[];
|
|
94
|
+
wide?: RawWideElement[];
|
|
95
|
+
truncated?: RawTruncated[];
|
|
96
|
+
images?: RawImage[];
|
|
97
|
+
/** Elements whose content scrolls sideways inside them (carousels, tab strips) */
|
|
98
|
+
scrollers?: Array<{
|
|
99
|
+
label: string;
|
|
100
|
+
scrollWidth: number;
|
|
101
|
+
width: number;
|
|
102
|
+
}>;
|
|
103
|
+
layers?: RawLayer[];
|
|
104
|
+
animations?: RawAnimation[];
|
|
105
|
+
/** Visible `<canvas>` elements (their animations are drawn by scripts, not CSS or Web Animations) */
|
|
106
|
+
canvases?: number;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Page-side audit walk. Arguments: the checks to collect for
|
|
110
|
+
* (`contrast`, `overflow`, `layers`, `animations`).
|
|
111
|
+
*/
|
|
112
|
+
export declare const AUDIT_PAGE_JS: string;
|
|
113
|
+
//# sourceMappingURL=auditScripts.d.ts.map
|