browser-debugger-cli 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/bdg/SKILL.md +100 -186
- package/README.md +5 -4
- package/dist/commands/cdp.d.ts +22 -1
- package/dist/commands/cdp.js +100 -43
- package/dist/commands/console.d.ts +12 -0
- package/dist/commands/console.js +67 -13
- package/dist/commands/dom/DomElementResolver.d.ts +3 -1
- package/dist/commands/dom/DomElementResolver.js +10 -3
- package/dist/commands/dom/a11y.d.ts +1 -1
- package/dist/commands/dom/a11y.js +23 -22
- package/dist/commands/dom/eval.d.ts +4 -2
- package/dist/commands/dom/eval.js +31 -7
- package/dist/commands/dom/form.js +10 -9
- package/dist/commands/dom/formInteraction.js +9 -8
- package/dist/commands/dom/get.js +32 -14
- package/dist/commands/dom/helpers/index.d.ts +1 -1
- package/dist/commands/dom/helpers/index.js +1 -1
- package/dist/commands/dom/helpers/query.d.ts +27 -3
- package/dist/commands/dom/helpers/query.js +152 -64
- package/dist/commands/dom/helpers/screenshot.js +13 -13
- package/dist/commands/dom/index.js +10 -3
- package/dist/commands/dom/query.d.ts +20 -2
- package/dist/commands/dom/query.js +39 -6
- package/dist/commands/dom/screenshot.js +3 -1
- package/dist/commands/dom/semanticUtils.d.ts +3 -2
- package/dist/commands/dom/semanticUtils.js +40 -9
- package/dist/commands/helpJson.d.ts +82 -19
- package/dist/commands/helpJson.js +112 -41
- package/dist/commands/helpTopic.d.ts +16 -1
- package/dist/commands/helpTopic.js +59 -1
- package/dist/commands/installSkill.d.ts +15 -5
- package/dist/commands/installSkill.js +86 -16
- package/dist/commands/network/list.js +65 -12
- package/dist/commands/optionBehaviors.d.ts +25 -2
- package/dist/commands/optionBehaviors.js +81 -46
- package/dist/commands/peek.js +3 -0
- package/dist/commands/shared/CommandRunner.js +13 -13
- package/dist/commands/shared/daemonErrorHandler.d.ts +5 -2
- package/dist/commands/shared/daemonErrorHandler.js +21 -10
- package/dist/commands/shared/dataFetcher.d.ts +14 -4
- package/dist/commands/shared/dataFetcher.js +20 -4
- package/dist/commands/shared/followMode.d.ts +9 -1
- package/dist/commands/shared/followMode.js +22 -4
- package/dist/commands/shared/handleValidationError.js +3 -3
- package/dist/commands/shared/optionTypes.d.ts +17 -3
- package/dist/commands/shared/outputFile.js +6 -1
- package/dist/commands/shared/startHelpers.js +3 -3
- package/dist/commands/start.d.ts +7 -5
- package/dist/commands/start.js +65 -21
- package/dist/commands/stop.d.ts +11 -0
- package/dist/commands/stop.js +24 -1
- package/dist/commands.js +1 -1
- package/dist/connection/cdp.d.ts +7 -0
- package/dist/connection/cdp.js +9 -0
- package/dist/connection/chromeIdentity.d.ts +8 -2
- package/dist/connection/chromeIdentity.js +85 -13
- package/dist/connection/launcher.js +3 -2
- package/dist/constants.d.ts +29 -1
- package/dist/constants.js +35 -1
- package/dist/daemon/SessionController.js +8 -1
- package/dist/daemon/launcher.d.ts +3 -2
- package/dist/daemon/launcher.js +47 -3
- package/dist/daemon/session/Session.d.ts +5 -1
- package/dist/daemon/session/Session.js +42 -3
- package/dist/daemon/session/TelemetryStore.d.ts +15 -1
- package/dist/daemon/session/TelemetryStore.js +19 -1
- package/dist/daemon/session/commandRegistry.js +52 -18
- package/dist/daemon/session/interactions.d.ts +2 -1
- package/dist/daemon/session/interactions.js +13 -1
- package/dist/daemon/session/matchedStylesReset.d.ts +26 -0
- package/dist/daemon/session/matchedStylesReset.js +46 -0
- package/dist/daemon/session/plugins.js +17 -2
- package/dist/daemon/session/teardown.js +1 -1
- package/dist/daemon/session/triggeredRequests.d.ts +0 -5
- package/dist/daemon/session/triggeredRequests.js +13 -7
- package/dist/daemon.js +2385 -1229
- package/dist/errors/messages.d.ts +62 -11
- package/dist/errors/messages.js +119 -22
- package/dist/index.js +14995 -9866
- package/dist/ipc/client.d.ts +18 -2
- package/dist/ipc/client.js +26 -5
- package/dist/ipc/protocol/auditTypes.d.ts +8 -2
- package/dist/ipc/protocol/commands.d.ts +16 -0
- package/dist/ipc/protocol/domTypes.d.ts +12 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +7 -2
- package/dist/ipc/session/types.d.ts +7 -1
- package/dist/program.d.ts +14 -0
- package/dist/program.js +53 -0
- package/dist/runtime/dom/actionEffects.d.ts +5 -1
- package/dist/runtime/dom/actionEffects.js +26 -14
- package/dist/runtime/dom/audit.js +3 -2
- package/dist/runtime/dom/auditModel.js +6 -1
- package/dist/runtime/dom/auditScripts.d.ts +9 -3
- package/dist/runtime/dom/auditScripts.js +41 -5
- package/dist/runtime/dom/elementGeometry.d.ts +33 -3
- package/dist/runtime/dom/elementGeometry.js +44 -19
- package/dist/runtime/dom/elementInfo.d.ts +76 -18
- package/dist/runtime/dom/elementInfo.js +190 -40
- package/dist/runtime/dom/evalHelpers.d.ts +12 -2
- package/dist/runtime/dom/evalHelpers.js +67 -7
- package/dist/runtime/dom/formDiscovery.d.ts +6 -2
- package/dist/runtime/dom/formDiscovery.js +20 -3
- package/dist/runtime/dom/formFillHelpers/fill.js +7 -11
- package/dist/runtime/dom/formFillHelpers/pressKey.js +2 -2
- package/dist/runtime/dom/formFillHelpers/shared.d.ts +16 -10
- package/dist/runtime/dom/formFillHelpers/shared.js +19 -52
- package/dist/runtime/dom/formSubmitHelpers.js +4 -3
- package/dist/runtime/dom/frameLayout.js +1 -0
- package/dist/runtime/dom/frameScopedConnection.d.ts +7 -0
- package/dist/runtime/dom/frameScopedConnection.js +2 -2
- package/dist/runtime/dom/inspect.d.ts +17 -3
- package/dist/runtime/dom/inspect.js +45 -32
- package/dist/runtime/dom/inspectAllStyles.js +1 -0
- package/dist/runtime/dom/inspectHints.d.ts +1 -1
- package/dist/runtime/dom/inspectModel.d.ts +5 -4
- package/dist/runtime/dom/inspectModel.js +7 -3
- package/dist/runtime/dom/inspectPaintModel.d.ts +2 -0
- package/dist/runtime/dom/inspectPaintModel.js +3 -1
- package/dist/runtime/dom/inspectRules.d.ts +29 -3
- package/dist/runtime/dom/inspectRules.js +205 -11
- package/dist/runtime/dom/inspectScripts.d.ts +29 -2
- package/dist/runtime/dom/inspectScripts.js +49 -10
- package/dist/runtime/dom/layout.d.ts +0 -2
- package/dist/runtime/dom/layout.js +10 -9
- package/dist/runtime/dom/reactEventHelpers.d.ts +17 -4
- package/dist/runtime/dom/reactEventHelpers.js +71 -28
- package/dist/runtime/dom/targetNode.d.ts +27 -10
- package/dist/runtime/dom/targetNode.js +283 -16
- package/dist/runtime/dom/wait.js +2 -1
- package/dist/runtime/page/bdgWorld.d.ts +57 -0
- package/dist/runtime/page/bdgWorld.js +180 -0
- package/dist/runtime/page/replacedBuiltins.d.ts +28 -0
- package/dist/runtime/page/replacedBuiltins.js +136 -0
- package/dist/session/QueryCacheManager.d.ts +4 -1
- package/dist/session/QueryCacheManager.js +5 -2
- package/dist/session/chrome.d.ts +4 -1
- package/dist/session/chrome.js +7 -1
- package/dist/session/cleanup/staleSession.d.ts +21 -4
- package/dist/session/cleanup/staleSession.js +79 -9
- package/dist/session/cleanup/userCommands.d.ts +4 -1
- package/dist/session/cleanup/userCommands.js +10 -5
- package/dist/session/daemonSocket.d.ts +10 -0
- package/dist/session/daemonSocket.js +22 -0
- package/dist/session/lastSession.d.ts +6 -3
- package/dist/session/lastSession.js +11 -5
- package/dist/session/paths.d.ts +3 -1
- package/dist/session/paths.js +5 -5
- package/dist/session/portClaims.js +4 -3
- package/dist/session/sessionList.d.ts +13 -5
- package/dist/session/sessionList.js +31 -7
- package/dist/telemetry/a11y.d.ts +15 -1
- package/dist/telemetry/a11y.js +85 -2
- package/dist/telemetry/console.d.ts +2 -1
- package/dist/telemetry/console.js +30 -21
- package/dist/telemetry/har/builder.js +1 -1
- package/dist/telemetry/network.d.ts +13 -16
- package/dist/telemetry/network.js +30 -52
- package/dist/telemetry/networkRetention.d.ts +83 -0
- package/dist/telemetry/networkRetention.js +117 -0
- package/dist/telemetry/pageCrash.d.ts +26 -0
- package/dist/telemetry/pageCrash.js +53 -0
- package/dist/types.d.ts +42 -0
- package/dist/ui/OutputBuilder.d.ts +10 -0
- package/dist/ui/OutputBuilder.js +12 -0
- package/dist/ui/formatters/a11y.d.ts +5 -7
- package/dist/ui/formatters/a11y.js +7 -61
- package/dist/ui/formatters/audit.js +14 -5
- package/dist/ui/formatters/cdp.d.ts +138 -0
- package/dist/ui/formatters/cdp.js +131 -0
- package/dist/ui/formatters/console/chronological.js +7 -5
- package/dist/ui/formatters/console/follow.d.ts +5 -2
- package/dist/ui/formatters/console/follow.js +7 -4
- package/dist/ui/formatters/console/json.d.ts +4 -7
- package/dist/ui/formatters/console/json.js +16 -14
- package/dist/ui/formatters/console/shared.d.ts +47 -2
- package/dist/ui/formatters/console/shared.js +33 -0
- package/dist/ui/formatters/console/summarize.d.ts +9 -2
- package/dist/ui/formatters/console/summarize.js +57 -11
- package/dist/ui/formatters/console.d.ts +3 -2
- package/dist/ui/formatters/console.js +8 -10
- package/dist/ui/formatters/details.js +4 -2
- package/dist/ui/formatters/dom.d.ts +14 -5
- package/dist/ui/formatters/dom.js +30 -13
- package/dist/ui/formatters/helpFormatters.js +1 -1
- package/dist/ui/formatters/inspect.js +9 -3
- package/dist/ui/formatters/installSkill.d.ts +9 -1
- package/dist/ui/formatters/installSkill.js +32 -6
- package/dist/ui/formatters/layout.js +4 -2
- package/dist/ui/formatters/longValues.d.ts +14 -0
- package/dist/ui/formatters/longValues.js +23 -0
- package/dist/ui/formatters/networkList.d.ts +8 -2
- package/dist/ui/formatters/networkList.js +11 -3
- package/dist/ui/formatters/preview.d.ts +6 -1
- package/dist/ui/formatters/preview.js +67 -15
- package/dist/ui/formatters/sessions.d.ts +2 -2
- package/dist/ui/formatters/sessions.js +9 -2
- package/dist/ui/formatters/status.js +7 -0
- package/dist/ui/formatters/triggeredRequests.js +2 -1
- package/dist/ui/logging/logger.d.ts +1 -1
- package/dist/ui/messages/chrome.d.ts +20 -1
- package/dist/ui/messages/chrome.js +29 -3
- package/dist/ui/messages/commands.d.ts +153 -12
- package/dist/ui/messages/commands.js +198 -15
- package/dist/ui/messages/consoleMessages.d.ts +24 -0
- package/dist/ui/messages/consoleMessages.js +32 -0
- package/dist/ui/messages/networkMessages.d.ts +24 -0
- package/dist/ui/messages/networkMessages.js +45 -0
- package/dist/ui/messages/preview.d.ts +6 -0
- package/dist/ui/messages/preview.js +9 -1
- package/dist/ui/messages/session.d.ts +13 -2
- package/dist/ui/messages/session.js +22 -3
- package/dist/utils/directories.d.ts +34 -0
- package/dist/utils/directories.js +88 -0
- package/dist/utils/display.d.ts +16 -0
- package/dist/utils/display.js +42 -0
- package/dist/utils/exitCodes.d.ts +1 -0
- package/dist/utils/exitCodes.js +6 -0
- package/dist/utils/http.d.ts +9 -2
- package/dist/utils/http.js +4 -3
- package/dist/utils/process.d.ts +12 -0
- package/dist/utils/process.js +25 -0
- package/dist/utils/strings.d.ts +19 -0
- package/dist/utils/strings.js +16 -0
- package/package.json +2 -2
|
@@ -16,8 +16,9 @@ export interface ElementGeometry {
|
|
|
16
16
|
rect: LayoutBox;
|
|
17
17
|
/**
|
|
18
18
|
* For a zero-size element whose children show (an inline list around
|
|
19
|
-
* floated items
|
|
20
|
-
*
|
|
19
|
+
* floated items, a `display: contents` web component whose shadow root
|
|
20
|
+
* shows a dialog): the box around those children in the flat tree, which
|
|
21
|
+
* is what can be seen of it
|
|
21
22
|
*/
|
|
22
23
|
content?: LayoutBox | null;
|
|
23
24
|
/** Area its iframes and overflow-clipping ancestors leave visible, in the same coordinates */
|
|
@@ -33,6 +34,11 @@ export interface ElementGeometry {
|
|
|
33
34
|
* e.g. `opacity: 0 on div#menu`
|
|
34
35
|
*/
|
|
35
36
|
invisible: string | null;
|
|
37
|
+
/**
|
|
38
|
+
* Masked by `mask-image` on it or an ancestor ({@link MASKED_BY_JS}), e.g.
|
|
39
|
+
* `mask-image on div.hero`: part or all of it may not show
|
|
40
|
+
*/
|
|
41
|
+
masked?: string | null;
|
|
36
42
|
/** Inside an `inert` element: shown, but not interactive */
|
|
37
43
|
inert: boolean;
|
|
38
44
|
/** Fixed to the top-level viewport (it or a container is `position: fixed`): page scroll does not move it */
|
|
@@ -113,6 +119,29 @@ export declare const FRAME_OFFSET_JS = "(frame) => {\n const rect = frame.getBo
|
|
|
113
119
|
* its bounding box is the box itself, scaled.
|
|
114
120
|
*/
|
|
115
121
|
export declare const SCALES_ONLY_JS = "(style) => {\n if (style.rotate && style.rotate !== 'none') return false;\n if (!style.transform || style.transform === 'none') return true;\n const matrix = /^matrix\\(([^)]*)\\)$/.exec(style.transform);\n if (!matrix) return false;\n const values = matrix[1].split(',').map(parseFloat);\n return Math.abs(values[1]) < 1e-6 && Math.abs(values[2]) < 1e-6;\n}";
|
|
122
|
+
/**
|
|
123
|
+
* Page-side clip of a node by its ancestors in the flat tree (through the
|
|
124
|
+
* slots it is shown in and open shadow roots): the padding boxes
|
|
125
|
+
* ({@link CLIP_BOX_JS}) of those that cut off overflowing content and hold
|
|
126
|
+
* the node in their containing-block chain. An absolutely positioned node
|
|
127
|
+
* skips static ancestors (that are not transformed) up to its containing
|
|
128
|
+
* block, a fixed one is not clipped at all unless a transformed (or
|
|
129
|
+
* filtered, contained, …) ancestor holds it like an absolute one, and
|
|
130
|
+
* inline ancestors and `display: contents` ones have no box to clip with.
|
|
131
|
+
* The root element is left out (its overflow belongs to the viewport), and
|
|
132
|
+
* so is the body's overflow unless the root element's overflow is not
|
|
133
|
+
* `visible` (then the body keeps its own overflow and, e.g. as the page's
|
|
134
|
+
* scroller, clips like any container).
|
|
135
|
+
* Returns the clip, whether overlay scrollbars of the containers show along
|
|
136
|
+
* its right and bottom edges ({@link OVERLAY_SCROLLBARS_JS}), the innermost
|
|
137
|
+
* ancestor cutting off part of `rect` (null when none does), why the
|
|
138
|
+
* innermost clipping ancestor with no area (a collapsed
|
|
139
|
+
* `height: 0; overflow: hidden` accordion) hides it, e.g.
|
|
140
|
+
* `clipped by div#acc: zero height` (null when none has), and whether the
|
|
141
|
+
* node is fixed to the viewport (it or a container in its containing-block
|
|
142
|
+
* chain is `position: fixed`; `fixedBy` is that node).
|
|
143
|
+
*/
|
|
144
|
+
export declare const ANCESTOR_CLIP_JS: string;
|
|
116
145
|
/** Page-side test of a `clip-path` that cuts everything away: `inset()` with percentages leaving no area. */
|
|
117
146
|
export declare const CLIP_PATH_CUTS_ALL_JS = "(clipPath) => {\n const inset = /^inset\\(([^)]*)\\)/.exec(clipPath || '');\n const values = inset ? inset[1].split(' round ')[0].trim().split(/\\s+/) : [];\n if (values.length === 0 || values.some((v) => !/%$/.test(v))) return false;\n const [top, right = top, bottom = top, left = right] = values.map(parseFloat);\n return top + bottom >= 100 || left + right >= 100;\n}";
|
|
118
147
|
/**
|
|
@@ -126,7 +155,8 @@ export declare const CLIP_RECT_CUTS_ALL_JS = "(position, clip) => {\n if ((posi
|
|
|
126
155
|
* top-level viewport coordinates, its clip by ancestors
|
|
127
156
|
* ({@link ANCESTOR_CLIP_JS}) and by the viewports of its iframes, why it
|
|
128
157
|
* cannot be seen at all (not rendered, or inside a clipping container
|
|
129
|
-
* collapsed to zero size
|
|
158
|
+
* collapsed to zero size; a `display: contents` element is measured by
|
|
159
|
+
* its children in the flat tree and is hidden only when none shows), why a rendered one is still invisible
|
|
130
160
|
* ({@link INVISIBLE_REASON_JS}), whether it is inert (an `inert` element
|
|
131
161
|
* around it, through shadow roots) or fixed to the top-level viewport, and how
|
|
132
162
|
* far the top-level page can scroll ({@link SCROLL_RANGE_JS}) or what locks
|
|
@@ -152,28 +152,30 @@ const HOLDS_FIXED_JS = `(style) =>
|
|
|
152
152
|
/transform|filter|perspective/.test(style.willChange) || /paint|layout|strict|content/.test(style.contain)`;
|
|
153
153
|
/**
|
|
154
154
|
* Page-side test of whether a `position: fixed` node is fixed to its
|
|
155
|
-
* document's viewport (no ancestor holds it,
|
|
155
|
+
* document's viewport (no ancestor in the flat tree holds it,
|
|
156
|
+
* {@link HOLDS_FIXED_JS}).
|
|
156
157
|
*/
|
|
157
158
|
const FIXED_TO_VIEWPORT_JS = `(n) => {
|
|
158
159
|
const holdsFixed = ${HOLDS_FIXED_JS};
|
|
159
|
-
const parentOf =
|
|
160
|
+
const parentOf = ${FLAT_PARENT_JS};
|
|
160
161
|
for (let p = parentOf(n); p && p !== n.ownerDocument.documentElement; p = parentOf(p)) {
|
|
161
162
|
if (holdsFixed(p.ownerDocument.defaultView.getComputedStyle(p))) return false;
|
|
162
163
|
}
|
|
163
164
|
return true;
|
|
164
165
|
}`;
|
|
165
166
|
/**
|
|
166
|
-
* Page-side clip of a node by its ancestors
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* transformed) up to its containing
|
|
171
|
-
*
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
167
|
+
* Page-side clip of a node by its ancestors in the flat tree (through the
|
|
168
|
+
* slots it is shown in and open shadow roots): the padding boxes
|
|
169
|
+
* ({@link CLIP_BOX_JS}) of those that cut off overflowing content and hold
|
|
170
|
+
* the node in their containing-block chain. An absolutely positioned node
|
|
171
|
+
* skips static ancestors (that are not transformed) up to its containing
|
|
172
|
+
* block, a fixed one is not clipped at all unless a transformed (or
|
|
173
|
+
* filtered, contained, …) ancestor holds it like an absolute one, and
|
|
174
|
+
* inline ancestors and `display: contents` ones have no box to clip with.
|
|
175
|
+
* The root element is left out (its overflow belongs to the viewport), and
|
|
176
|
+
* so is the body's overflow unless the root element's overflow is not
|
|
177
|
+
* `visible` (then the body keeps its own overflow and, e.g. as the page's
|
|
178
|
+
* scroller, clips like any container).
|
|
177
179
|
* Returns the clip, whether overlay scrollbars of the containers show along
|
|
178
180
|
* its right and bottom edges ({@link OVERLAY_SCROLLBARS_JS}), the innermost
|
|
179
181
|
* ancestor cutting off part of `rect` (null when none does), why the
|
|
@@ -183,14 +185,14 @@ const FIXED_TO_VIEWPORT_JS = `(n) => {
|
|
|
183
185
|
* node is fixed to the viewport (it or a container in its containing-block
|
|
184
186
|
* chain is `position: fixed`; `fixedBy` is that node).
|
|
185
187
|
*/
|
|
186
|
-
const ANCESTOR_CLIP_JS = `(node, rect, describe) => {
|
|
188
|
+
export const ANCESTOR_CLIP_JS = `(node, rect, describe) => {
|
|
187
189
|
const clipBox = ${CLIP_BOX_JS};
|
|
188
190
|
const overlayScrollbars = ${OVERLAY_SCROLLBARS_JS};
|
|
189
191
|
const holdsFixed = ${HOLDS_FIXED_JS};
|
|
190
192
|
const fixedToViewport = ${FIXED_TO_VIEWPORT_JS};
|
|
191
193
|
const reasons = ${JSON.stringify(LAYOUT_REASONS)};
|
|
192
194
|
const styleOf = (n) => n.ownerDocument.defaultView.getComputedStyle(n);
|
|
193
|
-
const parentOf =
|
|
195
|
+
const parentOf = ${FLAT_PARENT_JS};
|
|
194
196
|
const doc = node.ownerDocument;
|
|
195
197
|
const rootStyle = styleOf(doc.documentElement);
|
|
196
198
|
const bodyClips = rootStyle.overflowX !== 'visible' || rootStyle.overflowY !== 'visible';
|
|
@@ -268,12 +270,28 @@ const INVISIBLE_REASON_JS = `(el, describe) => {
|
|
|
268
270
|
}
|
|
269
271
|
return null;
|
|
270
272
|
}`;
|
|
273
|
+
/**
|
|
274
|
+
* Page-side mask over an element: the nearest of it and its ancestors in the
|
|
275
|
+
* flat tree (slots, shadow hosts, iframes) with a `mask-image`. How much the
|
|
276
|
+
* mask hides is not evaluated. Null without one.
|
|
277
|
+
*/
|
|
278
|
+
const MASKED_BY_JS = `(el, describe) => {
|
|
279
|
+
const flatParent = ${FLAT_PARENT_JS};
|
|
280
|
+
const parentOf = (n) => flatParent(n) || n.ownerDocument.defaultView.frameElement || null;
|
|
281
|
+
for (let n = el; n; n = parentOf(n)) {
|
|
282
|
+
const style = n.ownerDocument.defaultView.getComputedStyle(n);
|
|
283
|
+
const mask = style.maskImage || style.webkitMaskImage;
|
|
284
|
+
if (mask && mask !== 'none') return n === el ? 'mask-image' : 'mask-image on ' + describe(n);
|
|
285
|
+
}
|
|
286
|
+
return null;
|
|
287
|
+
}`;
|
|
271
288
|
/**
|
|
272
289
|
* Page-side measurement of an element ({@link ElementGeometry}): its box in
|
|
273
290
|
* top-level viewport coordinates, its clip by ancestors
|
|
274
291
|
* ({@link ANCESTOR_CLIP_JS}) and by the viewports of its iframes, why it
|
|
275
292
|
* cannot be seen at all (not rendered, or inside a clipping container
|
|
276
|
-
* collapsed to zero size
|
|
293
|
+
* collapsed to zero size; a `display: contents` element is measured by
|
|
294
|
+
* its children in the flat tree and is hidden only when none shows), why a rendered one is still invisible
|
|
277
295
|
* ({@link INVISIBLE_REASON_JS}), whether it is inert (an `inert` element
|
|
278
296
|
* around it, through shadow roots) or fixed to the top-level viewport, and how
|
|
279
297
|
* far the top-level page can scroll ({@link SCROLL_RANGE_JS}) or what locks
|
|
@@ -292,6 +310,7 @@ export const ELEMENT_GEOMETRY_JS = `(el) => {
|
|
|
292
310
|
const scrollRange = ${SCROLL_RANGE_JS};
|
|
293
311
|
const scrollLock = ${SCROLL_LOCK_JS};
|
|
294
312
|
const invisibleReason = ${INVISIBLE_REASON_JS};
|
|
313
|
+
const maskedBy = ${MASKED_BY_JS};
|
|
295
314
|
const describe = ${ELEMENT_DESCRIPTION_JS};
|
|
296
315
|
const reasons = ${JSON.stringify(LAYOUT_REASONS)};
|
|
297
316
|
const styleOf = (node) => node.ownerDocument.defaultView.getComputedStyle(node);
|
|
@@ -311,11 +330,16 @@ export const ELEMENT_GEOMETRY_JS = `(el) => {
|
|
|
311
330
|
}
|
|
312
331
|
return 'not rendered';
|
|
313
332
|
};
|
|
333
|
+
const flatChildren = (node) =>
|
|
334
|
+
Array.from((node.shadowRoot || node).children).flatMap((c) => {
|
|
335
|
+
const shown = c.localName === 'slot' ? c.assignedElements({ flatten: true }) : [c];
|
|
336
|
+
return shown.flatMap((s) => (styleOf(s).display === 'contents' ? flatChildren(s) : [s]));
|
|
337
|
+
});
|
|
314
338
|
const shownChildren = (node) => {
|
|
315
339
|
const s = styleOf(node);
|
|
316
340
|
if (s.overflowX !== 'visible' || s.overflowY !== 'visible') return null;
|
|
317
341
|
let union = null;
|
|
318
|
-
for (const c of
|
|
342
|
+
for (const c of flatChildren(node).slice(0, 50)) {
|
|
319
343
|
const r = c.getBoundingClientRect();
|
|
320
344
|
if (r.width <= 0 || r.height <= 0 || styleOf(c).visibility !== 'visible') continue;
|
|
321
345
|
union = union
|
|
@@ -326,7 +350,7 @@ export const ELEMENT_GEOMETRY_JS = `(el) => {
|
|
|
326
350
|
};
|
|
327
351
|
const hiddenReason = (style, box, content) => {
|
|
328
352
|
if (style.display === 'none') return 'display: none';
|
|
329
|
-
if (style.display === 'contents') return 'display: contents (no box of its own)';
|
|
353
|
+
if (style.display === 'contents') return content ? null : 'display: contents (no box of its own)';
|
|
330
354
|
if (el.getClientRects().length === 0) {
|
|
331
355
|
return el.tagName === 'OPTION' ? reasons.option : 'not rendered (an ancestor has display: none)';
|
|
332
356
|
}
|
|
@@ -386,9 +410,10 @@ export const ELEMENT_GEOMETRY_JS = `(el) => {
|
|
|
386
410
|
while (top.frameElement) top = top.parent;
|
|
387
411
|
const toBox = (r) => r && { x: r.left, y: r.top, width: r.right - r.left, height: r.bottom - r.top };
|
|
388
412
|
const invisible = hidden ? null : invisibleReason(el, describe);
|
|
413
|
+
const masked = hidden || invisible ? null : maskedBy(el, describe);
|
|
389
414
|
const lock = scrollLock(top, describe);
|
|
390
415
|
if (lock && fixedBy === top.document.body) fixed = false;
|
|
391
|
-
return { rect: toBox(rect), content: toBox(content), clip: toBox(clip), clipOverlay: overlay, clipper: clipper, hidden: hidden, invisible: invisible, inert: isInert(), fixed: fixed, sticky: !fixed && isSticky(), pageScroll: scrollRange(top), scrollLock: lock, offset: { x: x, y: y } };
|
|
416
|
+
return { rect: toBox(rect), content: toBox(content), clip: toBox(clip), clipOverlay: overlay, clipper: clipper, hidden: hidden, invisible: invisible, masked: masked, inert: isInert(), fixed: fixed, sticky: !fixed && isSticky(), pageScroll: scrollRange(top), scrollLock: lock, offset: { x: x, y: y } };
|
|
392
417
|
}`;
|
|
393
418
|
/**
|
|
394
419
|
* Edges of a box.
|
|
@@ -3,6 +3,19 @@
|
|
|
3
3
|
* `dom layout`, DOM context of console messages): their text as a user sees
|
|
4
4
|
* it and where they live (iframes, shadow roots).
|
|
5
5
|
*/
|
|
6
|
+
/**
|
|
7
|
+
* Whether a class name is shown in element labels: not empty and not a
|
|
8
|
+
* fragment of a declaration-like class attribute ({@link CLASS_FRAGMENT}).
|
|
9
|
+
*
|
|
10
|
+
* @param name - Class name
|
|
11
|
+
* @returns True to show it
|
|
12
|
+
*/
|
|
13
|
+
export declare function isLabelClass(name: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Page-side `(node) => string[]`: the element's classes shown in labels
|
|
16
|
+
* ({@link isLabelClass}), read without array helpers a page may replace
|
|
17
|
+
*/
|
|
18
|
+
export declare const LABEL_CLASSES_JS: string;
|
|
6
19
|
/** Length of the text `dom get` shows for an element. */
|
|
7
20
|
export declare const ELEMENT_TEXT_LENGTH = 500;
|
|
8
21
|
/**
|
|
@@ -14,18 +27,47 @@ export declare const ELEMENT_TEXT_LENGTH = 500;
|
|
|
14
27
|
* text is removed once, from the end.
|
|
15
28
|
*/
|
|
16
29
|
export declare const WITHOUT_DECORATIONS_JS = "(el, text) => {\n if (!text || typeof el.querySelectorAll !== 'function') return text;\n const glyph = /^\\s*[\u00D7\u2715\u2716\u2717\u2A2F]\\s*$/;\n const textOf = (node) => (typeof node.innerText === 'string' ? node.innerText : node.textContent || '').trim();\n const closer = '.close, [aria-label=\"close\" i], [aria-label=\"dismiss\" i]';\n const rendered = (node) => !node.checkVisibility || node.checkVisibility();\n const found = Array.from(el.querySelectorAll(closer + ', [aria-hidden=\"true\"]'))\n .filter((node) => rendered(node) && (node.matches(closer) || !/[\\p{L}\\p{N}]/u.test(textOf(node))));\n if (/[\u00D7\u2715\u2716\u2717\u2A2F]/.test(text)) {\n found.push(...Array.from(el.querySelectorAll('button, a, [role=\"button\"]')).filter((node) => glyph.test(node.textContent || '')));\n }\n const unique = Array.from(new Set(found));\n const outermost = unique.filter((node) => !unique.some((other) => other !== node && other.contains(node)));\n let result = text;\n for (const node of outermost) {\n const part = textOf(node);\n const at = part ? result.lastIndexOf(part) : -1;\n if (at >= 0) result = result.slice(0, at) + result.slice(at + part.length);\n }\n return result;\n}";
|
|
30
|
+
/**
|
|
31
|
+
* Page-side check whether `innerText` misses part of what an element shows:
|
|
32
|
+
* it is a `<slot>` or hosts an open shadow root, or one of its descendants
|
|
33
|
+
* is or does. `innerText` follows neither shadow roots nor slots.
|
|
34
|
+
*/
|
|
35
|
+
export declare const COMPOSED_JS = "(node) => {\n const composes = (n) => Boolean(n.shadowRoot) || n.localName === 'slot';\n if (composes(node)) return true;\n const walker = node.ownerDocument.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);\n while (walker.nextNode()) if (composes(walker.currentNode)) return true;\n return false;\n}";
|
|
36
|
+
/**
|
|
37
|
+
* Page-side text of an element as the flat tree renders it, for elements
|
|
38
|
+
* `innerText` cannot read ({@link COMPOSED_JS}): a shadow host is read from
|
|
39
|
+
* its open shadow root (its own labels and fallback content; light children
|
|
40
|
+
* only where a slot shows them), and each slot is replaced by what it
|
|
41
|
+
* shows, its assigned nodes flattened through nested slots (or its fallback
|
|
42
|
+
* content when nothing is assigned). Parts without slots or shadow roots
|
|
43
|
+
* are read with `innerText`; elements that are not rendered and text under
|
|
44
|
+
* `visibility: hidden` are left out, elements that are not inline are set
|
|
45
|
+
* apart by line breaks, as is a `<br>`. Fields and editable regions inside
|
|
46
|
+
* it (inputs, textareas, selects, a contenteditable editor) are skipped, so
|
|
47
|
+
* what a user typed is never read, unless `fields` is set: then selects
|
|
48
|
+
* (all their options) and editable regions are read as `innerText` reads
|
|
49
|
+
* them (inputs and textareas it leaves out too). Raw text keeps
|
|
50
|
+
* `innerText`'s collapsed whitespace. The text is cut at `limit` characters, and a
|
|
51
|
+
* part whose text alone passes the limit is read from its text nodes
|
|
52
|
+
* (`textContent`) instead of `innerText`, which would lay out all of it.
|
|
53
|
+
*/
|
|
54
|
+
export declare const FLAT_TEXT_JS = "(el, limit, fields) => {\n const composed = (node) => {\n const composes = (n) => Boolean(n.shadowRoot) || n.localName === 'slot';\n if (composes(node)) return true;\n const walker = node.ownerDocument.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);\n while (walker.nextNode()) if (composes(walker.currentNode)) return true;\n return false;\n};\n const view = el.ownerDocument.defaultView;\n let text = '';\n const nodesOf = (node) =>\n node.localName === 'slot' ? node.assignedNodes({ flatten: true }) : Array.from((node.shadowRoot || node).childNodes);\n const read = (node, visible) => {\n if (text.length >= limit) return;\n if (node.nodeType === 3 && visible) text += node.data.replace(/\\s+/g, ' ');\n if (node.nodeType !== 1) return;\n if (/^(input|textarea)$/.test(node.localName)) return;\n if (!fields && (node.localName === 'select' || node.isContentEditable)) return;\n const style = view.getComputedStyle(node);\n if (node.checkVisibility && !node.checkVisibility() && style.display !== 'contents') return;\n if (node.localName === 'br') text += '\\n';\n const apart = style.display.startsWith('inline') || style.display === 'contents' ? '' : '\\n';\n text += apart;\n const own = node.textContent || '';\n if (composed(node)) nodesOf(node).forEach((child) => read(child, style.visibility === 'visible'));\n else if (own.length > limit - text.length) text += own.slice(0, limit - text.length);\n else text += typeof node.innerText === 'string' ? node.innerText : own;\n text += apart;\n };\n const visible = view.getComputedStyle(el).visibility === 'visible';\n nodesOf(el).forEach((child) => read(child, visible));\n return text.slice(0, limit);\n}";
|
|
17
55
|
/**
|
|
18
56
|
* Page-side text of an element as a user sees it: `innerText` for a rendered
|
|
19
57
|
* element (CSS-hidden parts left out, inline elements not split apart), none
|
|
20
58
|
* for an element that is not rendered, `textContent` for SVG and other
|
|
21
59
|
* elements without `innerText` and for `display: contents` wrappers (no box
|
|
22
60
|
* of their own, but their children are shown), and the label of an
|
|
23
|
-
* `<option>` (which its `<select>` renders).
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
61
|
+
* `<option>` (which its `<select>` renders). A web component, a slot, and
|
|
62
|
+
* an element holding either are read through the flat tree
|
|
63
|
+
* ({@link FLAT_TEXT_JS}): the text a component renders from its shadow
|
|
64
|
+
* root, slotted content in place of its slots, blocks set apart. For large
|
|
65
|
+
* containers (more than 2000 characters of text) only the start is read,
|
|
66
|
+
* from the text nodes whose parent is rendered, so a preview never lays out
|
|
67
|
+
* a whole page's text, unless `full` is set. Decorations are left out
|
|
68
|
+
* ({@link WITHOUT_DECORATIONS_JS}).
|
|
27
69
|
*/
|
|
28
|
-
export declare const ELEMENT_TEXT_JS = "(el, full) => {\n const withoutDecorations = (el, text) => {\n if (!text || typeof el.querySelectorAll !== 'function') return text;\n const glyph = /^\\s*[\u00D7\u2715\u2716\u2717\u2A2F]\\s*$/;\n const textOf = (node) => (typeof node.innerText === 'string' ? node.innerText : node.textContent || '').trim();\n const closer = '.close, [aria-label=\"close\" i], [aria-label=\"dismiss\" i]';\n const rendered = (node) => !node.checkVisibility || node.checkVisibility();\n const found = Array.from(el.querySelectorAll(closer + ', [aria-hidden=\"true\"]'))\n .filter((node) => rendered(node) && (node.matches(closer) || !/[\\p{L}\\p{N}]/u.test(textOf(node))));\n if (/[\u00D7\u2715\u2716\u2717\u2A2F]/.test(text)) {\n found.push(...Array.from(el.querySelectorAll('button, a, [role=\"button\"]')).filter((node) => glyph.test(node.textContent || '')));\n }\n const unique = Array.from(new Set(found));\n const outermost = unique.filter((node) => !unique.some((other) => other !== node && other.contains(node)));\n let result = text;\n for (const node of outermost) {\n const part = textOf(node);\n const at = part ? result.lastIndexOf(part) : -1;\n if (at >= 0) result = result.slice(0, at) + result.slice(at + part.length);\n }\n return result;\n};\n const all = el.textContent || '';\n if (el.tagName === 'OPTION') return el.label;\n if (typeof el.innerText !== 'string') return full ? all : all.slice(0, 2000);\n const rendered = (node) => !node.checkVisibility || node.checkVisibility();\n
|
|
70
|
+
export declare const ELEMENT_TEXT_JS = "(el, full) => {\n const withoutDecorations = (el, text) => {\n if (!text || typeof el.querySelectorAll !== 'function') return text;\n const glyph = /^\\s*[\u00D7\u2715\u2716\u2717\u2A2F]\\s*$/;\n const textOf = (node) => (typeof node.innerText === 'string' ? node.innerText : node.textContent || '').trim();\n const closer = '.close, [aria-label=\"close\" i], [aria-label=\"dismiss\" i]';\n const rendered = (node) => !node.checkVisibility || node.checkVisibility();\n const found = Array.from(el.querySelectorAll(closer + ', [aria-hidden=\"true\"]'))\n .filter((node) => rendered(node) && (node.matches(closer) || !/[\\p{L}\\p{N}]/u.test(textOf(node))));\n if (/[\u00D7\u2715\u2716\u2717\u2A2F]/.test(text)) {\n found.push(...Array.from(el.querySelectorAll('button, a, [role=\"button\"]')).filter((node) => glyph.test(node.textContent || '')));\n }\n const unique = Array.from(new Set(found));\n const outermost = unique.filter((node) => !unique.some((other) => other !== node && other.contains(node)));\n let result = text;\n for (const node of outermost) {\n const part = textOf(node);\n const at = part ? result.lastIndexOf(part) : -1;\n if (at >= 0) result = result.slice(0, at) + result.slice(at + part.length);\n }\n return result;\n};\n const composed = (node) => {\n const composes = (n) => Boolean(n.shadowRoot) || n.localName === 'slot';\n if (composes(node)) return true;\n const walker = node.ownerDocument.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);\n while (walker.nextNode()) if (composes(walker.currentNode)) return true;\n return false;\n};\n const flatText = (el, limit, fields) => {\n const composed = (node) => {\n const composes = (n) => Boolean(n.shadowRoot) || n.localName === 'slot';\n if (composes(node)) return true;\n const walker = node.ownerDocument.createTreeWalker(node, NodeFilter.SHOW_ELEMENT);\n while (walker.nextNode()) if (composes(walker.currentNode)) return true;\n return false;\n};\n const view = el.ownerDocument.defaultView;\n let text = '';\n const nodesOf = (node) =>\n node.localName === 'slot' ? node.assignedNodes({ flatten: true }) : Array.from((node.shadowRoot || node).childNodes);\n const read = (node, visible) => {\n if (text.length >= limit) return;\n if (node.nodeType === 3 && visible) text += node.data.replace(/\\s+/g, ' ');\n if (node.nodeType !== 1) return;\n if (/^(input|textarea)$/.test(node.localName)) return;\n if (!fields && (node.localName === 'select' || node.isContentEditable)) return;\n const style = view.getComputedStyle(node);\n if (node.checkVisibility && !node.checkVisibility() && style.display !== 'contents') return;\n if (node.localName === 'br') text += '\\n';\n const apart = style.display.startsWith('inline') || style.display === 'contents' ? '' : '\\n';\n text += apart;\n const own = node.textContent || '';\n if (composed(node)) nodesOf(node).forEach((child) => read(child, style.visibility === 'visible'));\n else if (own.length > limit - text.length) text += own.slice(0, limit - text.length);\n else text += typeof node.innerText === 'string' ? node.innerText : own;\n text += apart;\n };\n const visible = view.getComputedStyle(el).visibility === 'visible';\n nodesOf(el).forEach((child) => read(child, visible));\n return text.slice(0, limit);\n};\n const all = el.textContent || '';\n if (el.tagName === 'OPTION') return el.label;\n if (typeof el.innerText !== 'string') return full ? all : all.slice(0, 2000);\n const rendered = (node) => !node.checkVisibility || node.checkVisibility();\n const shown = rendered(el);\n const boxless = !shown && el.ownerDocument.defaultView.getComputedStyle(el).display === 'contents';\n if (!shown && !boxless) return '';\n if (composed(el)) return withoutDecorations(el, flatText(el, full ? Infinity : 2000));\n if (boxless) return withoutDecorations(el, full ? all : all.slice(0, 2000));\n if (full || all.length <= 2000) return withoutDecorations(el, el.innerText);\n const walker = el.ownerDocument.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n let start = '';\n while (start.length < 1000 && walker.nextNode()) {\n const parent = walker.currentNode.parentElement;\n if (!parent || rendered(parent)) start += walker.currentNode.data;\n }\n return withoutDecorations(el, start);\n}";
|
|
29
71
|
/** Shown instead of a secret field value (the same for every length) */
|
|
30
72
|
export declare const MASKED_VALUE = "\u2022\u2022\u2022\u2022";
|
|
31
73
|
/**
|
|
@@ -53,26 +95,40 @@ export declare const SENSITIVE_FIELD_JS = "(el) => {\n const autocomplete = el.
|
|
|
53
95
|
*/
|
|
54
96
|
export declare const ELEMENT_STATE_JS = "(el) => {\n const isSensitive = (el) => {\n const autocomplete = el.getAttribute('autocomplete') || '';\n if (/(^|\\s)(cc-[a-z-]+|one-time-code|current-password|new-password)(\\s|$)/i.test(autocomplete)) return true;\n if (el.type === 'password' || /^password$/i.test(el.getAttribute('type') || '')) return true;\n const names = [el.getAttribute('name'), el.id, autocomplete].join(' ');\n if (/passw|passwd|pwd|passcode|(^|[^a-z])otp([^a-z]|$)|cvv|cvc/i.test(names)) return true;\n try {\n const security = el.ownerDocument.defaultView.getComputedStyle(el).getPropertyValue('-webkit-text-security');\n return Boolean(security) && security !== 'none';\n } catch (e) {\n return false;\n }\n};\n const mask = (value) => (value ? '\u2022\u2022\u2022\u2022' : '');\n const guarded = (state) => {\n if (!isSensitive(el)) return state;\n const result = { ...state, sensitive: true };\n if ('value' in result) result.value = mask(result.value);\n if ('selected' in result) result.selected = mask(result.selected);\n return result;\n };\n switch (el.localName) {\n case 'input':\n if (el.type === 'hidden') return { type: 'hidden' };\n return guarded(\n /^(checkbox|radio)$/.test(el.type)\n ? { type: el.type, checked: el.checked, value: el.getAttribute('value') || '' }\n : { type: el.type, value: el.value }\n );\n case 'textarea':\n return guarded({ value: el.value });\n case 'select':\n return guarded({ selected: Array.from(el.selectedOptions || [], (option) => option.label).join(', ') });\n case 'button':\n return el.form ? { type: el.type } : {};\n default:\n return {};\n }\n}";
|
|
55
97
|
/**
|
|
56
|
-
* Page-side short description of an element: tag, id and up to two classes
|
|
57
|
-
* e.g. `button#save.primary.large`.
|
|
98
|
+
* Page-side short description of an element: tag, id and up to two classes
|
|
99
|
+
* ({@link LABEL_CLASSES_JS}), e.g. `button#save.primary.large`.
|
|
100
|
+
*/
|
|
101
|
+
export declare const ELEMENT_DESCRIPTION_JS: string;
|
|
102
|
+
/**
|
|
103
|
+
* Page-side reason an element is disabled, or null when it is not. A native
|
|
104
|
+
* control (`button`, `input`, `select`, `textarea`, `fieldset`, `optgroup`,
|
|
105
|
+
* `option`) is disabled by its `disabled attribute` or by being `inside a
|
|
106
|
+
* disabled <fieldset>` (not in its first `<legend>`), an `<option>` by
|
|
107
|
+
* being `inside a disabled <optgroup>`; any other element
|
|
108
|
+
* (e.g. a custom element) when its `disabled` property is set (empty
|
|
109
|
+
* reason). Reads the element's own attributes rather than
|
|
110
|
+
* `matches(':disabled')`, which pages replace.
|
|
58
111
|
*/
|
|
59
|
-
export declare const
|
|
112
|
+
export declare const DISABLED_CAUSE_JS = "(el) => {\n if (!/^(button|input|select|textarea|fieldset|optgroup|option)$/.test(el.localName)) return el.disabled ? '' : null;\n if (el.hasAttribute('disabled')) return 'disabled attribute';\n if (el.localName === 'option') {\n const group = el.parentElement;\n return group && group.localName === 'optgroup' && group.hasAttribute('disabled') ? 'inside a disabled <optgroup>' : null;\n }\n for (let node = el.parentElement; node; node = node.parentElement) {\n if (node.localName !== 'fieldset' || !node.hasAttribute('disabled')) continue;\n let legend = node.firstElementChild;\n while (legend && legend.localName !== 'legend') legend = legend.nextElementSibling;\n if (!legend || !legend.contains(el)) return 'inside a disabled <fieldset>';\n }\n return null;\n}";
|
|
60
113
|
/**
|
|
61
114
|
* Page-side position of an element among its parent's children with the
|
|
62
115
|
* same short description ({@link ELEMENT_DESCRIPTION_JS}), e.g. `(2nd of 3)`;
|
|
63
116
|
* empty when it is the only one.
|
|
64
117
|
*/
|
|
65
|
-
export declare const SIBLING_POSITION_JS
|
|
118
|
+
export declare const SIBLING_POSITION_JS: string;
|
|
66
119
|
/**
|
|
67
120
|
* Page-side identity of an element an action hit, so the output says which
|
|
68
121
|
* one it was, as one string: its short description
|
|
69
122
|
* ({@link ELEMENT_DESCRIPTION_JS}) and visible text (button value for button
|
|
70
|
-
* inputs, decorations left out
|
|
71
|
-
*
|
|
123
|
+
* inputs, decorations left out; read through the flat tree for web
|
|
124
|
+
* components and slots, {@link FLAT_TEXT_JS}), e.g.
|
|
125
|
+
* `button#add.btn "Add to cart"`. A `<select>` is named by its label
|
|
126
|
+
* (`aria-labelledby` or `<label>`), aria-label or name, else by its selected
|
|
72
127
|
* option, e.g. `select.sort "Sort products"`. An element without visible
|
|
73
128
|
* text is described by itself first: by its position among same-looking
|
|
74
129
|
* siblings ({@link SIBLING_POSITION_JS}), e.g. `div.figure (2nd of 3)`, with
|
|
75
|
-
* its
|
|
130
|
+
* its name when it has one: aria-label, label, placeholder, title, or the
|
|
131
|
+
* alt text of an image (in it). Only an element
|
|
76
132
|
* without an id that is the only one of its kind is named by the nearest of
|
|
77
133
|
* three ancestors that has text, e.g.
|
|
78
134
|
* `input.toggle in div.view "Write report"` (rows of a list share their
|
|
@@ -80,18 +136,20 @@ export declare const SIBLING_POSITION_JS = "(el) => {\n const describe = (node)
|
|
|
80
136
|
* of `<select>`s in it (read like `innerText`: CSS-hidden text is left out of
|
|
81
137
|
* a rendered ancestor; at most 500 text nodes; selects in shadow roots are
|
|
82
138
|
* not looked into), and never past an editable ancestor, whose text may be
|
|
83
|
-
* typed input; otherwise its
|
|
139
|
+
* typed input; otherwise its name is used. Texts
|
|
84
140
|
* are cut at 40 characters. Contenteditable elements count as controls: what
|
|
85
141
|
* was typed into them is never echoed (nor their ancestors' text).
|
|
86
142
|
*/
|
|
87
|
-
export declare const ELEMENT_IDENTITY_JS
|
|
143
|
+
export declare const ELEMENT_IDENTITY_JS: string;
|
|
88
144
|
/**
|
|
89
145
|
* Page-side location of an element: the iframes it is in (outermost first)
|
|
90
|
-
* and the shadow root holding it, with the host's first class and
|
|
91
|
-
*
|
|
92
|
-
*
|
|
146
|
+
* and the shadow root holding it, with the host's first class and the text
|
|
147
|
+
* a user sees of it ({@link ELEMENT_TEXT_JS}, cut at 30 characters with
|
|
148
|
+
* `…`), e.g. `iframe#pay > shadow root of <sl-button.primary "Save">`;
|
|
149
|
+
* empty for the main document. Each host's text is read once per script
|
|
150
|
+
* run, as many matches share a host.
|
|
93
151
|
*/
|
|
94
|
-
export declare const ELEMENT_CONTEXT_JS
|
|
152
|
+
export declare const ELEMENT_CONTEXT_JS: string;
|
|
95
153
|
/**
|
|
96
154
|
* Short text preview of an element's text: whitespace collapsed, cut on a
|
|
97
155
|
* whole character (an emoji is never split, which would make JSON invalid).
|