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
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* backgrounds of the element and its ancestors composited over the page
|
|
8
8
|
* canvas).
|
|
9
9
|
*/
|
|
10
|
-
import type { InspectContrast, InspectEffect, InspectFill, InspectFx, InspectPseudo, InspectState, InspectStroke, InspectText, Sides } from '../../ipc/protocol/inspectTypes.js';
|
|
10
|
+
import type { InspectContrast, InspectEffect, InspectFill, InspectFx, InspectPseudo, InspectState, InspectStroke, InspectSvgPaint, InspectText, Sides } from '../../ipc/protocol/inspectTypes.js';
|
|
11
11
|
import type { StyleMap } from './inspectLayoutModel.js';
|
|
12
12
|
import type { RawBackground, RawInspect } from './inspectScripts.js';
|
|
13
13
|
import { type Rgba } from '../../utils/color.js';
|
|
@@ -18,20 +18,24 @@ export interface PlatformFont {
|
|
|
18
18
|
glyphCount: number;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* The font the text was rendered with
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
21
|
+
* The font the text was rendered with and whether it is a web font. For a
|
|
22
|
+
* generic first family, the font it resolved to (`resolved`). Otherwise
|
|
23
|
+
* `rendered` only when it is a fallback: not a face of the first family
|
|
24
|
+
* (`DM Sans 9pt` is a face of `DM Sans`, `Liberation Sans` is not one of
|
|
25
|
+
* `Arial`), and the first family is not a web font the page loaded (whose
|
|
26
|
+
* file may give any internal name: `Copyright Klim Type Foundry`, or the
|
|
27
|
+
* local font a `src: local()` points at). Names that are not readable
|
|
28
|
+
* (sites that scramble a web font's internal name) are left out.
|
|
26
29
|
*
|
|
27
30
|
* @param family - First family of `font-family`
|
|
28
31
|
* @param fonts - Platform fonts of the text
|
|
29
|
-
* @
|
|
32
|
+
* @param familyLoaded - The first family is a loaded web font
|
|
33
|
+
* @returns `rendered`, `resolved` and `webfont` fields
|
|
30
34
|
*/
|
|
31
|
-
export declare function renderedFont(family: string, fonts: readonly PlatformFont[]): Pick<InspectText, 'rendered' | 'webfont'>;
|
|
35
|
+
export declare function renderedFont(family: string, fonts: readonly PlatformFont[], familyLoaded?: boolean): Pick<InspectText, 'rendered' | 'resolved' | 'webfont'>;
|
|
32
36
|
/**
|
|
33
37
|
* The background behind the element's text: its own and its ancestors'
|
|
34
|
-
* backgrounds composited
|
|
38
|
+
* backgrounds composited with their opacity over the page canvas.
|
|
35
39
|
*
|
|
36
40
|
* @param backgrounds - Backgrounds, the element's own first
|
|
37
41
|
* @param canvasDark - The page canvas is dark
|
|
@@ -42,36 +46,60 @@ export declare function effectiveBackground(backgrounds: readonly RawBackground[
|
|
|
42
46
|
inherited: boolean;
|
|
43
47
|
overImage: boolean;
|
|
44
48
|
};
|
|
49
|
+
/** Why a contrast over a background image or gradient is approximate (its pixels are unknown) */
|
|
50
|
+
export declare const OVER_IMAGE_RISK = "background image or gradient behind";
|
|
45
51
|
/**
|
|
46
|
-
* Contrast of the text color with the background behind it
|
|
52
|
+
* Contrast of the text color with the background behind it, both painted
|
|
53
|
+
* as the browser composites them ({@link paintOver}), with what makes the
|
|
54
|
+
* number approximate (blend modes, filters, content behind or on top).
|
|
47
55
|
*
|
|
48
56
|
* @param style - Computed styles (color, font size and weight)
|
|
49
|
-
* @param raw - Backgrounds
|
|
57
|
+
* @param raw - Backgrounds, the page canvas, opacity and paint risks
|
|
50
58
|
* @returns Ratio (rounded down to 2 decimals), level and background
|
|
51
59
|
*/
|
|
52
|
-
export declare function textContrast(style: StyleMap, raw: Pick<RawInspect, 'backgrounds' | 'canvasDark' | 'opacity'>): InspectContrast | undefined;
|
|
60
|
+
export declare function textContrast(style: StyleMap, raw: Pick<RawInspect, 'backgrounds' | 'canvasDark' | 'opacity' | 'paintRisks'>): InspectContrast | undefined;
|
|
61
|
+
/** Computed styles the text group reads */
|
|
62
|
+
export interface TextStyles {
|
|
63
|
+
/** The element's */
|
|
64
|
+
style: StyleMap;
|
|
65
|
+
/** Its layout parent's */
|
|
66
|
+
parentStyle?: StyleMap | undefined;
|
|
67
|
+
/** The descendant's that draws most of its text, when it is not the element */
|
|
68
|
+
holderStyle?: StyleMap | undefined;
|
|
69
|
+
}
|
|
53
70
|
/**
|
|
54
|
-
* The text group. Elements with text (or
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* differs
|
|
71
|
+
* The text group. Elements with text (or text fields) get the full group,
|
|
72
|
+
* read from whatever draws the text (the element, or the descendant with
|
|
73
|
+
* most of it, named in `holder`): font with the rendered font, size, color,
|
|
74
|
+
* alignment, contrast (not for text no one can see: not rendered,
|
|
75
|
+
* `opacity: 0` on it or an ancestor, `visibility: hidden`) and the
|
|
76
|
+
* non-default extras. Containers get only what differs from their parent,
|
|
77
|
+
* with the font their text was rendered in when that text has the
|
|
78
|
+
* container's family. Nothing for an element without text (an icon button,
|
|
79
|
+
* a checkbox).
|
|
60
80
|
*
|
|
61
|
-
* @param
|
|
62
|
-
* @param parentStyle - Computed styles of the layout parent
|
|
81
|
+
* @param styles - Computed styles of the element, its parent and its text holder
|
|
63
82
|
* @param raw - Page-side measurements
|
|
64
83
|
* @param fonts - Platform fonts of the text
|
|
65
84
|
* @returns Text group, or undefined when there is nothing to say
|
|
66
85
|
*/
|
|
67
|
-
export declare function buildText(
|
|
86
|
+
export declare function buildText(styles: TextStyles, raw: Pick<RawInspect, 'textual' | 'textHolder' | 'rendered' | 'hasText' | 'familyLoaded' | 'truncated' | 'backgrounds' | 'canvasDark' | 'opacity' | 'paintRisks'>, fonts: readonly PlatformFont[]): InspectText | undefined;
|
|
68
87
|
/**
|
|
69
|
-
* Background layers: images and gradients (top first),
|
|
88
|
+
* Background layers: images and gradients (top first), each with its own
|
|
89
|
+
* size and position when they are not the defaults, then the color.
|
|
70
90
|
*
|
|
71
91
|
* @param style - Computed styles
|
|
72
92
|
* @returns Fills
|
|
73
93
|
*/
|
|
74
94
|
export declare function buildFills(style: StyleMap): InspectFill[];
|
|
95
|
+
/**
|
|
96
|
+
* How an SVG element is painted: its `fill` and `stroke` (with the width).
|
|
97
|
+
*
|
|
98
|
+
* @param style - Computed styles
|
|
99
|
+
* @param raw - Whether it is an SVG element
|
|
100
|
+
* @returns Paint, or undefined for an HTML element
|
|
101
|
+
*/
|
|
102
|
+
export declare function buildSvgPaint(style: StyleMap, raw: Pick<RawInspect, 'svg'>): InspectSvgPaint | undefined;
|
|
75
103
|
/**
|
|
76
104
|
* Border sides that show (a style other than none/hidden and a width): one
|
|
77
105
|
* `all` stroke when the four are equal.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* canvas).
|
|
9
9
|
*/
|
|
10
10
|
import { composite, contrastLevel, contrastRatio, hexColor, parseColor, toHex, } from '../../utils/color.js';
|
|
11
|
-
import { cssLength, firstFontFamily, normalizeCssValue, parseShadows, pxNumber, readableTransform, shadowText, shortUrls, splitTopLevel, } from '../../utils/cssValues.js';
|
|
11
|
+
import { cssLength, firstFontFamily, normalizeCssValue, parseShadows, pxNumber, readableTransform, shadowText, shortUrls, sidesShorthand, splitTopLevel, } from '../../utils/cssValues.js';
|
|
12
12
|
/** Background images and gradients are shown at most this long */
|
|
13
13
|
const IMAGE_TEXT_LENGTH = 140;
|
|
14
14
|
/** Page canvas colors (light and dark color-scheme) */
|
|
@@ -16,62 +16,127 @@ const CANVAS = {
|
|
|
16
16
|
light: { r: 1, g: 1, b: 1, a: 1 },
|
|
17
17
|
dark: { r: 0x12 / 255, g: 0x12 / 255, b: 0x12 / 255, a: 1 },
|
|
18
18
|
};
|
|
19
|
+
/** CSS generic font families: the browser picks a font for them */
|
|
20
|
+
const GENERIC_FAMILIES = new Set([
|
|
21
|
+
'serif',
|
|
22
|
+
'sans-serif',
|
|
23
|
+
'monospace',
|
|
24
|
+
'cursive',
|
|
25
|
+
'fantasy',
|
|
26
|
+
'system-ui',
|
|
27
|
+
'ui-serif',
|
|
28
|
+
'ui-sans-serif',
|
|
29
|
+
'ui-monospace',
|
|
30
|
+
'ui-rounded',
|
|
31
|
+
'math',
|
|
32
|
+
'emoji',
|
|
33
|
+
'fangsong',
|
|
34
|
+
'-apple-system',
|
|
35
|
+
'blinkmacsystemfont',
|
|
36
|
+
]);
|
|
19
37
|
/**
|
|
20
|
-
* The font the text was rendered with
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
38
|
+
* The font the text was rendered with and whether it is a web font. For a
|
|
39
|
+
* generic first family, the font it resolved to (`resolved`). Otherwise
|
|
40
|
+
* `rendered` only when it is a fallback: not a face of the first family
|
|
41
|
+
* (`DM Sans 9pt` is a face of `DM Sans`, `Liberation Sans` is not one of
|
|
42
|
+
* `Arial`), and the first family is not a web font the page loaded (whose
|
|
43
|
+
* file may give any internal name: `Copyright Klim Type Foundry`, or the
|
|
44
|
+
* local font a `src: local()` points at). Names that are not readable
|
|
45
|
+
* (sites that scramble a web font's internal name) are left out.
|
|
25
46
|
*
|
|
26
47
|
* @param family - First family of `font-family`
|
|
27
48
|
* @param fonts - Platform fonts of the text
|
|
28
|
-
* @
|
|
49
|
+
* @param familyLoaded - The first family is a loaded web font
|
|
50
|
+
* @returns `rendered`, `resolved` and `webfont` fields
|
|
29
51
|
*/
|
|
30
|
-
export function renderedFont(family, fonts) {
|
|
52
|
+
export function renderedFont(family, fonts, familyLoaded = false) {
|
|
31
53
|
const primary = [...fonts].sort((a, b) => b.glyphCount - a.glyphCount)[0];
|
|
32
54
|
if (!primary)
|
|
33
55
|
return {};
|
|
56
|
+
const webfont = primary.isCustomFont ? { webfont: true } : {};
|
|
34
57
|
const readable = /^[\p{L}\p{N}.][\p{L}\p{N} ._'-]+$/u.test(primary.familyName);
|
|
35
|
-
|
|
58
|
+
if (!readable || familyLoaded)
|
|
59
|
+
return webfont;
|
|
60
|
+
if (GENERIC_FAMILIES.has(family.toLowerCase())) {
|
|
61
|
+
return { resolved: primary.familyName, ...webfont };
|
|
62
|
+
}
|
|
63
|
+
const differs = !primary.familyName.toLowerCase().startsWith(family.toLowerCase());
|
|
64
|
+
return { ...(differs && { rendered: primary.familyName }), ...webfont };
|
|
65
|
+
}
|
|
66
|
+
/** Fully transparent */
|
|
67
|
+
const CLEAR = { r: 0, g: 0, b: 0, a: 0 };
|
|
68
|
+
/**
|
|
69
|
+
* Paint the text color and the background behind it the way the browser
|
|
70
|
+
* composites them: from the element up to the root, each element's content
|
|
71
|
+
* over its own background, the result faded by its opacity (a translucent
|
|
72
|
+
* ancestor fades its background along with the text), then over the page
|
|
73
|
+
* canvas.
|
|
74
|
+
*
|
|
75
|
+
* @param text - Text color (undefined: the background alone)
|
|
76
|
+
* @param backgrounds - Backgrounds with their opacity, the element's own first
|
|
77
|
+
* @param canvasDark - The page canvas is dark
|
|
78
|
+
* @returns The text pixel, the background pixel and whether a background
|
|
79
|
+
* image or gradient was in the way
|
|
80
|
+
*/
|
|
81
|
+
function paintOver(text, backgrounds, canvasDark) {
|
|
82
|
+
let withText = text ?? CLEAR;
|
|
83
|
+
let without = CLEAR;
|
|
84
|
+
let overImage = false;
|
|
85
|
+
for (const layer of backgrounds) {
|
|
86
|
+
if (layer.image && without.a < 0.999)
|
|
87
|
+
overImage = true;
|
|
88
|
+
const color = parseColor(layer.color);
|
|
89
|
+
if (color && color.a > 0) {
|
|
90
|
+
withText = composite(withText, color);
|
|
91
|
+
without = composite(without, color);
|
|
92
|
+
}
|
|
93
|
+
const opacity = layer.opacity ?? 1;
|
|
94
|
+
withText = { ...withText, a: withText.a * opacity };
|
|
95
|
+
without = { ...without, a: without.a * opacity };
|
|
96
|
+
}
|
|
97
|
+
const canvas = CANVAS[canvasDark ? 'dark' : 'light'];
|
|
36
98
|
return {
|
|
37
|
-
|
|
38
|
-
|
|
99
|
+
text: composite(withText, canvas),
|
|
100
|
+
background: composite(without, canvas),
|
|
101
|
+
overImage,
|
|
39
102
|
};
|
|
40
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Whether the element's own background lets what is behind it through (the
|
|
106
|
+
* background behind its text comes from an ancestor or the canvas).
|
|
107
|
+
*
|
|
108
|
+
* @param backgrounds - Backgrounds, the element's own first
|
|
109
|
+
* @returns True when its own background is not opaque
|
|
110
|
+
*/
|
|
111
|
+
function ownBackgroundTranslucent(backgrounds) {
|
|
112
|
+
const own = parseColor(backgrounds[0]?.color ?? '');
|
|
113
|
+
return !own || own.a < 0.999;
|
|
114
|
+
}
|
|
41
115
|
/**
|
|
42
116
|
* The background behind the element's text: its own and its ancestors'
|
|
43
|
-
* backgrounds composited
|
|
117
|
+
* backgrounds composited with their opacity over the page canvas.
|
|
44
118
|
*
|
|
45
119
|
* @param backgrounds - Backgrounds, the element's own first
|
|
46
120
|
* @param canvasDark - The page canvas is dark
|
|
47
121
|
* @returns Opaque background, whether it came from an ancestor and whether an image was in the way
|
|
48
122
|
*/
|
|
49
123
|
export function effectiveBackground(backgrounds, canvasDark) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (!color || color.a === 0)
|
|
57
|
-
continue;
|
|
58
|
-
layers.push(color);
|
|
59
|
-
if (color.a >= 0.999)
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
const base = layers[layers.length - 1];
|
|
63
|
-
let color = base && base.a >= 0.999 ? base : CANVAS[canvasDark ? 'dark' : 'light'];
|
|
64
|
-
const translucent = base && base.a >= 0.999 ? layers.slice(0, -1) : layers;
|
|
65
|
-
for (const layer of [...translucent].reverse())
|
|
66
|
-
color = composite(layer, color);
|
|
67
|
-
const own = parseColor(backgrounds[0]?.color ?? '');
|
|
68
|
-
return { color, inherited: !own || own.a < 0.999, overImage };
|
|
124
|
+
const painted = paintOver(undefined, backgrounds, canvasDark);
|
|
125
|
+
return {
|
|
126
|
+
color: painted.background,
|
|
127
|
+
inherited: ownBackgroundTranslucent(backgrounds),
|
|
128
|
+
overImage: painted.overImage,
|
|
129
|
+
};
|
|
69
130
|
}
|
|
131
|
+
/** Why a contrast over a background image or gradient is approximate (its pixels are unknown) */
|
|
132
|
+
export const OVER_IMAGE_RISK = 'background image or gradient behind';
|
|
70
133
|
/**
|
|
71
|
-
* Contrast of the text color with the background behind it
|
|
134
|
+
* Contrast of the text color with the background behind it, both painted
|
|
135
|
+
* as the browser composites them ({@link paintOver}), with what makes the
|
|
136
|
+
* number approximate (blend modes, filters, content behind or on top).
|
|
72
137
|
*
|
|
73
138
|
* @param style - Computed styles (color, font size and weight)
|
|
74
|
-
* @param raw - Backgrounds
|
|
139
|
+
* @param raw - Backgrounds, the page canvas, opacity and paint risks
|
|
75
140
|
* @returns Ratio (rounded down to 2 decimals), level and background
|
|
76
141
|
*/
|
|
77
142
|
export function textContrast(style, raw) {
|
|
@@ -79,18 +144,19 @@ export function textContrast(style, raw) {
|
|
|
79
144
|
if (!color)
|
|
80
145
|
return undefined;
|
|
81
146
|
const opacity = raw.opacity ?? 1;
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
const ratio = Math.floor(contrastRatio(text, background.color) * 100) / 100;
|
|
147
|
+
const painted = paintOver(color, raw.backgrounds, raw.canvasDark);
|
|
148
|
+
const ratio = Math.floor(contrastRatio(painted.text, painted.background) * 100) / 100;
|
|
85
149
|
const size = pxNumber(style['font-size']) ?? 16;
|
|
86
150
|
const weight = Number(style['font-weight'] ?? 400);
|
|
151
|
+
const approximate = [...(raw.paintRisks ?? []), ...(painted.overImage ? [OVER_IMAGE_RISK] : [])];
|
|
87
152
|
return {
|
|
88
153
|
ratio,
|
|
89
154
|
level: contrastLevel(ratio, size, weight),
|
|
90
|
-
background: toHex(background
|
|
91
|
-
...(
|
|
92
|
-
...(
|
|
155
|
+
background: toHex(painted.background),
|
|
156
|
+
...(ownBackgroundTranslucent(raw.backgrounds) && { inherited: true }),
|
|
157
|
+
...(painted.overImage && { overImage: true }),
|
|
93
158
|
...(opacity < 1 && { opacity: Math.round(opacity * 100) / 100 }),
|
|
159
|
+
...(approximate.length > 0 && { approximate }),
|
|
94
160
|
};
|
|
95
161
|
}
|
|
96
162
|
/**
|
|
@@ -188,40 +254,56 @@ function fontFields(style) {
|
|
|
188
254
|
};
|
|
189
255
|
}
|
|
190
256
|
/**
|
|
191
|
-
* The text group. Elements with text (or
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
* differs
|
|
257
|
+
* The text group. Elements with text (or text fields) get the full group,
|
|
258
|
+
* read from whatever draws the text (the element, or the descendant with
|
|
259
|
+
* most of it, named in `holder`): font with the rendered font, size, color,
|
|
260
|
+
* alignment, contrast (not for text no one can see: not rendered,
|
|
261
|
+
* `opacity: 0` on it or an ancestor, `visibility: hidden`) and the
|
|
262
|
+
* non-default extras. Containers get only what differs from their parent,
|
|
263
|
+
* with the font their text was rendered in when that text has the
|
|
264
|
+
* container's family. Nothing for an element without text (an icon button,
|
|
265
|
+
* a checkbox).
|
|
197
266
|
*
|
|
198
|
-
* @param
|
|
199
|
-
* @param parentStyle - Computed styles of the layout parent
|
|
267
|
+
* @param styles - Computed styles of the element, its parent and its text holder
|
|
200
268
|
* @param raw - Page-side measurements
|
|
201
269
|
* @param fonts - Platform fonts of the text
|
|
202
270
|
* @returns Text group, or undefined when there is nothing to say
|
|
203
271
|
*/
|
|
204
|
-
export function buildText(
|
|
205
|
-
const
|
|
272
|
+
export function buildText(styles, raw, fonts) {
|
|
273
|
+
const { style, parentStyle, holderStyle } = styles;
|
|
206
274
|
if (raw.textual) {
|
|
207
|
-
const
|
|
208
|
-
const
|
|
275
|
+
const textStyle = raw.textHolder && holderStyle ? holderStyle : style;
|
|
276
|
+
const fields = fontFields(textStyle);
|
|
277
|
+
const gradientFill = (textStyle['background-clip'] ?? '').includes('text') &&
|
|
278
|
+
(parseColor(textStyle['-webkit-text-fill-color'] ?? '')?.a ?? 1) === 0;
|
|
279
|
+
const seen = raw.rendered !== false &&
|
|
280
|
+
(raw.opacity ?? 1) > 0 &&
|
|
281
|
+
textStyle['visibility'] !== 'hidden' &&
|
|
282
|
+
!gradientFill;
|
|
283
|
+
const contrast = seen ? textContrast(textStyle, raw) : undefined;
|
|
209
284
|
return {
|
|
285
|
+
...(textStyle !== style && raw.textHolder && { holder: raw.textHolder }),
|
|
210
286
|
...fields,
|
|
211
|
-
...renderedFont(fields.family ?? '', fonts),
|
|
287
|
+
...renderedFont(fields.family ?? '', fonts, raw.familyLoaded),
|
|
212
288
|
...(contrast && { contrast }),
|
|
213
|
-
...textExtras(
|
|
214
|
-
align: alignOf(
|
|
289
|
+
...textExtras(textStyle),
|
|
290
|
+
align: alignOf(textStyle),
|
|
291
|
+
...(raw.truncated && { truncated: true }),
|
|
292
|
+
...(gradientFill && { gradientFill: true }),
|
|
215
293
|
};
|
|
216
294
|
}
|
|
217
|
-
if (!parentStyle)
|
|
295
|
+
if (!parentStyle || raw.hasText === false)
|
|
218
296
|
return undefined;
|
|
297
|
+
const fields = fontFields(style);
|
|
219
298
|
const parentFields = { ...fontFields(parentStyle), ...textExtras(parentStyle) };
|
|
220
299
|
const own = { ...fields, ...textExtras(style) };
|
|
221
300
|
const differing = Object.fromEntries(Object.entries(own).filter(([key, value]) => parentFields[key] !== value));
|
|
222
301
|
if (Object.keys(differing).length === 0)
|
|
223
302
|
return undefined;
|
|
224
|
-
|
|
303
|
+
const sameFamily = !holderStyle || holderStyle['font-family'] === style['font-family'];
|
|
304
|
+
return differing.family && sameFamily
|
|
305
|
+
? { ...differing, ...renderedFont(differing.family, fonts, raw.familyLoaded) }
|
|
306
|
+
: differing;
|
|
225
307
|
}
|
|
226
308
|
/**
|
|
227
309
|
* Cut a long value.
|
|
@@ -233,7 +315,8 @@ function cut(text) {
|
|
|
233
315
|
return text.length > IMAGE_TEXT_LENGTH ? `${text.slice(0, IMAGE_TEXT_LENGTH)}…` : text;
|
|
234
316
|
}
|
|
235
317
|
/**
|
|
236
|
-
* Background layers: images and gradients (top first),
|
|
318
|
+
* Background layers: images and gradients (top first), each with its own
|
|
319
|
+
* size and position when they are not the defaults, then the color.
|
|
237
320
|
*
|
|
238
321
|
* @param style - Computed styles
|
|
239
322
|
* @returns Fills
|
|
@@ -241,25 +324,46 @@ function cut(text) {
|
|
|
241
324
|
export function buildFills(style) {
|
|
242
325
|
const fills = [];
|
|
243
326
|
const image = style['background-image'];
|
|
244
|
-
const size = style['background-size'];
|
|
245
327
|
if (image && image !== 'none') {
|
|
246
|
-
|
|
328
|
+
const sizes = splitTopLevel(style['background-size'] ?? 'auto');
|
|
329
|
+
const xs = splitTopLevel(style['background-position-x'] ?? '0%');
|
|
330
|
+
const ys = splitTopLevel(style['background-position-y'] ?? '0%');
|
|
331
|
+
const positions = xs.map((x, i) => `${x} ${ys[i % ys.length] ?? '0%'}`);
|
|
332
|
+
splitTopLevel(image).forEach((layer, i) => {
|
|
333
|
+
const size = sizes[i % sizes.length] ?? 'auto';
|
|
334
|
+
const position = positions[i % positions.length] ?? '0% 0%';
|
|
247
335
|
const value = cut(normalizeCssValue(shortUrls(layer)));
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
});
|
|
256
|
-
}
|
|
336
|
+
fills.push({
|
|
337
|
+
type: layer.includes('gradient(') ? 'gradient' : 'image',
|
|
338
|
+
value,
|
|
339
|
+
...(size !== 'auto' && size !== 'auto auto' && { size: normalizeCssValue(size) }),
|
|
340
|
+
...(position !== '0% 0%' && { position: normalizeCssValue(position) }),
|
|
341
|
+
});
|
|
342
|
+
});
|
|
257
343
|
}
|
|
258
344
|
const color = hexColor(style['background-color'] ?? 'transparent');
|
|
259
345
|
if (color !== 'transparent')
|
|
260
346
|
fills.push({ type: 'solid', color });
|
|
261
347
|
return fills;
|
|
262
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* How an SVG element is painted: its `fill` and `stroke` (with the width).
|
|
351
|
+
*
|
|
352
|
+
* @param style - Computed styles
|
|
353
|
+
* @param raw - Whether it is an SVG element
|
|
354
|
+
* @returns Paint, or undefined for an HTML element
|
|
355
|
+
*/
|
|
356
|
+
export function buildSvgPaint(style, raw) {
|
|
357
|
+
if (!raw.svg)
|
|
358
|
+
return undefined;
|
|
359
|
+
const paint = (value) => normalizeCssValue(shortUrls(hexColor(value ?? 'none')));
|
|
360
|
+
const stroke = paint(style['stroke']);
|
|
361
|
+
return {
|
|
362
|
+
fill: paint(style['fill']),
|
|
363
|
+
stroke,
|
|
364
|
+
...(stroke !== 'none' && { strokeWidth: cssLength(style['stroke-width'] ?? '1px') }),
|
|
365
|
+
};
|
|
366
|
+
}
|
|
263
367
|
/**
|
|
264
368
|
* Border sides that show (a style other than none/hidden and a width): one
|
|
265
369
|
* `all` stroke when the four are equal.
|
|
@@ -421,6 +525,7 @@ export function buildGeneratedPseudo(pseudo, hostColor) {
|
|
|
421
525
|
content: shortUrls(content),
|
|
422
526
|
...(display && display !== 'inline' && { display }),
|
|
423
527
|
...(position && position !== 'static' && { position }),
|
|
528
|
+
...(position && position !== 'static' && { inset: insetOf(style) }),
|
|
424
529
|
...(pseudo.size && { size: pseudo.size }),
|
|
425
530
|
...(style['color'] && style['color'] !== hostColor && { color: hexColor(style['color']) }),
|
|
426
531
|
...(fills.length > 0 && { fills }),
|
|
@@ -430,6 +535,15 @@ export function buildGeneratedPseudo(pseudo, hostColor) {
|
|
|
430
535
|
...(opacity !== 1 && { opacity }),
|
|
431
536
|
};
|
|
432
537
|
}
|
|
538
|
+
/**
|
|
539
|
+
* Offsets of a positioned box, as one 1-4 value shorthand.
|
|
540
|
+
*
|
|
541
|
+
* @param style - Computed styles
|
|
542
|
+
* @returns e.g. `auto 50% -9 0`
|
|
543
|
+
*/
|
|
544
|
+
function insetOf(style) {
|
|
545
|
+
return sidesShorthand(['top', 'right', 'bottom', 'left'].map((side) => normalizeCssValue(style[side] ?? 'auto')));
|
|
546
|
+
}
|
|
433
547
|
/**
|
|
434
548
|
* The pseudo group: generated `::before`/`::after` and the placeholder color.
|
|
435
549
|
*
|
|
@@ -14,6 +14,14 @@ import type { Declaration } from './inspectCascade.js';
|
|
|
14
14
|
* @param cdp - CDP connection
|
|
15
15
|
*/
|
|
16
16
|
export declare function trackStyleSheets(cdp: CDPConnection): void;
|
|
17
|
+
/**
|
|
18
|
+
* The stylesheet headers seen on a connection (after {@link trackStyleSheets}
|
|
19
|
+
* and `CSS.enable`).
|
|
20
|
+
*
|
|
21
|
+
* @param cdp - CDP connection
|
|
22
|
+
* @returns Headers
|
|
23
|
+
*/
|
|
24
|
+
export declare function styleSheetHeaders(cdp: CDPConnection): Iterable<Protocol.CSS.CSSStyleSheetHeader>;
|
|
17
25
|
/**
|
|
18
26
|
* The rules that match an element, with its inline style and what its
|
|
19
27
|
* ancestors pass down, or why they are missing.
|
|
@@ -34,4 +42,15 @@ export declare function matchedStyles(cdp: CDPConnection, nodeId: number, budget
|
|
|
34
42
|
* @returns e.g. `.btn-primary (bootstrap.min.css:5:52628)`, `style attribute`, `browser default`
|
|
35
43
|
*/
|
|
36
44
|
export declare function sourceLabel(declaration: Declaration, cdp: CDPConnection): string;
|
|
45
|
+
/**
|
|
46
|
+
* A stylesheet position as `file:line[:column]`.
|
|
47
|
+
*
|
|
48
|
+
* @param header - Stylesheet header (unknown: just the line)
|
|
49
|
+
* @param line - 0-based line within the stylesheet
|
|
50
|
+
* @param column - 0-based column
|
|
51
|
+
* @returns e.g. `app.css:12`, `bootstrap.min.css:5:52628`, `<style> in index.html:40`,
|
|
52
|
+
* `constructed stylesheet`, `<style> added by a script` (a sheet a script created and
|
|
53
|
+
* filled with `insertRule`: its lines are not in any file)
|
|
54
|
+
*/
|
|
55
|
+
export declare function stylesheetPositionLabel(header: Protocol.CSS.CSSStyleSheetHeader | undefined, line: number | undefined, column: number | undefined): string;
|
|
37
56
|
//# sourceMappingURL=inspectRules.d.ts.map
|
|
@@ -27,6 +27,16 @@ export function trackStyleSheets(cdp) {
|
|
|
27
27
|
headers.delete(styleSheetId);
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* The stylesheet headers seen on a connection (after {@link trackStyleSheets}
|
|
32
|
+
* and `CSS.enable`).
|
|
33
|
+
*
|
|
34
|
+
* @param cdp - CDP connection
|
|
35
|
+
* @returns Headers
|
|
36
|
+
*/
|
|
37
|
+
export function styleSheetHeaders(cdp) {
|
|
38
|
+
return headersByConnection.get(cdp)?.values() ?? [];
|
|
39
|
+
}
|
|
30
40
|
/**
|
|
31
41
|
* The rules that match an element, with its inline style and what its
|
|
32
42
|
* ancestors pass down, or why they are missing.
|
|
@@ -77,7 +87,7 @@ export function sourceLabel(declaration, cdp) {
|
|
|
77
87
|
const header = source.styleSheetId
|
|
78
88
|
? headersByConnection.get(cdp)?.get(source.styleSheetId)
|
|
79
89
|
: undefined;
|
|
80
|
-
return `${source.selector ?? ''} (${
|
|
90
|
+
return `${source.selector ?? ''} (${stylesheetPositionLabel(header, source.line, source.column)})`;
|
|
81
91
|
}
|
|
82
92
|
/**
|
|
83
93
|
* A stylesheet position as `file:line[:column]`.
|
|
@@ -85,17 +95,23 @@ export function sourceLabel(declaration, cdp) {
|
|
|
85
95
|
* @param header - Stylesheet header (unknown: just the line)
|
|
86
96
|
* @param line - 0-based line within the stylesheet
|
|
87
97
|
* @param column - 0-based column
|
|
88
|
-
* @returns e.g. `app.css:12`, `bootstrap.min.css:5:52628`, `<style> in index.html:40`,
|
|
98
|
+
* @returns e.g. `app.css:12`, `bootstrap.min.css:5:52628`, `<style> in index.html:40`,
|
|
99
|
+
* `constructed stylesheet`, `<style> added by a script` (a sheet a script created and
|
|
100
|
+
* filled with `insertRule`: its lines are not in any file)
|
|
89
101
|
*/
|
|
90
|
-
function
|
|
102
|
+
export function stylesheetPositionLabel(header, line, column) {
|
|
91
103
|
if (!header)
|
|
92
104
|
return line === undefined ? 'stylesheet' : `stylesheet:${line + 1}`;
|
|
93
105
|
if (header.isConstructed)
|
|
94
106
|
return 'constructed stylesheet';
|
|
95
107
|
const file = fileName(header.sourceURL) || 'page';
|
|
96
|
-
const absoluteLine = (line ?? 0) + (header.isInline ? header.startLine : 0) + 1;
|
|
97
108
|
const where = header.isInline ? `<style> in ${file}` : file;
|
|
109
|
+
if (header.isMutable && !header.sourceURL)
|
|
110
|
+
return `<style> added by a script`;
|
|
111
|
+
const absoluteLine = (line ?? 0) + (header.isInline ? header.startLine : 0) + 1;
|
|
112
|
+
const firstLine = header.isInline && (line ?? 0) === 0;
|
|
113
|
+
const absoluteColumn = (column ?? 0) + (firstLine ? header.startColumn : 0) + 1;
|
|
98
114
|
const minified = header.endLine - header.startLine < 10 && (column ?? 0) > 200;
|
|
99
|
-
return minified ? `${where}:${absoluteLine}:${
|
|
115
|
+
return minified ? `${where}:${absoluteLine}:${absoluteColumn}` : `${where}:${absoluteLine}`;
|
|
100
116
|
}
|
|
101
117
|
//# sourceMappingURL=inspectRules.js.map
|