browser-debugger-cli 0.11.0 → 0.12.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/README.md +142 -79
- package/dist/commands/css.d.ts +13 -0
- package/dist/commands/css.js +53 -0
- package/dist/commands/dom/audit.d.ts +14 -0
- package/dist/commands/dom/audit.js +87 -0
- package/dist/commands/dom/formInteraction.js +36 -6
- package/dist/commands/dom/helpers/keyAttributes.d.ts +3 -2
- package/dist/commands/dom/helpers/keyAttributes.js +6 -4
- package/dist/commands/dom/helpers/screenshot.d.ts +1 -0
- package/dist/commands/dom/helpers/screenshot.js +158 -38
- package/dist/commands/dom/index.js +4 -1
- package/dist/commands/dom/screenshot.js +10 -6
- package/dist/commands/dom/wait.js +5 -3
- package/dist/commands/helpJson.js +1 -1
- package/dist/commands/optionBehaviors.js +21 -6
- 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/optionTypes.d.ts +5 -1
- package/dist/commands/start.d.ts +13 -0
- package/dist/commands/start.js +19 -2
- package/dist/commands/tail.d.ts +7 -1
- package/dist/commands/tail.js +13 -62
- package/dist/commands.js +2 -0
- package/dist/daemon/session/commandRegistry.js +7 -1
- package/dist/daemon/session/plugins.js +4 -52
- package/dist/daemon.js +7986 -6848
- package/dist/errors/messages.d.ts +34 -4
- package/dist/errors/messages.js +68 -5
- package/dist/index.js +610 -186
- package/dist/ipc/client.d.ts +4 -0
- package/dist/ipc/client.js +8 -0
- package/dist/ipc/protocol/auditTypes.d.ts +129 -0
- package/dist/ipc/protocol/auditTypes.js +6 -0
- package/dist/ipc/protocol/commands.d.ts +23 -0
- package/dist/ipc/protocol/commands.js +2 -0
- package/dist/ipc/protocol/domTypes.d.ts +4 -0
- package/dist/ipc/protocol/inspectTypes.d.ts +71 -8
- package/dist/runtime/css/search.d.ts +39 -0
- package/dist/runtime/css/search.js +122 -0
- package/dist/runtime/dom/actionEffects.d.ts +4 -1
- package/dist/runtime/dom/actionEffects.js +8 -4
- package/dist/runtime/dom/audit.d.ts +19 -0
- package/dist/runtime/dom/audit.js +36 -0
- package/dist/runtime/dom/auditModel.d.ts +45 -0
- package/dist/runtime/dom/auditModel.js +215 -0
- package/dist/runtime/dom/auditScripts.d.ts +107 -0
- package/dist/runtime/dom/auditScripts.js +112 -0
- package/dist/runtime/dom/elementGeometry.d.ts +8 -2
- package/dist/runtime/dom/elementGeometry.js +24 -8
- package/dist/runtime/dom/elementInfo.d.ts +3 -2
- package/dist/runtime/dom/elementInfo.js +8 -2
- package/dist/runtime/dom/formFillHelpers/fill.js +2 -2
- package/dist/runtime/dom/inspect.d.ts +7 -0
- package/dist/runtime/dom/inspect.js +88 -23
- package/dist/runtime/dom/inspectAllStyles.d.ts +16 -4
- package/dist/runtime/dom/inspectAllStyles.js +89 -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 +3 -0
- package/dist/runtime/dom/inspectModel.js +30 -7
- package/dist/runtime/dom/inspectPaintModel.d.ts +48 -22
- package/dist/runtime/dom/inspectPaintModel.js +180 -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 +85 -12
- package/dist/runtime/dom/inspectScripts.js +314 -28
- 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 +31 -9
- package/dist/runtime/dom/reactEventHelpers.d.ts +7 -0
- package/dist/runtime/dom/reactEventHelpers.js +27 -9
- package/dist/runtime/page/emulation.d.ts +13 -4
- package/dist/runtime/page/emulation.js +69 -4
- package/dist/runtime/page/userAgent.d.ts +17 -0
- package/dist/runtime/page/userAgent.js +57 -0
- package/dist/types.d.ts +4 -0
- package/dist/ui/formatters/audit.d.ts +19 -0
- package/dist/ui/formatters/audit.js +106 -0
- package/dist/ui/formatters/dom.d.ts +1 -1
- package/dist/ui/formatters/dom.js +6 -3
- package/dist/ui/formatters/inspect.js +42 -15
- package/dist/ui/formatters/status.js +1 -1
- package/dist/ui/messages/commands.d.ts +44 -7
- package/dist/ui/messages/commands.js +83 -11
- package/dist/ui/messages/preview.d.ts +6 -0
- package/dist/ui/messages/preview.js +9 -1
- package/dist/utils/cssValues.js +36 -4
- package/dist/utils/decisionTrees.js +0 -5
- 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
|
@@ -26,6 +26,10 @@ export interface RawTreeNode {
|
|
|
26
26
|
display: string;
|
|
27
27
|
/** Text of an element without block-level children */
|
|
28
28
|
text?: string;
|
|
29
|
+
/** Reached through a slot or a `display: contents` wrapper (`slot.label`, `div.row (contents)`) */
|
|
30
|
+
via?: string;
|
|
31
|
+
/** In the shadow root of its parent */
|
|
32
|
+
shadow?: boolean;
|
|
29
33
|
children?: RawTreeNode[];
|
|
30
34
|
/** Rendered element children (at the depth limit) */
|
|
31
35
|
childCount?: number;
|
|
@@ -38,6 +42,15 @@ export interface RawBackground {
|
|
|
38
42
|
color: string;
|
|
39
43
|
/** Has a background image or gradient */
|
|
40
44
|
image: boolean;
|
|
45
|
+
/** Its own opacity, below 1 (it fades its background and everything inside it) */
|
|
46
|
+
opacity?: number;
|
|
47
|
+
}
|
|
48
|
+
/** A rule that would set a property if its `@media`/`@supports` condition applied */
|
|
49
|
+
export interface InactiveRule {
|
|
50
|
+
selector: string;
|
|
51
|
+
/** e.g. `@media (max-width: 600px)` */
|
|
52
|
+
condition: string;
|
|
53
|
+
value: string;
|
|
41
54
|
}
|
|
42
55
|
/** What {@link INSPECT_PAGE_JS} returns */
|
|
43
56
|
export interface RawInspect {
|
|
@@ -56,15 +69,31 @@ export interface RawInspect {
|
|
|
56
69
|
style: string;
|
|
57
70
|
weight: string;
|
|
58
71
|
};
|
|
59
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Has text to describe: a text field or select, its own text where most
|
|
74
|
+
* of its text is, or only inline content with text
|
|
75
|
+
*/
|
|
60
76
|
textual: boolean;
|
|
61
77
|
formControl: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Label of the descendant that draws most of the text (`abbr`,
|
|
80
|
+
* `slot.button__label`) when it is not the element itself; its styles are
|
|
81
|
+
* the text's
|
|
82
|
+
*/
|
|
83
|
+
textHolder?: string;
|
|
84
|
+
/** Its text (the element, or the descendant that draws it) has a box and is not `visibility: hidden` */
|
|
85
|
+
rendered: boolean;
|
|
86
|
+
/** Visible text is drawn in it (or it is a text field or select) */
|
|
87
|
+
hasText: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* The first family of the text's `font-family` is a web font (`@font-face`)
|
|
90
|
+
* the page loaded: whatever name the font file gives, it is not a fallback
|
|
91
|
+
*/
|
|
92
|
+
familyLoaded?: boolean;
|
|
62
93
|
/** Replaced element (img, svg and its shapes, video, canvas, iframe, embed, object, form controls): sized by its content */
|
|
63
94
|
replaced?: boolean;
|
|
64
95
|
/** An SVG element (SVG properties are not noise for it) */
|
|
65
96
|
svg?: boolean;
|
|
66
|
-
/** A text node is a direct child (the rendered font is read from the element itself) */
|
|
67
|
-
ownText: boolean;
|
|
68
97
|
/** Computed (not resolved) width and height: `auto`, `200px`, `50%`, … */
|
|
69
98
|
typed: {
|
|
70
99
|
width: string;
|
|
@@ -86,6 +115,8 @@ export interface RawInspect {
|
|
|
86
115
|
left?: number;
|
|
87
116
|
right?: number;
|
|
88
117
|
};
|
|
118
|
+
/** Its text is cut off: clipped by `overflow` (ellipsis or not) or by a line clamp, on it or its text holder */
|
|
119
|
+
truncated?: boolean;
|
|
89
120
|
/** Content size when it overflows the box */
|
|
90
121
|
scroll?: {
|
|
91
122
|
w: number;
|
|
@@ -99,6 +130,12 @@ export interface RawInspect {
|
|
|
99
130
|
canvasDark: boolean;
|
|
100
131
|
/** Opacity of the element times that of its ancestors */
|
|
101
132
|
opacity?: number;
|
|
133
|
+
/**
|
|
134
|
+
* What makes the text's contrast approximate: blend modes and filters on
|
|
135
|
+
* it or its ancestors, painted content behind it that is not an ancestor
|
|
136
|
+
* (a canvas, a positioned layer) or on top of it
|
|
137
|
+
*/
|
|
138
|
+
paintRisks?: string[];
|
|
102
139
|
tree?: RawTreeNode[];
|
|
103
140
|
hiddenChildren: number;
|
|
104
141
|
/** Children the walk did not reach ({@link TREE_NODE_CAP}) */
|
|
@@ -109,24 +146,60 @@ export interface RawInspect {
|
|
|
109
146
|
* given per side, e.g. `top 1px solid … / right 0px none …`
|
|
110
147
|
*/
|
|
111
148
|
props?: Record<string, string>;
|
|
149
|
+
/** Font size of the root element (px), for rem custom properties in `--props` */
|
|
150
|
+
rootFontSize?: number;
|
|
112
151
|
/** `--props` names the browser does not know as CSS properties */
|
|
113
152
|
unknownProps?: string[];
|
|
114
|
-
/**
|
|
153
|
+
/** The `--why` property is not a CSS property */
|
|
154
|
+
unknownWhy?: boolean;
|
|
155
|
+
/** Longhands of the `--why` property when it is a shorthand (as the browser expands it) */
|
|
156
|
+
whyLonghands?: string[];
|
|
157
|
+
/** Computed value of the `--why` shorthand (`getComputedStyle` writes it as one value) */
|
|
158
|
+
whyComputed?: string;
|
|
159
|
+
/** Rules for the element that set the `--why` property under a condition that does not apply now */
|
|
160
|
+
whyInactive?: InactiveRule[];
|
|
161
|
+
/** Properties of running CSS transitions, and names of running animations (time-based: scroll-driven ones do not change on their own) */
|
|
115
162
|
animating: string[];
|
|
116
163
|
}
|
|
117
164
|
/**
|
|
118
165
|
* Page-side function run on the element (`this`), see {@link RawInspect}.
|
|
119
|
-
* Arguments: tree depth,
|
|
120
|
-
* (or null).
|
|
166
|
+
* Arguments: tree depth, the property names asked for with `--props` (or
|
|
167
|
+
* null) and the `--why` property (or null).
|
|
121
168
|
*/
|
|
122
|
-
export declare const INSPECT_PAGE_JS = "function (depth, props) {\n const el = this;\n const view = el.ownerDocument.defaultView;\n const tree = ((view) => {\n const style = (n, pseudo) => view.getComputedStyle(n, pseudo);\n const skipped = /^(script|style|template|link|meta|noscript|title|head|base)$/;\n const flatParent = (n) => n.assignedSlot || n.parentElement || (n.parentNode && n.parentNode.host) || null;\n const layoutParent = (n) => {\n let p = flatParent(n);\n while (p && style(p).display === 'contents') p = flatParent(p);\n return p;\n };\n const children = (n) => {\n const out = [];\n const add = (c) => {\n if (skipped.test(c.localName)) return;\n if (c.localName === 'slot') {\n const assigned = c.assignedElements({ flatten: true });\n (assigned.length ? assigned : Array.from(c.children)).forEach(add);\n } else if (style(c).display === 'contents') {\n Array.from((c.shadowRoot || c).children).forEach(add);\n } else {\n out.push(c);\n }\n };\n Array.from((n.shadowRoot || n).children).forEach(add);\n return out;\n };\n const rendered = (n) => n.getClientRects().length > 0 &&\n (!n.checkVisibility || n.checkVisibility({ visibilityProperty: true }));\n const container = (n) => children(n).some((c) => rendered(c) && !/^inline/.test(style(c).display));\n return { style, flatParent, layoutParent, children, rendered, container };\n})(view);\n const textOf = (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 clean = (text) => String(text || '').replace(/\\s+/g, ' ').trim().slice(0, 200);\n if (el.localName === 'input' && el.type === 'hidden') return '';\n if (el.localName === 'input' || el.localName === 'textarea') {\n return el.value && isSensitive(el) ? '\u2022\u2022\u2022\u2022' : clean(el.value);\n }\n if (el.localName === 'select') {\n const chosen = clean(Array.from(el.selectedOptions || [], (o) => o.label).join(', '));\n return chosen && isSensitive(el) ? '\u2022\u2022\u2022\u2022' : chosen;\n }\n const outsideControls = () => {\n const parts = [];\n const walker = el.ownerDocument.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n for (let n = walker.nextNode(); n && parts.length < 400; n = walker.nextNode()) {\n const holder = n.parentElement;\n if (!holder || holder.closest('select, textarea, script, style, template, noscript')) continue;\n if (holder.checkVisibility && !holder.checkVisibility({ visibilityProperty: true })) continue;\n parts.push(n.data);\n }\n return parts.join(' ');\n };\n const holdsControls = Boolean(el.querySelector && el.querySelector('select, textarea'));\n const raw = holdsControls ? outsideControls() : typeof el.innerText === 'string' ? el.innerText : el.textContent;\n const text = clean(raw);\n const view = el.ownerDocument.defaultView;\n const security = view ? view.getComputedStyle(el).getPropertyValue('-webkit-text-security') : '';\n return text && security && security !== 'none' ? '\u2022\u2022\u2022\u2022' : text;\n};\n const describe = (node) => node.tagName.toLowerCase() +\n (node.id ? '#' + node.id : '') +\n (node.classList && node.classList.length ? '.' + Array.from(node.classList).slice(0, 2).join('.') : '');\n const s = tree.style(el);\n const formControl = /^(input|textarea|select|button)$/.test(el.localName);\n const content = textOf(el);\n const parent = tree.layoutParent(el);\n const typedMap = el.computedStyleMap ? el.computedStyleMap() : null;\n const typed = (name) => { try { return typedMap ? String(typedMap.get(name)) : ''; } catch (e) { return ''; } };\n const result = {\n tag: el.localName,\n id: el.id || '',\n classes: el.classList ? Array.from(el.classList) : [],\n context: ((el) => {\n const describe = (node) => node.tagName.toLowerCase() + (node.id ? '#' + node.id : '');\n const parts = [];\n for (let doc = el.ownerDocument; doc && doc.defaultView && doc.defaultView.frameElement; ) {\n const frame = doc.defaultView.frameElement;\n parts.unshift(describe(frame));\n doc = frame.ownerDocument;\n }\n const root = el.getRootNode();\n if (root.host) parts.push('shadow root of <' + describe(root.host) + '>');\n return parts.join(' > ');\n})(el),\n content: content,\n textual: formControl || (content !== '' && !tree.container(el)),\n formControl: formControl,\n replaced: el instanceof SVGElement || /^(img|video|canvas|iframe|embed|object|input|textarea|select|button|meter|progress)$/.test(el.localName),\n svg: el.namespaceURI === 'http://www.w3.org/2000/svg',\n ownText: Array.from(el.childNodes).some((n) => n.nodeType === 3 && n.data.trim() !== ''),\n typed: { width: typed('width'), height: typed('height') },\n parent: parent ? describe(parent) : undefined,\n animating: el.getAnimations ? [...new Set(el.getAnimations().filter((a) => a.playState === 'running').map((a) => a.transitionProperty || a.animationName || 'animation'))] : []\n };\n if (/^(input|textarea)$/.test(el.localName) && el.placeholder && !el.value) {\n result.placeholder = el.placeholder.replace(/\\s+/g, ' ').trim();\n const placeholderStyle = tree.style(el, '::placeholder');\n result.placeholderColor = placeholderStyle.color;\n result.placeholderFont = { style: placeholderStyle.fontStyle, weight: placeholderStyle.fontWeight };\n }\n if (el.clientWidth > 0 && (el.scrollWidth > el.clientWidth + 1 || el.scrollHeight > el.clientHeight + 1)) {\n result.scroll = { w: el.scrollWidth, h: el.scrollHeight, clientW: el.clientWidth, clientH: el.clientHeight };\n }\n if (props) {\n const known = (name) => name.startsWith('--') || CSS.supports(name, 'inherit');\n const valueOf = (name) => {\n const value = s.getPropertyValue(name).trim();\n if (value !== '' || name.startsWith('--')) return value;\n const sides = ['top', 'right', 'bottom', 'left'].map((side) => name + '-' + side).filter(known);\n return sides.map((side) => side.slice(name.length + 1) + ' ' + s.getPropertyValue(side).trim()).join(' / ');\n };\n result.props = Object.fromEntries(props.filter(known).map((name) => [name, valueOf(name)]));\n result.unknownProps = props.filter((name) => !known(name));\n }\n return Object.assign(result,\n ((el, tree) => {\n const parent = tree.layoutParent(el);\n if (!parent || tree.style(el).position === 'fixed' || !tree.rendered(el)) return {};\n const r = el.getBoundingClientRect();\n const p = parent.getBoundingClientRect();\n const ps = tree.style(parent);\n const edge = (side) => parseFloat(ps['border-' + side + '-width']) + parseFloat(ps['padding-' + side]);\n const inParent = {\n left: r.left - (p.left + edge('left')),\n top: r.top - (p.top + edge('top')),\n right: (p.right - edge('right')) - r.right,\n bottom: (p.bottom - edge('bottom')) - r.bottom\n };\n const inFlow = (n) => n !== el && tree.rendered(n) && !/^(absolute|fixed)$/.test(tree.style(n).position);\n const siblings = tree.children(parent);\n const at = siblings.indexOf(el);\n const before = siblings.slice(0, Math.max(at, 0)).reverse().find(inFlow);\n const after = at < 0 ? undefined : siblings.slice(at + 1).find(inFlow);\n const gaps = {};\n for (const sibling of [before, after]) {\n if (!sibling) continue;\n const s = sibling.getBoundingClientRect();\n if (s.bottom <= r.top + 0.5) gaps.top = r.top - s.bottom;\n else if (s.top >= r.bottom - 0.5) gaps.bottom = s.top - r.bottom;\n else if (s.right <= r.left + 0.5) gaps.left = r.left - s.right;\n else if (s.left >= r.right - 0.5) gaps.right = s.left - r.right;\n }\n return { inParent: inParent, siblings: gaps };\n})(el, tree),\n ((el, tree, view) => {\n const backgrounds = [];\n let opacity = 1;\n for (let n = el; n && backgrounds.length < 60; n = tree.flatParent(n)) {\n const s = tree.style(n);\n backgrounds.push({ color: s.backgroundColor, image: s.backgroundImage !== 'none' });\n opacity *= Number(s.opacity) || 0;\n }\n const doc = el.ownerDocument;\n const meta = doc.querySelector('meta[name=\"color-scheme\"]');\n const rootScheme = tree.style(doc.documentElement).colorScheme;\n const scheme = rootScheme && rootScheme !== 'normal' ? rootScheme : (meta && meta.content) || '';\n const prefersDark = view.matchMedia('(prefers-color-scheme: dark)').matches;\n const canvasDark = /dark/.test(scheme) && (!/light/.test(scheme) || prefersDark);\n return { backgrounds: backgrounds, canvasDark: canvasDark, opacity: opacity };\n})(el, tree, view),\n ((el, tree, textOf, depth) => {\n let budget = 400;\n let skipped = 0;\n const labelOf = (n) => n.localName + (n.id ? '#' + n.id : n.classList && n.classList.length ? '.' + n.classList[0] : '');\n const walk = (kids, level, origin) => {\n const shown = kids.filter(tree.rendered);\n const nodes = [];\n for (const k of shown) {\n if (budget <= 0) { skipped++; continue; }\n budget--;\n nodes.push(nodeOf(k, level, origin));\n }\n return { nodes: nodes, hidden: kids.length - shown.length };\n };\n const nodeOf = (n, level, origin) => {\n const r = n.getBoundingClientRect();\n const node = { label: labelOf(n), x: r.left - origin.left, y: r.top - origin.top, w: r.width, h: r.height, display: tree.style(n).display };\n const kids = tree.children(n);\n if (!tree.container(n)) node.text = textOf(n).slice(0, 60);\n if (level >= depth) {\n node.childCount = kids.filter(tree.rendered).length;\n return node;\n }\n const sub = walk(kids, level + 1, r);\n node.children = sub.nodes;\n node.hidden = sub.hidden;\n return node;\n };\n if (depth <= 0) return { hiddenChildren: 0, treeSkipped: 0 };\n const top = walk(tree.children(el), 1, el.getBoundingClientRect());\n return { tree: top.nodes, hiddenChildren: top.hidden, treeSkipped: skipped };\n})(el, tree, textOf, depth));\n}";
|
|
169
|
+
export declare const INSPECT_PAGE_JS = "function (depth, props, why) {\n const el = this;\n const view = el.ownerDocument.defaultView;\n const tree = ((view) => {\n const style = (n, pseudo) => view.getComputedStyle(n, pseudo);\n const skipped = /^(script|style|template|link|meta|noscript|title|head|base)$/;\n const flatParent = (n) => n.assignedSlot || n.parentElement || (n.parentNode && n.parentNode.host) || null;\n const layoutParent = (n) => {\n let p = flatParent(n);\n while (p && style(p).display === 'contents') p = flatParent(p);\n return p;\n };\n const via = new WeakMap();\n const label = (n) => n.localName + (n.id ? '#' + n.id : n.classList && n.classList.length ? '.' + n.classList[0] : '');\n const slotText = (slot) => slot.assignedNodes({ flatten: true }).some((t) => t.nodeType === 3 && t.data.trim() !== '');\n const children = (n) => {\n const out = [];\n const add = (c, through) => {\n if (skipped.test(c.localName)) return;\n if (c.localName === 'slot') {\n const assigned = c.assignedElements({ flatten: true });\n if (assigned.length === 0 && slotText(c)) out.push(c);\n else (assigned.length ? assigned : Array.from(c.children)).forEach((a) => add(a, label(c)));\n } else if (style(c).display === 'contents') {\n Array.from((c.shadowRoot || c).children).forEach((a) => add(a, label(c) + ' (contents)'));\n } else {\n if (through) via.set(c, through);\n out.push(c);\n }\n };\n Array.from((n.shadowRoot || n).children).forEach((c) => add(c, null));\n return out;\n };\n const rendered = (n) => n.getClientRects().length > 0 &&\n (!n.checkVisibility || n.checkVisibility({ visibilityProperty: true }));\n const container = (n) => children(n).some((c) => rendered(c) && !/^inline/.test(style(c).display));\n return { style, skipped, flatParent, layoutParent, children, rendered, container, label, via, slotText };\n})(view);\n const textOf = (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 clean = (text) => String(text || '').replace(/\\s+/g, ' ').trim().slice(0, 200);\n if (el.localName === 'input' && el.type === 'hidden') return '';\n if (el.localName === 'input' || el.localName === 'textarea') {\n return el.value && isSensitive(el) ? '\u2022\u2022\u2022\u2022' : clean(el.value);\n }\n if (el.localName === 'select') {\n const chosen = clean(Array.from(el.selectedOptions || [], (o) => o.label).join(', '));\n return chosen && isSensitive(el) ? '\u2022\u2022\u2022\u2022' : chosen;\n }\n const outsideControls = () => {\n const parts = [];\n const walker = el.ownerDocument.createTreeWalker(el, NodeFilter.SHOW_TEXT);\n for (let n = walker.nextNode(); n && parts.length < 400; n = walker.nextNode()) {\n const holder = n.parentElement;\n if (!holder || holder.closest('select, textarea, script, style, template, noscript')) continue;\n if (holder.checkVisibility && !holder.checkVisibility({ visibilityProperty: true })) continue;\n parts.push(n.data);\n }\n return parts.join(' ');\n };\n const holdsControls = Boolean(el.querySelector && el.querySelector('select, textarea'));\n const raw = holdsControls ? outsideControls() : typeof el.innerText === 'string' ? el.innerText : el.textContent;\n const text = clean(raw);\n const view = el.ownerDocument.defaultView;\n const security = view ? view.getComputedStyle(el).getPropertyValue('-webkit-text-security') : '';\n return text && security && security !== 'none' ? '\u2022\u2022\u2022\u2022' : text;\n};\n const describe = (node) => node.tagName.toLowerCase() +\n (node.id ? '#' + node.id : '') +\n (node.classList && node.classList.length ? '.' + Array.from(node.classList).slice(0, 2).join('.') : '');\n const s = tree.style(el);\n const formControl = /^(input|textarea|select|button)$/.test(el.localName);\n const textControl = ((el) => {\n if (el.localName === 'textarea' || el.localName === 'select') return true;\n return el.localName === 'input' && !/^(checkbox|radio|range|color|hidden|image)$/.test(el.type);\n})(el);\n const holder = textControl ? null : ((el, tree) => {\n const counts = new Map();\n const parents = new Map();\n let budget = 2000;\n const shown = (n) => tree.style(n).display === 'contents' || tree.rendered(n);\n const nodesOf = (n) => {\n if (n.localName !== 'slot') return Array.from((n.shadowRoot || n).childNodes);\n const assigned = n.assignedNodes({ flatten: true });\n return assigned.length ? assigned : Array.from(n.childNodes);\n };\n const visit = (n) => {\n if (budget-- <= 0) return;\n for (const c of nodesOf(n)) {\n if (budget <= 0) return;\n if (c.nodeType === 3) {\n const length = c.data.replace(/\\s+/g, '').length;\n if (length === 0) continue;\n counts.set(n, (counts.get(n) || 0) + length);\n if (!parents.has(n)) parents.set(n, c.parentElement || n);\n } else if (c.nodeType === 1 && !tree.skipped.test(c.localName) && shown(c)) {\n visit(c);\n }\n }\n };\n visit(el);\n let best = null;\n for (const [holder, length] of counts) if (!best || length > counts.get(best)) best = holder;\n let total = 0;\n for (const length of counts.values()) total += length;\n return best && { style: best, font: parents.get(best), share: counts.get(best) / total };\n})(el, tree);\n const textChildren = tree.children(el).filter((c) => tree.rendered(c) && (c.textContent || '').trim() !== '').length;\n const textual = textControl || Boolean(holder && (holder.style === el || (holder.share >= 0.9 && textChildren <= 1) || !tree.container(el)));\n const textFrom = holder && holder.style !== el ? holder.style : el;\n const content = textOf(el);\n const parent = tree.layoutParent(el);\n const typedMap = el.computedStyleMap ? el.computedStyleMap() : null;\n const typed = (name) => { try { return typedMap ? String(typedMap.get(name)) : ''; } catch (e) { return ''; } };\n const result = {\n tag: el.localName,\n id: el.id || '',\n classes: el.classList ? Array.from(el.classList) : [],\n context: ((el) => {\n const describe = (node) => node.tagName.toLowerCase() + (node.id ? '#' + node.id : '');\n const parts = [];\n for (let doc = el.ownerDocument; doc && doc.defaultView && doc.defaultView.frameElement; ) {\n const frame = doc.defaultView.frameElement;\n parts.unshift(describe(frame));\n doc = frame.ownerDocument;\n }\n const root = el.getRootNode();\n if (root.host) {\n const host = root.host;\n const label = describe(host) + (!host.id && host.classList.length ? '.' + host.classList[0] : '');\n const text = (host.textContent || '').replace(/\\s+/g, ' ').trim().slice(0, 30);\n parts.push('shadow root of <' + label + (text ? ' \"' + text + '\"' : '') + '>');\n }\n return parts.join(' > ');\n})(el),\n content: content,\n textual: textual,\n formControl: formControl,\n rendered: textual && textFrom !== el\n ? tree.style(textFrom).visibility !== 'hidden' && tree.rendered(tree.style(textFrom).display === 'contents' ? tree.layoutParent(textFrom) : textFrom)\n : tree.rendered(el),\n hasText: textControl || holder !== null,\n replaced: el instanceof SVGElement || /^(img|video|audio|canvas|iframe|embed|object|input|textarea|select|button|meter|progress)$/.test(el.localName),\n svg: el.namespaceURI === 'http://www.w3.org/2000/svg',\n typed: { width: typed('width'), height: typed('height') },\n parent: parent ? describe(parent) : undefined,\n animating: el.getAnimations ? [...new Set(el.getAnimations().filter((a) => a.playState === 'running' && (!a.timeline || a.timeline === el.ownerDocument.timeline)).map((a) => a.transitionProperty || a.animationName || 'animation'))] : []\n };\n if (textFrom !== el) result.textHolder = tree.label(textFrom);\n const clipped = (n) => {\n const cs = tree.style(n);\n if (cs.overflowX !== 'visible' && n.scrollWidth > n.clientWidth + 1) return true;\n return cs.webkitLineClamp !== 'none' && cs.overflowY !== 'visible' && n.scrollHeight > n.clientHeight + 1;\n };\n if (textual && !textControl && (clipped(el) || (textFrom !== el && clipped(textFrom)))) result.truncated = true;\n if (((n, tree, text) => {\n const unquote = (name) => name.trim().replace(/^[\"']|[\"']$/g, '').toLowerCase();\n const match = /^\\s*(\"[^\"]*\"|'[^']*'|[^,]*)/.exec(tree.style(n).fontFamily);\n const first = unquote(match ? match[1] : '');\n if (!first || !n.ownerDocument.fonts) return false;\n const ranges = [];\n for (const face of n.ownerDocument.fonts) {\n if (face.status !== 'loaded' || unquote(face.family) !== first) continue;\n for (const part of face.unicodeRange.split(',')) {\n const [from, to] = part.trim().replace(/^U\\+/i, '').split('-');\n const low = parseInt(from.replace(/\\?/g, '0'), 16);\n const high = parseInt((to || from).replace(/\\?/g, 'F'), 16);\n if (!Number.isNaN(low) && !Number.isNaN(high)) ranges.push([low, high]);\n }\n }\n if (ranges.length === 0) return false;\n const covered = (code) => ranges.some(([low, high]) => code >= low && code <= high);\n return Array.from(text.replace(/\\s+/g, '')).every((char) => covered(char.codePointAt(0)));\n})(textFrom, tree, textOf(textFrom))) result.familyLoaded = true;\n if (/^(input|textarea)$/.test(el.localName) && el.placeholder && !el.value) {\n result.placeholder = el.placeholder.replace(/\\s+/g, ' ').trim();\n const placeholderStyle = tree.style(el, '::placeholder');\n result.placeholderColor = placeholderStyle.color;\n result.placeholderFont = { style: placeholderStyle.fontStyle, weight: placeholderStyle.fontWeight };\n }\n if (el.clientWidth > 0 && (el.scrollWidth > el.clientWidth + 1 || el.scrollHeight > el.clientHeight + 1)) {\n result.scroll = { w: el.scrollWidth, h: el.scrollHeight, clientW: el.clientWidth, clientH: el.clientHeight };\n }\n if (props) {\n const known = (name) => name.startsWith('--') || CSS.supports(name, 'inherit');\n const valueOf = (name) => {\n const value = s.getPropertyValue(name).trim();\n if (value !== '' || name.startsWith('--')) return value;\n const sides = ['top', 'right', 'bottom', 'left'].map((side) => name + '-' + side).filter(known);\n return sides.map((side) => side.slice(name.length + 1) + ' ' + s.getPropertyValue(side).trim()).join(' / ');\n };\n result.props = Object.fromEntries(props.filter(known).map((name) => [name, valueOf(name)]));\n result.rootFontSize = parseFloat(tree.style(el.ownerDocument.documentElement).fontSize) || 16;\n result.unknownProps = props.filter((name) => !known(name));\n }\n if (why && !why.startsWith('--')) {\n if (!CSS.supports(why, 'inherit')) result.unknownWhy = true;\n else {\n const probe = el.ownerDocument.createElement('div').style;\n probe.setProperty(why, 'inherit');\n if (probe.length > 1) {\n result.whyLonghands = Array.from(probe);\n result.whyComputed = s.getPropertyValue(why).trim();\n }\n const inactive = ((el, names) => {\n const view = el.ownerDocument.defaultView;\n const found = [];\n let budget = 20000;\n const unmet = (rule) => {\n if (rule.media && rule.media.mediaText && !view.matchMedia(rule.media.mediaText).matches) return '@media ' + rule.media.mediaText;\n if (typeof CSSSupportsRule !== 'undefined' && rule instanceof CSSSupportsRule && !CSS.supports(rule.conditionText)) return '@supports ' + rule.conditionText;\n return null;\n };\n const sets = (rule) => names.map((name) => rule.style.getPropertyValue(name).trim()).find((value) => value !== '');\n const matches = (selector) => {\n try { return el.matches(selector); } catch (e) { return false; }\n };\n const visit = (rules, condition) => {\n for (const rule of Array.from(rules)) {\n if (budget-- <= 0 || found.length >= 5) return;\n if (typeof CSSImportRule !== 'undefined' && rule instanceof CSSImportRule) {\n try { if (rule.styleSheet) visit(rule.styleSheet.cssRules, condition); } catch (e) { continue; }\n continue;\n }\n const value = condition && rule.style && rule.selectorText ? sets(rule) : undefined;\n if (value !== undefined && matches(rule.selectorText)) found.push({ selector: rule.selectorText, condition: condition, value: value });\n if (rule.cssRules) visit(rule.cssRules, condition || unmet(rule));\n }\n };\n for (const scope of new Set([el.getRootNode(), el.ownerDocument])) {\n for (const sheet of [...Array.from(scope.styleSheets || []), ...Array.from(scope.adoptedStyleSheets || [])]) {\n try { visit(sheet.cssRules, null); } catch (e) { continue; }\n }\n }\n return found;\n})(el, [why].concat(result.whyLonghands || []));\n if (inactive.length > 0) result.whyInactive = inactive;\n }\n }\n return Object.assign(result,\n ((el, tree) => {\n const parent = tree.layoutParent(el);\n if (!parent || tree.style(el).position === 'fixed' || !tree.rendered(el)) return {};\n const r = el.getBoundingClientRect();\n const p = parent.getBoundingClientRect();\n const ps = tree.style(parent);\n const zoom = parent.currentCSSZoom || 1;\n const edge = (side) => (parseFloat(ps['border-' + side + '-width']) + parseFloat(ps['padding-' + side])) * zoom;\n const inParent = {\n left: r.left - (p.left + edge('left')),\n top: r.top - (p.top + edge('top')),\n right: (p.right - edge('right')) - r.right,\n bottom: (p.bottom - edge('bottom')) - r.bottom\n };\n const inFlow = (n) => {\n if (n === el || !tree.rendered(n) || /^(absolute|fixed)$/.test(tree.style(n).position)) return false;\n const box = n.getBoundingClientRect();\n return box.width > 0 || box.height > 0;\n };\n const siblings = tree.children(parent);\n const at = siblings.indexOf(el);\n const before = siblings.slice(0, Math.max(at, 0)).reverse().find(inFlow);\n const after = at < 0 ? undefined : siblings.slice(at + 1).find(inFlow);\n const gaps = {};\n for (const sibling of [before, after]) {\n if (!sibling) continue;\n const s = sibling.getBoundingClientRect();\n if (s.bottom <= r.top + 0.5) gaps.top = r.top - s.bottom;\n else if (s.top >= r.bottom - 0.5) gaps.bottom = s.top - r.bottom;\n else if (s.right <= r.left + 0.5) gaps.left = r.left - s.right;\n else if (s.left >= r.right - 0.5) gaps.right = s.left - r.right;\n }\n return { inParent: inParent, siblings: gaps };\n})(el, tree),\n ((el, tree, view) => {\n const backgrounds = [];\n let opacity = 1;\n for (let n = el; n && backgrounds.length < 60; n = tree.flatParent(n)) {\n const s = tree.style(n);\n const own = Number(s.opacity) || 0;\n const background = { color: s.backgroundColor, image: s.backgroundImage !== 'none' };\n backgrounds.push(own < 1 ? Object.assign(background, { opacity: own }) : background);\n opacity *= own;\n }\n const doc = el.ownerDocument;\n const meta = doc.querySelector('meta[name=\"color-scheme\"]');\n const rootScheme = tree.style(doc.documentElement).colorScheme;\n const scheme = rootScheme && rootScheme !== 'normal' ? rootScheme : (meta && meta.content) || '';\n const prefersDark = view.matchMedia('(prefers-color-scheme: dark)').matches;\n const canvasDark = /dark/.test(scheme) && (!/light/.test(scheme) || prefersDark);\n return { backgrounds: backgrounds, canvasDark: canvasDark, opacity: opacity };\n})(textual ? textFrom : el, tree, view),\n textual ? { paintRisks: ((el, tree, textParent) => {\n const risks = [];\n const chain = [];\n for (let n = el; n && chain.length < 60; n = tree.flatParent(n)) chain.push(n);\n for (const n of chain) {\n const s = tree.style(n);\n if (s.mixBlendMode !== 'normal') risks.push('mix-blend-mode ' + s.mixBlendMode + ' on ' + tree.label(n));\n if (s.filter !== 'none') risks.push('filter on ' + tree.label(n));\n }\n const textNode = Array.from(textParent.childNodes).find((c) => c.nodeType === 3 && c.data.trim() !== '');\n const range = el.ownerDocument.createRange();\n if (textNode) range.selectNodeContents(textNode);\n const box = tree.style(el).display === 'contents' ? tree.layoutParent(el) : el;\n const rect = (textNode && range.getClientRects()[0]) || (box && box.getClientRects()[0]);\n const view = el.ownerDocument.defaultView;\n if (!rect) return risks;\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n if (x < 0 || y < 0 || x >= view.innerWidth || y >= view.innerHeight) return risks;\n const root = el.getRootNode();\n const hits = (root.elementsFromPoint ? root : el.ownerDocument).elementsFromPoint(x, y);\n const at = hits.findIndex((h) => chain.includes(h));\n if (at < 0) return risks;\n const clear = (color) => color === 'transparent' || /^rgba\\(.*,\\s*0\\)$/.test(color) || /\\/\\s*0\\)$/.test(color);\n const opaque = (n) => {\n const s = tree.style(n);\n return /^rgb\\(/.test(s.backgroundColor) && s.backgroundImage === 'none' && Number(s.opacity) === 1;\n };\n const paints = (n) => {\n const s = tree.style(n);\n return /^(canvas|video|img|iframe|embed|object|svg)$/.test(n.localName) || s.backgroundImage !== 'none' || !clear(s.backgroundColor);\n };\n let behind = null;\n for (const h of hits.slice(at)) {\n if (chain.includes(h)) {\n if (opaque(h)) break;\n } else if (paints(h)) {\n behind = h;\n break;\n }\n }\n if (behind) risks.push(tree.label(behind) + ' behind');\n const onTop = hits.slice(0, at).find((h) => !el.contains(h) && paints(h));\n if (onTop) risks.push(tree.label(onTop) + ' on top');\n return risks;\n})(textFrom, tree, holder ? holder.font : el) } : {},\n ((el, tree, textOf, depth) => {\n let budget = 400;\n let skipped = 0;\n const walk = (kids, level, origin) => {\n const shown = kids.filter((k) => tree.rendered(k) || k.localName === 'slot');\n const nodes = [];\n for (const k of shown) {\n if (budget <= 0) { skipped++; continue; }\n budget--;\n nodes.push(nodeOf(k, level, origin));\n }\n return { nodes: nodes, hidden: kids.length - shown.length };\n };\n const nodeOf = (n, level, origin) => {\n const r = n.getBoundingClientRect();\n const node = { label: tree.label(n), x: r.left - origin.left, y: r.top - origin.top, w: r.width, h: r.height, display: tree.style(n).display };\n if (tree.via.has(n)) node.via = tree.via.get(n);\n if (n.parentNode && n.parentNode.nodeType === 11 && n.parentNode.host) node.shadow = true;\n if (n.localName === 'slot') {\n node.text = n.assignedNodes({ flatten: true }).map((t) => t.textContent).join(' ').replace(/\\s+/g, ' ').trim().slice(0, 60);\n return node;\n }\n const kids = tree.children(n);\n if (!tree.container(n)) node.text = textOf(n).slice(0, 60);\n if (level >= depth) {\n node.childCount = kids.filter(tree.rendered).length;\n return node;\n }\n const sub = walk(kids, level + 1, r);\n node.children = sub.nodes;\n node.hidden = sub.hidden;\n return node;\n };\n if (depth <= 0) return { hiddenChildren: 0, treeSkipped: 0 };\n const top = walk(tree.children(el), 1, el.getBoundingClientRect());\n return { tree: top.nodes, hiddenChildren: top.hidden, treeSkipped: skipped };\n})(el, tree, textOf, depth));\n}";
|
|
123
170
|
/**
|
|
124
171
|
* Page-side function run on the element (`this`) that returns another
|
|
125
172
|
* element whose styles CDP reads: `"parent"`, the parent that lays it out
|
|
126
|
-
* (`display: contents` skipped, through shadow roots and slots),
|
|
127
|
-
* `"textHolder"`,
|
|
128
|
-
* (
|
|
129
|
-
*
|
|
173
|
+
* (`display: contents` skipped, through shadow roots and slots),
|
|
174
|
+
* `"textHolder"`, the element whose styles draw most of its text
|
|
175
|
+
* ({@link TEXT_HOLDER_JS}; the element itself when that is its own text), or
|
|
176
|
+
* `"fontHolder"`, the parent of that text's nodes (for the rendered font: a
|
|
177
|
+
* slot's text nodes belong to the host's light DOM). Null when there is none.
|
|
178
|
+
*/
|
|
179
|
+
export declare const RELATED_NODE_JS = "function (which) {\n const tree = ((view) => {\n const style = (n, pseudo) => view.getComputedStyle(n, pseudo);\n const skipped = /^(script|style|template|link|meta|noscript|title|head|base)$/;\n const flatParent = (n) => n.assignedSlot || n.parentElement || (n.parentNode && n.parentNode.host) || null;\n const layoutParent = (n) => {\n let p = flatParent(n);\n while (p && style(p).display === 'contents') p = flatParent(p);\n return p;\n };\n const via = new WeakMap();\n const label = (n) => n.localName + (n.id ? '#' + n.id : n.classList && n.classList.length ? '.' + n.classList[0] : '');\n const slotText = (slot) => slot.assignedNodes({ flatten: true }).some((t) => t.nodeType === 3 && t.data.trim() !== '');\n const children = (n) => {\n const out = [];\n const add = (c, through) => {\n if (skipped.test(c.localName)) return;\n if (c.localName === 'slot') {\n const assigned = c.assignedElements({ flatten: true });\n if (assigned.length === 0 && slotText(c)) out.push(c);\n else (assigned.length ? assigned : Array.from(c.children)).forEach((a) => add(a, label(c)));\n } else if (style(c).display === 'contents') {\n Array.from((c.shadowRoot || c).children).forEach((a) => add(a, label(c) + ' (contents)'));\n } else {\n if (through) via.set(c, through);\n out.push(c);\n }\n };\n Array.from((n.shadowRoot || n).children).forEach((c) => add(c, null));\n return out;\n };\n const rendered = (n) => n.getClientRects().length > 0 &&\n (!n.checkVisibility || n.checkVisibility({ visibilityProperty: true }));\n const container = (n) => children(n).some((c) => rendered(c) && !/^inline/.test(style(c).display));\n return { style, skipped, flatParent, layoutParent, children, rendered, container, label, via, slotText };\n})(this.ownerDocument.defaultView);\n if (which === 'parent') return tree.layoutParent(this);\n const holder = ((el, tree) => {\n const counts = new Map();\n const parents = new Map();\n let budget = 2000;\n const shown = (n) => tree.style(n).display === 'contents' || tree.rendered(n);\n const nodesOf = (n) => {\n if (n.localName !== 'slot') return Array.from((n.shadowRoot || n).childNodes);\n const assigned = n.assignedNodes({ flatten: true });\n return assigned.length ? assigned : Array.from(n.childNodes);\n };\n const visit = (n) => {\n if (budget-- <= 0) return;\n for (const c of nodesOf(n)) {\n if (budget <= 0) return;\n if (c.nodeType === 3) {\n const length = c.data.replace(/\\s+/g, '').length;\n if (length === 0) continue;\n counts.set(n, (counts.get(n) || 0) + length);\n if (!parents.has(n)) parents.set(n, c.parentElement || n);\n } else if (c.nodeType === 1 && !tree.skipped.test(c.localName) && shown(c)) {\n visit(c);\n }\n }\n };\n visit(el);\n let best = null;\n for (const [holder, length] of counts) if (!best || length > counts.get(best)) best = holder;\n let total = 0;\n for (const length of counts.values()) total += length;\n return best && { style: best, font: parents.get(best), share: counts.get(best) / total };\n})(this, tree);\n if (!holder) return null;\n return which === 'textHolder' ? holder.style : holder.font;\n}";
|
|
180
|
+
/** Where a custom property is set, as {@link VARIABLE_SETTERS_JS} finds it */
|
|
181
|
+
export interface VariableSetter {
|
|
182
|
+
/** Selector of the rule, or `@keyframes name` */
|
|
183
|
+
selector: string;
|
|
184
|
+
/** Value as written (`inherit`, `` for an empty one) */
|
|
185
|
+
value: string;
|
|
186
|
+
/** Set in a keyframe of this animation */
|
|
187
|
+
keyframes?: string;
|
|
188
|
+
/** The rule matches the element or an ancestor now (null: bdg cannot test its selector) */
|
|
189
|
+
matches: boolean | null;
|
|
190
|
+
/** The `@media` or `@supports` condition it is under that does not apply now */
|
|
191
|
+
condition?: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Page-side function run on the element (`this`): for each custom property
|
|
195
|
+
* name, a rule in the page's stylesheets (same-origin, `@import`ed,
|
|
196
|
+
* constructed and the element's shadow root's) that sets it, keyframes
|
|
197
|
+
* included: the first one that matches the element or an ancestor now
|
|
198
|
+
* (across shadow roots, so `:root` matches inside a component), else the
|
|
199
|
+
* first that would match without its state (`.btn:hover` for this `.btn`),
|
|
200
|
+
* else the first one, with the `@media`/`@supports` condition it is under
|
|
201
|
+
* when that does not apply. At most 20000 rules are read; cross-origin sheets are
|
|
202
|
+
* skipped.
|
|
130
203
|
*/
|
|
131
|
-
export declare const
|
|
204
|
+
export declare const VARIABLE_SETTERS_JS = "function (names) {\n const el = this;\n const view = el.ownerDocument.defaultView;\n const matching = {};\n const related = {};\n const other = {};\n let budget = 20000;\n const closestAcross = (selector) => {\n for (let n = el; n; n = n.getRootNode().host || null) {\n if (n.closest(selector)) return true;\n }\n return false;\n };\n const matches = (selector) => {\n try { return closestAcross(selector); } catch (e) { return null; }\n };\n const stateless = (selector) => selector.replace(/:(focus-visible|focus-within|focus|hover|active|visited|checked|target|open)(?![\\w-])/g, '');\n const applies = (rule) => {\n if (rule.media && rule.media.mediaText && !view.matchMedia(rule.media.mediaText).matches) return '@media ' + rule.media.mediaText;\n if (typeof CSSSupportsRule !== 'undefined' && rule instanceof CSSSupportsRule && !CSS.supports(rule.conditionText)) return '@supports ' + rule.conditionText;\n return null;\n };\n const record = (name, rule, keyframes, condition) => {\n const selector = keyframes ? '@keyframes ' + keyframes : rule.selectorText || '';\n const match = keyframes || condition ? false : matches(selector);\n const setter = Object.assign(\n { selector: selector, value: rule.style.getPropertyValue(name).trim(), matches: match },\n keyframes ? { keyframes: keyframes } : {},\n condition ? { condition: condition } : {}\n );\n if (match && !matching[name]) matching[name] = setter;\n else if (!match && !keyframes && !related[name] && matches(stateless(selector))) related[name] = setter;\n else if (!match && !other[name]) other[name] = setter;\n };\n const visit = (rules, keyframes, condition) => {\n for (const rule of Array.from(rules)) {\n if (budget-- <= 0 || names.every((name) => matching[name])) return;\n if (typeof CSSImportRule !== 'undefined' && rule instanceof CSSImportRule) {\n try { if (rule.styleSheet) visit(rule.styleSheet.cssRules, keyframes, condition); } catch (e) { continue; }\n continue;\n }\n if (typeof CSSKeyframesRule !== 'undefined' && rule instanceof CSSKeyframesRule) {\n visit(rule.cssRules, rule.name, condition);\n continue;\n }\n if (rule.style) {\n for (const name of names) {\n if (!matching[name] && Array.from(rule.style).includes(name)) record(name, rule, keyframes, condition);\n }\n }\n if (rule.cssRules) visit(rule.cssRules, keyframes, condition || applies(rule));\n }\n };\n const sheets = [];\n for (const scope of new Set([el.getRootNode(), el.ownerDocument])) {\n sheets.push(...Array.from(scope.styleSheets || []), ...Array.from(scope.adoptedStyleSheets || []));\n }\n for (const sheet of sheets) {\n try { visit(sheet.cssRules, null, null); } catch (e) { continue; }\n }\n return Object.assign({}, other, related, matching);\n}";
|
|
132
205
|
//# sourceMappingURL=inspectScripts.d.ts.map
|