browser-debugger-cli 0.10.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.
Files changed (103) hide show
  1. package/.claude/skills/bdg/SKILL.md +268 -0
  2. package/README.md +148 -74
  3. package/dist/commands/css.d.ts +13 -0
  4. package/dist/commands/css.js +53 -0
  5. package/dist/commands/dom/audit.d.ts +14 -0
  6. package/dist/commands/dom/audit.js +87 -0
  7. package/dist/commands/dom/formInteraction.js +36 -6
  8. package/dist/commands/dom/helpers/keyAttributes.d.ts +3 -2
  9. package/dist/commands/dom/helpers/keyAttributes.js +6 -4
  10. package/dist/commands/dom/helpers/screenshot.d.ts +1 -0
  11. package/dist/commands/dom/helpers/screenshot.js +158 -38
  12. package/dist/commands/dom/index.js +4 -1
  13. package/dist/commands/dom/screenshot.js +10 -6
  14. package/dist/commands/dom/wait.js +5 -3
  15. package/dist/commands/helpJson.js +1 -1
  16. package/dist/commands/installSkill.d.ts +20 -0
  17. package/dist/commands/installSkill.js +87 -0
  18. package/dist/commands/optionBehaviors.js +21 -6
  19. package/dist/commands/page.js +7 -4
  20. package/dist/commands/peek.d.ts +7 -0
  21. package/dist/commands/peek.js +65 -23
  22. package/dist/commands/shared/optionTypes.d.ts +5 -1
  23. package/dist/commands/start.d.ts +13 -0
  24. package/dist/commands/start.js +19 -2
  25. package/dist/commands/tail.d.ts +7 -1
  26. package/dist/commands/tail.js +13 -62
  27. package/dist/commands.js +5 -0
  28. package/dist/daemon/session/commandRegistry.js +7 -1
  29. package/dist/daemon/session/plugins.js +4 -52
  30. package/dist/daemon.js +7986 -6848
  31. package/dist/errors/messages.d.ts +50 -4
  32. package/dist/errors/messages.js +94 -5
  33. package/dist/index.js +709 -190
  34. package/dist/ipc/client.d.ts +4 -0
  35. package/dist/ipc/client.js +8 -0
  36. package/dist/ipc/protocol/auditTypes.d.ts +129 -0
  37. package/dist/ipc/protocol/auditTypes.js +6 -0
  38. package/dist/ipc/protocol/commands.d.ts +23 -0
  39. package/dist/ipc/protocol/commands.js +2 -0
  40. package/dist/ipc/protocol/domTypes.d.ts +4 -0
  41. package/dist/ipc/protocol/inspectTypes.d.ts +71 -8
  42. package/dist/runtime/css/search.d.ts +39 -0
  43. package/dist/runtime/css/search.js +122 -0
  44. package/dist/runtime/dom/actionEffects.d.ts +4 -1
  45. package/dist/runtime/dom/actionEffects.js +8 -4
  46. package/dist/runtime/dom/audit.d.ts +19 -0
  47. package/dist/runtime/dom/audit.js +36 -0
  48. package/dist/runtime/dom/auditModel.d.ts +45 -0
  49. package/dist/runtime/dom/auditModel.js +215 -0
  50. package/dist/runtime/dom/auditScripts.d.ts +107 -0
  51. package/dist/runtime/dom/auditScripts.js +112 -0
  52. package/dist/runtime/dom/elementGeometry.d.ts +8 -2
  53. package/dist/runtime/dom/elementGeometry.js +24 -8
  54. package/dist/runtime/dom/elementInfo.d.ts +3 -2
  55. package/dist/runtime/dom/elementInfo.js +8 -2
  56. package/dist/runtime/dom/formFillHelpers/fill.js +2 -2
  57. package/dist/runtime/dom/inspect.d.ts +7 -0
  58. package/dist/runtime/dom/inspect.js +88 -23
  59. package/dist/runtime/dom/inspectAllStyles.d.ts +16 -4
  60. package/dist/runtime/dom/inspectAllStyles.js +89 -7
  61. package/dist/runtime/dom/inspectCascade.d.ts +19 -2
  62. package/dist/runtime/dom/inspectCascade.js +214 -44
  63. package/dist/runtime/dom/inspectCascadeModel.d.ts +8 -0
  64. package/dist/runtime/dom/inspectCascadeModel.js +108 -34
  65. package/dist/runtime/dom/inspectHints.d.ts +26 -3
  66. package/dist/runtime/dom/inspectHints.js +125 -9
  67. package/dist/runtime/dom/inspectModel.d.ts +3 -0
  68. package/dist/runtime/dom/inspectModel.js +30 -7
  69. package/dist/runtime/dom/inspectPaintModel.d.ts +48 -22
  70. package/dist/runtime/dom/inspectPaintModel.js +180 -68
  71. package/dist/runtime/dom/inspectRules.d.ts +19 -0
  72. package/dist/runtime/dom/inspectRules.js +21 -5
  73. package/dist/runtime/dom/inspectScripts.d.ts +85 -12
  74. package/dist/runtime/dom/inspectScripts.js +314 -28
  75. package/dist/runtime/dom/inspectTree.js +10 -2
  76. package/dist/runtime/dom/inspectWhyModel.d.ts +2 -1
  77. package/dist/runtime/dom/inspectWhyModel.js +52 -10
  78. package/dist/runtime/dom/layout.js +31 -9
  79. package/dist/runtime/dom/reactEventHelpers.d.ts +7 -0
  80. package/dist/runtime/dom/reactEventHelpers.js +27 -9
  81. package/dist/runtime/page/emulation.d.ts +13 -4
  82. package/dist/runtime/page/emulation.js +69 -4
  83. package/dist/runtime/page/userAgent.d.ts +17 -0
  84. package/dist/runtime/page/userAgent.js +57 -0
  85. package/dist/types.d.ts +12 -0
  86. package/dist/ui/formatters/audit.d.ts +19 -0
  87. package/dist/ui/formatters/audit.js +106 -0
  88. package/dist/ui/formatters/dom.d.ts +1 -1
  89. package/dist/ui/formatters/dom.js +6 -3
  90. package/dist/ui/formatters/inspect.js +42 -15
  91. package/dist/ui/formatters/installSkill.d.ts +11 -0
  92. package/dist/ui/formatters/installSkill.js +31 -0
  93. package/dist/ui/formatters/status.js +1 -1
  94. package/dist/ui/messages/commands.d.ts +44 -7
  95. package/dist/ui/messages/commands.js +83 -11
  96. package/dist/ui/messages/preview.d.ts +6 -0
  97. package/dist/ui/messages/preview.js +9 -1
  98. package/dist/utils/cssValues.js +36 -4
  99. package/dist/utils/decisionTrees.js +0 -5
  100. package/dist/utils/suggestions.d.ts +4 -2
  101. package/dist/utils/suggestions.js +7 -5
  102. package/dist/utils/taskMappings.js +1 -1
  103. package/package.json +4 -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
- /** Has text to describe: own text, only inline content with text, or a form control */
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
- /** Properties of running CSS transitions, and names of running animations */
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, and the property names asked for with `--props`
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), or
127
- * `"textHolder"`, for an element whose text is in a descendant
128
- * (`<button><span>Buy</span></button>`), the first element holding text,
129
- * whose rendered font is the one shown. Null when there is none.
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 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 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})(this.ownerDocument.defaultView);\n if (which === 'parent') return tree.layoutParent(this);\n const walker = this.ownerDocument.createTreeWalker(this, NodeFilter.SHOW_TEXT);\n while (walker.nextNode()) {\n if (walker.currentNode.data.trim() !== '') return walker.currentNode.parentElement;\n }\n return null;\n}";
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