browser-debugger-cli 0.8.0 → 0.10.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 (304) hide show
  1. package/README.md +7 -1
  2. package/dist/cdp/schema.d.ts +4 -1
  3. package/dist/cdp/schema.js +48 -7
  4. package/dist/commands/cdp.js +3 -2
  5. package/dist/commands/cleanup.d.ts +11 -0
  6. package/dist/commands/cleanup.js +161 -57
  7. package/dist/commands/console.d.ts +20 -1
  8. package/dist/commands/console.js +57 -17
  9. package/dist/commands/details.js +3 -2
  10. package/dist/commands/dom/DomElementResolver.d.ts +10 -3
  11. package/dist/commands/dom/DomElementResolver.js +35 -17
  12. package/dist/commands/dom/a11y.d.ts +10 -0
  13. package/dist/commands/dom/a11y.js +29 -6
  14. package/dist/commands/dom/eval.d.ts +3 -1
  15. package/dist/commands/dom/eval.js +29 -4
  16. package/dist/commands/dom/form.js +16 -62
  17. package/dist/commands/dom/formInteraction.js +189 -119
  18. package/dist/commands/dom/formSummary.d.ts +49 -0
  19. package/dist/commands/dom/formSummary.js +180 -0
  20. package/dist/commands/dom/frames.d.ts +2 -1
  21. package/dist/commands/dom/frames.js +17 -2
  22. package/dist/commands/dom/get.d.ts +6 -5
  23. package/dist/commands/dom/get.js +92 -82
  24. package/dist/commands/dom/helpers/index.d.ts +1 -1
  25. package/dist/commands/dom/helpers/index.js +1 -1
  26. package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
  27. package/dist/commands/dom/helpers/keyAttributes.js +54 -0
  28. package/dist/commands/dom/helpers/query.d.ts +44 -17
  29. package/dist/commands/dom/helpers/query.js +300 -106
  30. package/dist/commands/dom/helpers/runElementCommand.d.ts +10 -2
  31. package/dist/commands/dom/helpers/runElementCommand.js +98 -30
  32. package/dist/commands/dom/helpers/screenshot.d.ts +4 -1
  33. package/dist/commands/dom/helpers/screenshot.js +239 -51
  34. package/dist/commands/dom/index.d.ts +4 -1
  35. package/dist/commands/dom/index.js +22 -7
  36. package/dist/commands/dom/inspect.d.ts +15 -0
  37. package/dist/commands/dom/inspect.js +82 -0
  38. package/dist/commands/dom/layout.d.ts +14 -0
  39. package/dist/commands/dom/layout.js +54 -0
  40. package/dist/commands/dom/listeners.d.ts +5 -1
  41. package/dist/commands/dom/listeners.js +15 -5
  42. package/dist/commands/dom/query.js +2 -3
  43. package/dist/commands/dom/screenshot.d.ts +12 -2
  44. package/dist/commands/dom/screenshot.js +27 -3
  45. package/dist/commands/dom/semanticUtils.d.ts +16 -10
  46. package/dist/commands/dom/semanticUtils.js +53 -16
  47. package/dist/commands/dom/wait.d.ts +13 -0
  48. package/dist/commands/dom/wait.js +83 -0
  49. package/dist/commands/helpJson.js +2 -2
  50. package/dist/commands/network/list.js +17 -13
  51. package/dist/commands/optionBehaviors.js +154 -21
  52. package/dist/commands/page.d.ts +3 -2
  53. package/dist/commands/page.js +100 -5
  54. package/dist/commands/peek.js +4 -11
  55. package/dist/commands/sessions.d.ts +8 -0
  56. package/dist/commands/sessions.js +19 -0
  57. package/dist/commands/shared/CommandRunner.js +4 -4
  58. package/dist/commands/shared/commonOptions.d.ts +4 -0
  59. package/dist/commands/shared/commonOptions.js +9 -0
  60. package/dist/commands/shared/dataFetcher.js +2 -2
  61. package/dist/commands/shared/followMode.d.ts +21 -1
  62. package/dist/commands/shared/followMode.js +29 -2
  63. package/dist/commands/shared/handleValidationError.d.ts +2 -2
  64. package/dist/commands/shared/handleValidationError.js +12 -3
  65. package/dist/commands/shared/optionTypes.d.ts +61 -5
  66. package/dist/commands/shared/startHelpers.d.ts +66 -0
  67. package/dist/commands/shared/startHelpers.js +103 -13
  68. package/dist/commands/shared/validation.d.ts +14 -2
  69. package/dist/commands/shared/validation.js +20 -3
  70. package/dist/commands/start.d.ts +63 -0
  71. package/dist/commands/start.js +115 -15
  72. package/dist/commands/status.js +29 -7
  73. package/dist/commands/stop.js +7 -6
  74. package/dist/commands/tail.js +4 -11
  75. package/dist/commands/types.d.ts +2 -0
  76. package/dist/commands.js +2 -0
  77. package/dist/connection/chromeIdentity.d.ts +65 -0
  78. package/dist/connection/chromeIdentity.js +143 -0
  79. package/dist/connection/launcher/profilePreferences.d.ts +47 -0
  80. package/dist/connection/launcher/profilePreferences.js +151 -0
  81. package/dist/connection/launcher.d.ts +21 -2
  82. package/dist/connection/launcher.js +42 -16
  83. package/dist/connection/portReservation.d.ts +14 -4
  84. package/dist/connection/portReservation.js +21 -6
  85. package/dist/connection/startupExit.d.ts +8 -0
  86. package/dist/connection/startupExit.js +15 -6
  87. package/dist/constants.d.ts +6 -2
  88. package/dist/constants.js +9 -2
  89. package/dist/daemon/SessionController.js +23 -7
  90. package/dist/daemon/errors.d.ts +1 -1
  91. package/dist/daemon/errors.js +1 -1
  92. package/dist/daemon/launcher.d.ts +10 -2
  93. package/dist/daemon/launcher.js +8 -7
  94. package/dist/daemon/server/SocketServer.js +1 -2
  95. package/dist/daemon/session/Session.d.ts +20 -0
  96. package/dist/daemon/session/Session.js +80 -9
  97. package/dist/daemon/session/chromeConnection.d.ts +9 -0
  98. package/dist/daemon/session/chromeConnection.js +45 -8
  99. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  100. package/dist/daemon/session/commandRegistry.js +113 -67
  101. package/dist/daemon/session/interactions.d.ts +48 -9
  102. package/dist/daemon/session/interactions.js +46 -9
  103. package/dist/daemon/session/triggeredRequests.d.ts +67 -0
  104. package/dist/daemon/session/triggeredRequests.js +157 -0
  105. package/dist/daemon/session/types.d.ts +5 -1
  106. package/dist/daemon.js +10630 -3601
  107. package/dist/errors/messages.d.ts +456 -24
  108. package/dist/errors/messages.js +862 -67
  109. package/dist/index.js +6915 -3401
  110. package/dist/ipc/client.d.ts +21 -1
  111. package/dist/ipc/client.js +35 -3
  112. package/dist/ipc/protocol/commands.d.ts +145 -5
  113. package/dist/ipc/protocol/commands.js +4 -0
  114. package/dist/ipc/protocol/domTypes.d.ts +291 -7
  115. package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
  116. package/dist/ipc/protocol/inspectTypes.js +10 -0
  117. package/dist/ipc/session/lifecycle.d.ts +8 -1
  118. package/dist/ipc/session/queries.d.ts +5 -1
  119. package/dist/ipc/session/types.d.ts +5 -0
  120. package/dist/ipc/transport/index.d.ts +2 -1
  121. package/dist/ipc/transport/index.js +2 -2
  122. package/dist/runtime/dom/actionEffects.d.ts +185 -0
  123. package/dist/runtime/dom/actionEffects.js +402 -0
  124. package/dist/runtime/dom/actionEffectsScripts.d.ts +90 -0
  125. package/dist/runtime/dom/actionEffectsScripts.js +426 -0
  126. package/dist/runtime/dom/elementGeometry.d.ts +170 -0
  127. package/dist/runtime/dom/elementGeometry.js +553 -0
  128. package/dist/runtime/dom/elementInfo.d.ts +103 -0
  129. package/dist/runtime/dom/elementInfo.js +256 -0
  130. package/dist/runtime/dom/evalHelpers.d.ts +51 -6
  131. package/dist/runtime/dom/evalHelpers.js +136 -26
  132. package/dist/runtime/dom/eventListeners.d.ts +2 -1
  133. package/dist/runtime/dom/eventListeners.js +184 -47
  134. package/dist/runtime/dom/formDiscovery.d.ts +1 -1
  135. package/dist/runtime/dom/formDiscovery.js +116 -16
  136. package/dist/runtime/dom/formFillHelpers/fill.d.ts +9 -0
  137. package/dist/runtime/dom/formFillHelpers/fill.js +178 -14
  138. package/dist/runtime/dom/formFillHelpers/index.d.ts +2 -2
  139. package/dist/runtime/dom/formFillHelpers/index.js +2 -2
  140. package/dist/runtime/dom/formFillHelpers/pressKey.js +14 -3
  141. package/dist/runtime/dom/formFillHelpers/scroll.d.ts +3 -0
  142. package/dist/runtime/dom/formFillHelpers/scroll.js +60 -18
  143. package/dist/runtime/dom/formFillHelpers/shared.d.ts +17 -0
  144. package/dist/runtime/dom/formFillHelpers/shared.js +25 -1
  145. package/dist/runtime/dom/formFillHelpers/stability.d.ts +20 -6
  146. package/dist/runtime/dom/formFillHelpers/stability.js +50 -19
  147. package/dist/runtime/dom/formSubmitHelpers.d.ts +3 -0
  148. package/dist/runtime/dom/formSubmitHelpers.js +89 -15
  149. package/dist/runtime/dom/frameLayout.d.ts +60 -0
  150. package/dist/runtime/dom/frameLayout.js +140 -0
  151. package/dist/runtime/dom/frameOrigin.d.ts +50 -0
  152. package/dist/runtime/dom/frameOrigin.js +62 -0
  153. package/dist/runtime/dom/frameScopedConnection.d.ts +92 -0
  154. package/dist/runtime/dom/frameScopedConnection.js +252 -0
  155. package/dist/runtime/dom/frameSelection.d.ts +12 -1
  156. package/dist/runtime/dom/frameSelection.js +22 -3
  157. package/dist/runtime/dom/frames.d.ts +61 -5
  158. package/dist/runtime/dom/frames.js +329 -75
  159. package/dist/runtime/dom/inspect.d.ts +28 -0
  160. package/dist/runtime/dom/inspect.js +557 -0
  161. package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
  162. package/dist/runtime/dom/inspectAllStyles.js +385 -0
  163. package/dist/runtime/dom/inspectCascade.d.ts +94 -0
  164. package/dist/runtime/dom/inspectCascade.js +371 -0
  165. package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
  166. package/dist/runtime/dom/inspectCascadeModel.js +232 -0
  167. package/dist/runtime/dom/inspectHints.d.ts +62 -0
  168. package/dist/runtime/dom/inspectHints.js +305 -0
  169. package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
  170. package/dist/runtime/dom/inspectLayoutModel.js +346 -0
  171. package/dist/runtime/dom/inspectModel.d.ts +74 -0
  172. package/dist/runtime/dom/inspectModel.js +184 -0
  173. package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
  174. package/dist/runtime/dom/inspectPaintModel.js +461 -0
  175. package/dist/runtime/dom/inspectRules.d.ts +37 -0
  176. package/dist/runtime/dom/inspectRules.js +101 -0
  177. package/dist/runtime/dom/inspectScripts.d.ts +132 -0
  178. package/dist/runtime/dom/inspectScripts.js +263 -0
  179. package/dist/runtime/dom/inspectTree.d.ts +40 -0
  180. package/dist/runtime/dom/inspectTree.js +134 -0
  181. package/dist/runtime/dom/inspectVariables.d.ts +33 -0
  182. package/dist/runtime/dom/inspectVariables.js +94 -0
  183. package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
  184. package/dist/runtime/dom/inspectWhyModel.js +134 -0
  185. package/dist/runtime/dom/layout.d.ts +71 -0
  186. package/dist/runtime/dom/layout.js +340 -0
  187. package/dist/runtime/dom/listenerPageScripts.d.ts +72 -0
  188. package/dist/runtime/dom/listenerPageScripts.js +365 -0
  189. package/dist/runtime/dom/listenerSummary.d.ts +136 -11
  190. package/dist/runtime/dom/listenerSummary.js +361 -22
  191. package/dist/runtime/dom/pageActivity.d.ts +41 -0
  192. package/dist/runtime/dom/pageActivity.js +123 -0
  193. package/dist/runtime/dom/reactEventHelpers.d.ts +63 -2
  194. package/dist/runtime/dom/reactEventHelpers.js +220 -41
  195. package/dist/runtime/dom/targetNode.d.ts +80 -27
  196. package/dist/runtime/dom/targetNode.js +249 -33
  197. package/dist/runtime/dom/wait.d.ts +25 -0
  198. package/dist/runtime/dom/wait.js +199 -0
  199. package/dist/runtime/dom/waitCondition.d.ts +71 -0
  200. package/dist/runtime/dom/waitCondition.js +75 -0
  201. package/dist/runtime/page/emulation.d.ts +71 -0
  202. package/dist/runtime/page/emulation.js +117 -0
  203. package/dist/runtime/page/loadingState.d.ts +36 -0
  204. package/dist/runtime/page/loadingState.js +86 -0
  205. package/dist/runtime/page/navigation.d.ts +46 -2
  206. package/dist/runtime/page/navigation.js +69 -33
  207. package/dist/session/QueryCacheManager.d.ts +11 -1
  208. package/dist/session/QueryCacheManager.js +25 -3
  209. package/dist/session/chromeOwners.d.ts +34 -0
  210. package/dist/session/chromeOwners.js +51 -0
  211. package/dist/session/cleanup/staleSession.d.ts +11 -1
  212. package/dist/session/cleanup/staleSession.js +17 -6
  213. package/dist/session/cleanup/userCommands.js +2 -4
  214. package/dist/session/metadata.d.ts +5 -1
  215. package/dist/session/metadata.js +2 -1
  216. package/dist/session/paths.d.ts +77 -3
  217. package/dist/session/paths.js +111 -5
  218. package/dist/session/port.d.ts +31 -7
  219. package/dist/session/port.js +50 -43
  220. package/dist/session/portClaims.d.ts +66 -0
  221. package/dist/session/portClaims.js +284 -0
  222. package/dist/session/sessionList.d.ts +58 -0
  223. package/dist/session/sessionList.js +199 -0
  224. package/dist/session/sessionName.d.ts +46 -0
  225. package/dist/session/sessionName.js +97 -0
  226. package/dist/telemetry/a11y.d.ts +18 -3
  227. package/dist/telemetry/a11y.js +170 -29
  228. package/dist/telemetry/console.d.ts +1 -0
  229. package/dist/telemetry/console.js +100 -5
  230. package/dist/telemetry/network.js +3 -1
  231. package/dist/telemetry/requestKinds.d.ts +32 -0
  232. package/dist/telemetry/requestKinds.js +61 -0
  233. package/dist/telemetry/requestState.d.ts +31 -0
  234. package/dist/telemetry/requestState.js +38 -0
  235. package/dist/types.d.ts +112 -3
  236. package/dist/ui/formatters/a11y.js +3 -0
  237. package/dist/ui/formatters/console/chronological.d.ts +8 -0
  238. package/dist/ui/formatters/console/chronological.js +17 -4
  239. package/dist/ui/formatters/console/json.js +3 -4
  240. package/dist/ui/formatters/console/shared.d.ts +12 -0
  241. package/dist/ui/formatters/console.d.ts +2 -2
  242. package/dist/ui/formatters/console.js +1 -1
  243. package/dist/ui/formatters/details.d.ts +8 -0
  244. package/dist/ui/formatters/details.js +61 -4
  245. package/dist/ui/formatters/dom.d.ts +27 -14
  246. package/dist/ui/formatters/dom.js +88 -59
  247. package/dist/ui/formatters/form.js +29 -18
  248. package/dist/ui/formatters/inspect.d.ts +39 -0
  249. package/dist/ui/formatters/inspect.js +596 -0
  250. package/dist/ui/formatters/keyAttributes.d.ts +19 -0
  251. package/dist/ui/formatters/keyAttributes.js +84 -0
  252. package/dist/ui/formatters/layout.d.ts +31 -0
  253. package/dist/ui/formatters/layout.js +53 -0
  254. package/dist/ui/formatters/listeners.d.ts +3 -2
  255. package/dist/ui/formatters/listeners.js +73 -9
  256. package/dist/ui/formatters/networkHeaders.d.ts +13 -0
  257. package/dist/ui/formatters/networkHeaders.js +36 -3
  258. package/dist/ui/formatters/networkList.d.ts +29 -1
  259. package/dist/ui/formatters/networkList.js +86 -20
  260. package/dist/ui/formatters/preview.js +2 -1
  261. package/dist/ui/formatters/requestStatus.d.ts +1 -17
  262. package/dist/ui/formatters/requestStatus.js +2 -30
  263. package/dist/ui/formatters/sessions.d.ts +12 -0
  264. package/dist/ui/formatters/sessions.js +40 -0
  265. package/dist/ui/formatters/status.d.ts +21 -2
  266. package/dist/ui/formatters/status.js +47 -10
  267. package/dist/ui/formatters/triggeredRequests.d.ts +36 -0
  268. package/dist/ui/formatters/triggeredRequests.js +65 -0
  269. package/dist/ui/formatting.d.ts +19 -0
  270. package/dist/ui/formatting.js +31 -36
  271. package/dist/ui/messages/chrome.d.ts +9 -0
  272. package/dist/ui/messages/chrome.js +17 -5
  273. package/dist/ui/messages/commands.d.ts +504 -14
  274. package/dist/ui/messages/commands.js +835 -21
  275. package/dist/ui/messages/consoleMessages.d.ts +10 -0
  276. package/dist/ui/messages/consoleMessages.js +17 -0
  277. package/dist/ui/messages/hints.js +2 -1
  278. package/dist/ui/messages/networkMessages.d.ts +14 -0
  279. package/dist/ui/messages/networkMessages.js +18 -0
  280. package/dist/ui/messages/preview.js +5 -4
  281. package/dist/ui/messages/session.d.ts +30 -21
  282. package/dist/ui/messages/session.js +48 -26
  283. package/dist/ui/messages/sessionCommand.d.ts +43 -0
  284. package/dist/ui/messages/sessionCommand.js +52 -0
  285. package/dist/utils/async.d.ts +17 -0
  286. package/dist/utils/async.js +36 -0
  287. package/dist/utils/color.d.ts +84 -0
  288. package/dist/utils/color.js +376 -0
  289. package/dist/utils/cssValues.d.ts +109 -0
  290. package/dist/utils/cssValues.js +236 -0
  291. package/dist/utils/http.d.ts +22 -1
  292. package/dist/utils/http.js +28 -9
  293. package/dist/utils/selectorFilters.d.ts +48 -8
  294. package/dist/utils/selectorFilters.js +296 -53
  295. package/dist/utils/shellDetection.d.ts +8 -2
  296. package/dist/utils/shellDetection.js +120 -33
  297. package/dist/utils/suggestions.d.ts +26 -0
  298. package/dist/utils/suggestions.js +73 -0
  299. package/dist/utils/taskMappings.js +10 -0
  300. package/dist/utils/url.d.ts +12 -2
  301. package/dist/utils/url.js +69 -7
  302. package/package.json +1 -1
  303. package/dist/ui/formatters/sessionFormatters.d.ts +0 -58
  304. package/dist/ui/formatters/sessionFormatters.js +0 -121
@@ -0,0 +1,346 @@
1
+ /**
2
+ * Box and layout groups of `bdg dom inspect`, from computed styles.
3
+ *
4
+ * Core facts are always there (display, padding/margin/border as computed,
5
+ * even when they equal the UA default); the rest only when it applies
6
+ * (container fields for flex and grid containers, item fields in a flex or
7
+ * grid parent) and is not a no-op default. Sizing is named like Figma's
8
+ * auto layout: hug (sized by the content), fill (stretched by the parent)
9
+ * or fixed, from the computed (not resolved) width and height.
10
+ */
11
+ import { compressTracks, cssLength, round1 } from '../../utils/cssValues.js';
12
+ const SIDES = ['top', 'right', 'bottom', 'left'];
13
+ /**
14
+ * The four sides of a box property.
15
+ *
16
+ * @param style - Computed styles
17
+ * @param name - e.g. `padding-{side}`, `border-{side}-width`
18
+ * @returns Top, right, bottom, left
19
+ */
20
+ export function sides(style, name) {
21
+ return SIDES.map((side) => cssLength(style[name.replace('{side}', side)]));
22
+ }
23
+ /**
24
+ * Whether a computed value is a no-op for a size limit.
25
+ *
26
+ * @param value - Computed min/max width or height
27
+ * @returns True for `auto`, `none` and 0
28
+ */
29
+ function noLimit(value) {
30
+ return value === undefined || value === 'auto' || value === 'none' || value === '0px';
31
+ }
32
+ /**
33
+ * Min or max sizes that constrain the box.
34
+ *
35
+ * @param style - Computed styles
36
+ * @param kind - `min` or `max`
37
+ * @returns Width and height limits, or undefined when there are none
38
+ */
39
+ function sizeLimits(style, kind) {
40
+ const w = style[`${kind}-width`];
41
+ const h = style[`${kind}-height`];
42
+ const limits = {
43
+ ...(!noLimit(w) && { w: cssLength(w) }),
44
+ ...(!noLimit(h) && { h: cssLength(h) }),
45
+ };
46
+ return Object.keys(limits).length > 0 ? limits : undefined;
47
+ }
48
+ /**
49
+ * The box group: padding, margin, border widths, box-sizing, size limits,
50
+ * overflow and the content size when it overflows.
51
+ *
52
+ * @param style - Computed styles
53
+ * @param raw - Page-side measurements
54
+ * @returns Box group
55
+ */
56
+ export function buildBox(style, raw) {
57
+ const overflowX = style['overflow-x'] ?? 'visible';
58
+ const overflowY = style['overflow-y'] ?? 'visible';
59
+ const overflow = overflowX === 'visible' && overflowY === 'visible'
60
+ ? undefined
61
+ : overflowX === overflowY
62
+ ? overflowX
63
+ : `${overflowX} ${overflowY}`;
64
+ const min = sizeLimits(style, 'min');
65
+ const max = sizeLimits(style, 'max');
66
+ return {
67
+ padding: sides(style, 'padding-{side}'),
68
+ margin: sides(style, 'margin-{side}'),
69
+ border: sides(style, 'border-{side}-width'),
70
+ sizing: style['box-sizing'] ?? 'content-box',
71
+ ...(min && { min }),
72
+ ...(max && { max }),
73
+ ...(overflow && { overflow }),
74
+ ...(raw.scroll && { scroll: { w: raw.scroll.w, h: raw.scroll.h } }),
75
+ };
76
+ }
77
+ /**
78
+ * Row and column gap, when there is one.
79
+ *
80
+ * @param style - Computed styles
81
+ * @returns One length when both are equal, else row and column
82
+ */
83
+ function gapOf(style) {
84
+ const toLength = (value) => value === undefined || value === 'normal' ? 0 : cssLength(value);
85
+ const row = toLength(style['row-gap']);
86
+ const column = toLength(style['column-gap']);
87
+ if (row === 0 && column === 0)
88
+ return undefined;
89
+ return row === column ? row : [row, column];
90
+ }
91
+ /**
92
+ * Whether a display value makes a flex or grid container.
93
+ *
94
+ * @param display - Computed display
95
+ * @returns `flex`, `grid` or undefined
96
+ */
97
+ export function containerKind(display) {
98
+ if (display === undefined)
99
+ return undefined;
100
+ if (/(^|-)flex$/.test(display) || display === '-webkit-box')
101
+ return 'flex';
102
+ return /(^|-)grid$/.test(display) ? 'grid' : undefined;
103
+ }
104
+ /**
105
+ * Flex or grid container fields that are not no-op defaults (the flex
106
+ * direction is always there).
107
+ *
108
+ * @param style - Computed styles
109
+ * @returns Container fields, empty for other displays
110
+ */
111
+ export function buildContainer(style) {
112
+ const kind = containerKind(style['display']);
113
+ if (!kind)
114
+ return {};
115
+ const justify = style['justify-content'];
116
+ const align = style['align-items'];
117
+ const wrap = style['flex-wrap'];
118
+ const gap = gapOf(style);
119
+ const columns = style['grid-template-columns'] ?? 'none';
120
+ const rows = style['grid-template-rows'] ?? 'none';
121
+ return {
122
+ ...(kind === 'flex' && { direction: style['flex-direction'] ?? 'row' }),
123
+ ...(kind === 'flex' && wrap && wrap !== 'nowrap' && { wrap }),
124
+ ...(kind === 'grid' && columns !== 'none' && { columns: compressTracks(columns) }),
125
+ ...(kind === 'grid' && rows !== 'none' && { rows: compressTracks(rows) }),
126
+ ...(justify && !['normal', 'flex-start', 'start'].includes(justify) && { justify }),
127
+ ...(align && !['normal', 'stretch'].includes(align) && { align }),
128
+ ...(gap !== undefined && { gap }),
129
+ };
130
+ }
131
+ /**
132
+ * Position fields: position unless static, inset unless all `auto` (or all
133
+ * 0/auto for relative), z-index unless `auto`.
134
+ *
135
+ * @param style - Computed styles
136
+ * @returns Position fields
137
+ */
138
+ function positionFields(style) {
139
+ const position = style['position'] ?? 'static';
140
+ if (position === 'static')
141
+ return {};
142
+ const inset = sides(style, '{side}');
143
+ const allAuto = inset.every((value) => value === 'auto');
144
+ const noOffset = inset.every((value) => value === 'auto' || value === 0);
145
+ const z = style['z-index'];
146
+ return {
147
+ position,
148
+ ...(!allAuto && !(position === 'relative' && noOffset) && { inset }),
149
+ ...(z && z !== 'auto' && { z: /^-?\d+$/.test(z) ? Number(z) : z }),
150
+ };
151
+ }
152
+ /**
153
+ * Fields of an element laid out by a flex or grid parent: flex
154
+ * grow/shrink/basis (unless `0 1 auto`), self alignment, order and grid area.
155
+ *
156
+ * @param style - Computed styles
157
+ * @param parentDisplay - Display of the layout parent
158
+ * @returns Item fields, empty in other parents
159
+ */
160
+ function itemFields(style, parentDisplay) {
161
+ const parentKind = containerKind(parentDisplay);
162
+ if (!parentKind)
163
+ return {};
164
+ const flex = `${style['flex-grow'] ?? 0} ${style['flex-shrink'] ?? 1} ${cssLength(style['flex-basis'] ?? 'auto')}`;
165
+ const self = style['align-self'];
166
+ const justifySelf = style['justify-self'];
167
+ const order = Number(style['order'] ?? 0);
168
+ const placement = ['grid-row-start', 'grid-column-start', 'grid-row-end', 'grid-column-end'].map((name) => style[name] ?? 'auto');
169
+ const selfAlign = [self, parentKind === 'grid' ? justifySelf : undefined]
170
+ .filter((value) => value && value !== 'auto')
171
+ .join(' ');
172
+ return {
173
+ ...(parentKind === 'flex' && flex !== '0 1 auto' && { flex }),
174
+ ...(selfAlign && { self: selfAlign }),
175
+ ...(order !== 0 && { order }),
176
+ ...(parentKind === 'grid' &&
177
+ placement.some((value) => value !== 'auto') && { area: placement.join(' / ') }),
178
+ };
179
+ }
180
+ /**
181
+ * The parent line: its description, display, container fields and its
182
+ * text alignment (when not the start).
183
+ *
184
+ * @param parentStyle - Computed styles of the layout parent
185
+ * @param element - Its short description
186
+ * @returns Parent fields
187
+ */
188
+ function buildParent(parentStyle, element) {
189
+ const textAlign = parentStyle['text-align'];
190
+ return {
191
+ element,
192
+ display: parentStyle['display'] ?? 'block',
193
+ ...buildContainer(parentStyle),
194
+ ...(textAlign && !['start', 'left', '-webkit-auto'].includes(textAlign) && { textAlign }),
195
+ };
196
+ }
197
+ /**
198
+ * Whether an item stretches along the cross axis of its flex or grid parent.
199
+ *
200
+ * @param self - The item's `align-self`/`justify-self`
201
+ * @param items - The parent's `align-items`/`justify-items`
202
+ * @returns True for `stretch` and `normal` (stretch for non-replaced items)
203
+ */
204
+ function stretches(self, items) {
205
+ const effective = self === 'auto' ? (items ?? 'normal') : self;
206
+ return effective === 'normal' || effective === 'stretch';
207
+ }
208
+ /**
209
+ * How the element is sized along an axis inside a flex parent.
210
+ *
211
+ * @param input - Sizing inputs
212
+ * @param automatic - The size is `auto` (or content-based)
213
+ * @returns Sizing mode
214
+ */
215
+ function flexItemSizing(input, automatic) {
216
+ const mainAxis = (input.parentDirection ?? 'row').startsWith('row') ? 'w' : 'h';
217
+ if (input.axis === mainAxis) {
218
+ if (input.flexGrow > 0)
219
+ return 'fill';
220
+ if (!['auto', 'content'].includes(input.flexBasis))
221
+ return 'fixed';
222
+ return automatic ? 'hug' : 'fixed';
223
+ }
224
+ if (automatic && input.size === 'auto' && stretches(input.alignSelf, input.parentAlignItems)) {
225
+ return 'fill';
226
+ }
227
+ return automatic ? 'hug' : input.size === '100%' ? 'fill' : 'fixed';
228
+ }
229
+ /**
230
+ * Sizing of a replaced element with an automatic size: its intrinsic size
231
+ * (hug), unless it grows along a flex main axis or is stretched explicitly
232
+ * (`normal` alignment does not stretch replaced elements).
233
+ *
234
+ * @param input - Computed size, display and the parent's layout
235
+ * @returns Sizing mode
236
+ */
237
+ function replacedSizing(input) {
238
+ const kind = containerKind(input.parentDisplay);
239
+ const mainAxis = (input.parentDirection ?? 'row').startsWith('row') ? 'w' : 'h';
240
+ if (kind === 'flex' && input.axis === mainAxis && input.flexGrow > 0)
241
+ return 'fill';
242
+ const self = input.axis === 'w' && kind === 'grid' ? input.justifySelf : input.alignSelf;
243
+ return kind && self === 'stretch' ? 'fill' : 'hug';
244
+ }
245
+ /**
246
+ * How the element is sized along an axis: `fill` when its parent stretches
247
+ * it (a flex item that grows, a stretched cross axis or grid cell, a block's
248
+ * width in normal flow, 100%), `hug` when its content sizes it (`auto` and
249
+ * the content keywords elsewhere), `fixed` for a length.
250
+ *
251
+ * @param input - Computed size, display and the parent's layout
252
+ * @returns Sizing mode
253
+ */
254
+ export function deriveSizing(input) {
255
+ const automatic = /^(auto|fit-content|max-content|min-content)$/.test(input.size) || input.size === '';
256
+ if (input.display === 'inline')
257
+ return 'hug';
258
+ if (input.replaced && automatic)
259
+ return replacedSizing(input);
260
+ if (input.position === 'absolute' || input.position === 'fixed')
261
+ return automatic ? 'hug' : 'fixed';
262
+ const parentKind = containerKind(input.parentDisplay);
263
+ if (parentKind === 'flex')
264
+ return flexItemSizing(input, automatic);
265
+ if (parentKind === 'grid' && input.size === 'auto') {
266
+ const fills = input.axis === 'w'
267
+ ? stretches(input.justifySelf, input.parentJustifyItems)
268
+ : stretches(input.alignSelf, input.parentAlignItems);
269
+ return fills ? 'fill' : 'hug';
270
+ }
271
+ if (input.size === '100%')
272
+ return 'fill';
273
+ if (!automatic)
274
+ return 'fixed';
275
+ const blockLevel = !/^inline|^table$/.test(input.display) && input.float === 'none';
276
+ return input.axis === 'w' && input.size === 'auto' && blockLevel ? 'fill' : 'hug';
277
+ }
278
+ /**
279
+ * Sizing along both axes.
280
+ *
281
+ * @param style - Computed styles
282
+ * @param parentStyle - Computed styles of the layout parent
283
+ * @param raw - Computed (not resolved) width and height, and whether the element is replaced
284
+ * @returns Width and height sizing
285
+ */
286
+ function sizingOf(style, parentStyle, raw) {
287
+ const typed = raw.typed;
288
+ const base = {
289
+ ...(raw.replaced && { replaced: true }),
290
+ display: style['display'] ?? 'inline',
291
+ position: style['position'] ?? 'static',
292
+ float: style['float'] ?? 'none',
293
+ flexGrow: Number(style['flex-grow'] ?? 0),
294
+ flexBasis: style['flex-basis'] ?? 'auto',
295
+ alignSelf: style['align-self'] ?? 'auto',
296
+ justifySelf: style['justify-self'] ?? 'auto',
297
+ ...(parentStyle && {
298
+ parentDisplay: parentStyle['display'] ?? 'block',
299
+ parentDirection: parentStyle['flex-direction'] ?? 'row',
300
+ parentAlignItems: parentStyle['align-items'] ?? 'normal',
301
+ parentJustifyItems: parentStyle['justify-items'] ?? 'normal',
302
+ }),
303
+ };
304
+ return {
305
+ w: deriveSizing({ ...base, size: typed.width, axis: 'w' }),
306
+ h: deriveSizing({ ...base, size: typed.height, axis: 'h' }),
307
+ };
308
+ }
309
+ /**
310
+ * Round each value of a record of distances.
311
+ *
312
+ * @param distances - Distances in CSS px
313
+ * @returns Rounded distances
314
+ */
315
+ function rounded(distances) {
316
+ return Object.fromEntries(Object.entries(distances).map(([key, value]) => [key, round1(value)]));
317
+ }
318
+ /**
319
+ * The layout group: display, position, container and item fields, valign
320
+ * for inline displays, float, sizing, and the parent with the element's
321
+ * place in it (offsets from its content edges, gaps to the siblings).
322
+ *
323
+ * @param style - Computed styles
324
+ * @param parentStyle - Computed styles of the layout parent (none for the root)
325
+ * @param raw - Page-side measurements
326
+ * @returns Layout group
327
+ */
328
+ export function buildLayout(style, parentStyle, raw) {
329
+ const display = style['display'] ?? 'inline';
330
+ const valign = style['vertical-align'];
331
+ const float = style['float'];
332
+ const siblings = raw.siblings && Object.keys(raw.siblings).length > 0 ? raw.siblings : undefined;
333
+ return {
334
+ display,
335
+ ...positionFields(style),
336
+ ...buildContainer(style),
337
+ ...itemFields(style, parentStyle?.['display']),
338
+ ...(/^inline|table-cell/.test(display) && valign && valign !== 'baseline' && { valign }),
339
+ ...(float && float !== 'none' && { float }),
340
+ ...(display !== 'none' && { sizing: sizingOf(style, parentStyle, raw) }),
341
+ ...(parentStyle && raw.parent && { parent: buildParent(parentStyle, raw.parent) }),
342
+ ...(raw.inParent && { inParent: rounded(raw.inParent) }),
343
+ ...(siblings && { siblings: rounded(siblings) }),
344
+ };
345
+ }
346
+ //# sourceMappingURL=inspectLayoutModel.js.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Assemble the `bdg dom inspect` result from what CDP and the page-side walk
3
+ * read: the header (label, text, rect, what keeps it from being seen), then
4
+ * the groups (or, with `--all`/`--props`, the property lists) and the child
5
+ * tree. Pure: every input is plain data, so the rules are tested without a
6
+ * browser.
7
+ */
8
+ import type { Protocol } from '../../connection/typed-cdp.js';
9
+ import type { ElementLayout } from '../../ipc/protocol/domTypes.js';
10
+ import type { InspectResult, InspectVisibility } from '../../ipc/protocol/inspectTypes.js';
11
+ import { type StyleMap } from './inspectLayoutModel.js';
12
+ import { type PlatformFont, type PseudoSource } from './inspectPaintModel.js';
13
+ import type { RawInspect } from './inspectScripts.js';
14
+ /** What one inspect read */
15
+ export interface InspectSources {
16
+ raw: RawInspect;
17
+ style: StyleMap;
18
+ parentStyle?: StyleMap;
19
+ pseudo: PseudoSource[];
20
+ fonts: PlatformFont[];
21
+ /** Border box size from `DOM.getBoxModel`; absent when the element has no box */
22
+ size?: {
23
+ w: number;
24
+ h: number;
25
+ };
26
+ /** The element as `dom layout` measures it */
27
+ layout?: ElementLayout;
28
+ colorScheme?: 'light' | 'dark';
29
+ /** Matched rules for the cascade fields; `timeout` or `failed` when they were not read */
30
+ matched?: Protocol.CSS.GetMatchedStylesForNodeResponse | 'timeout' | 'failed';
31
+ /** `--rules` was asked for */
32
+ rules?: boolean;
33
+ /** `--why` property */
34
+ why?: string;
35
+ /** `--props` names, custom property patterns expanded (`--rules` covers only these) */
36
+ props?: string[];
37
+ /** `--no-hints` */
38
+ hints?: false;
39
+ }
40
+ /** What the command asked for */
41
+ export interface InspectRequest {
42
+ selector: string;
43
+ index: number;
44
+ count: number;
45
+ /** Tree rows shown at most */
46
+ treeLimit: number;
47
+ all?: boolean;
48
+ /** `--props` values (from `selectedProps`) */
49
+ propValues?: InspectResult['props'];
50
+ }
51
+ /**
52
+ * The element's label: tag, id and the first classes, with a count of the rest.
53
+ *
54
+ * @param raw - Tag, id and classes
55
+ * @returns e.g. `a.z-1.max-sm:hidden(+11)`, `input#user-name`
56
+ */
57
+ export declare function elementLabel(raw: Pick<RawInspect, 'tag' | 'id' | 'classes'>): string;
58
+ /**
59
+ * Why the element cannot be seen, from `dom layout`'s measurements.
60
+ *
61
+ * @param layout - Layout measurements
62
+ * @param rendered - The element has a box
63
+ * @returns Visibility fields
64
+ */
65
+ export declare function visibilityOf(layout: ElementLayout | undefined, rendered: boolean): InspectVisibility;
66
+ /**
67
+ * The `bdg dom inspect` result.
68
+ *
69
+ * @param sources - What CDP and the page-side walk read
70
+ * @param request - Selector, index, match count and options
71
+ * @returns Inspect result
72
+ */
73
+ export declare function buildInspectResult(sources: InspectSources, request: InspectRequest): InspectResult;
74
+ //# sourceMappingURL=inspectModel.d.ts.map
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Assemble the `bdg dom inspect` result from what CDP and the page-side walk
3
+ * read: the header (label, text, rect, what keeps it from being seen), then
4
+ * the groups (or, with `--all`/`--props`, the property lists) and the child
5
+ * tree. Pure: every input is plain data, so the rules are tested without a
6
+ * browser.
7
+ */
8
+ import { allStyles } from './inspectAllStyles.js';
9
+ import { buildBox, buildLayout } from './inspectLayoutModel.js';
10
+ import { buildEffects, buildFills, buildFx, buildOutline, buildPseudo, buildRadius, buildState, buildStrokes, buildText, effectiveBackground, } from './inspectPaintModel.js';
11
+ import { buildTree, rowText } from './inspectTree.js';
12
+ import { hexColor, relativeLuminance } from '../../utils/color.js';
13
+ import { normalizeCssValue, round1 } from '../../utils/cssValues.js';
14
+ /** Classes shown in the label (the rest are counted) */
15
+ const LABEL_CLASSES = 2;
16
+ /**
17
+ * The element's label: tag, id and the first classes, with a count of the rest.
18
+ *
19
+ * @param raw - Tag, id and classes
20
+ * @returns e.g. `a.z-1.max-sm:hidden(+11)`, `input#user-name`
21
+ */
22
+ export function elementLabel(raw) {
23
+ const shown = raw.classes
24
+ .slice(0, LABEL_CLASSES)
25
+ .map((name) => `.${name}`)
26
+ .join('');
27
+ const more = raw.classes.length - LABEL_CLASSES;
28
+ return `${raw.tag}${raw.id ? `#${raw.id}` : ''}${shown}${more > 0 ? `(+${more})` : ''}`;
29
+ }
30
+ /**
31
+ * Why the element cannot be seen, from `dom layout`'s measurements.
32
+ *
33
+ * @param layout - Layout measurements
34
+ * @param rendered - The element has a box
35
+ * @returns Visibility fields
36
+ */
37
+ export function visibilityOf(layout, rendered) {
38
+ if (!rendered)
39
+ return { notRendered: true, ...(layout?.hiddenReason && { hidden: layout.hiddenReason }) };
40
+ if (!layout)
41
+ return {};
42
+ const hidden = layout.inViewport === 'hidden' ? layout.hiddenReason : layout.invisible;
43
+ const offscreen = ['above', 'below', 'left', 'right'].includes(layout.inViewport)
44
+ ? layout.inViewport
45
+ : undefined;
46
+ return {
47
+ ...(hidden && { hidden }),
48
+ ...(offscreen && { offscreen }),
49
+ ...(layout.coveredBy && { coveredBy: layout.coveredBy }),
50
+ ...(layout.coverTransparent && { coverTransparent: true }),
51
+ };
52
+ }
53
+ /** Below this relative luminance a page background counts as dark */
54
+ const DARK_LUMINANCE = 0.18;
55
+ /**
56
+ * Header fields: label, text, placeholder, context, rect, visibility and
57
+ * the color scheme.
58
+ *
59
+ * @param sources - What was read
60
+ * @param request - Selector, index and match count
61
+ * @returns Header part of the result
62
+ */
63
+ function header(sources, request) {
64
+ const { raw, size, layout } = sources;
65
+ const content = raw.textual && raw.content ? rowText(raw.content) : undefined;
66
+ return {
67
+ success: true,
68
+ selector: request.selector,
69
+ count: request.count,
70
+ index: request.index,
71
+ element: elementLabel(raw),
72
+ ...(content && { content }),
73
+ ...(raw.placeholder && { placeholder: rowText(raw.placeholder) }),
74
+ ...(raw.context && { context: raw.context }),
75
+ ...(size &&
76
+ layout && {
77
+ rect: { x: layout.bounds.x, y: layout.bounds.y, w: round1(size.w), h: round1(size.h) },
78
+ }),
79
+ visibility: visibilityOf(layout, size !== undefined),
80
+ ...(sources.colorScheme && { colorScheme: sources.colorScheme }),
81
+ ...(sources.colorScheme === 'dark' && pageLooksDark(raw) && { theme: 'dark' }),
82
+ ...(raw.animating.length > 0 && { animating: raw.animating }),
83
+ };
84
+ }
85
+ /**
86
+ * Whether the page renders dark: a dark canvas (its color-scheme), or a dark
87
+ * background on the page's root (the backgrounds of body and html).
88
+ *
89
+ * @param raw - Backgrounds from the element up to the root, and the canvas
90
+ * @returns True for a dark page
91
+ */
92
+ function pageLooksDark(raw) {
93
+ if (raw.canvasDark)
94
+ return true;
95
+ const root = effectiveBackground(raw.backgrounds.slice(-2), false).color;
96
+ return relativeLuminance(root) < DARK_LUMINANCE;
97
+ }
98
+ /**
99
+ * The style groups: box, layout, text, fills, strokes, radius, outline,
100
+ * effects, fx, state and pseudo-elements.
101
+ *
102
+ * @param sources - What was read
103
+ * @returns Group fields
104
+ */
105
+ function groups(sources) {
106
+ const { style, parentStyle, raw } = sources;
107
+ const text = buildText(style, parentStyle, raw, sources.fonts);
108
+ const fills = buildFills(style);
109
+ const strokes = buildStrokes(style);
110
+ const radius = buildRadius(style);
111
+ const outline = buildOutline(style);
112
+ const effects = buildEffects(style);
113
+ const fx = buildFx(style);
114
+ const state = buildState(style, raw);
115
+ const pseudo = buildPseudo(sources.pseudo, style, raw);
116
+ const opacity = Number(style['opacity'] ?? 1);
117
+ const blend = style['mix-blend-mode'];
118
+ return {
119
+ box: buildBox(style, raw),
120
+ layout: buildLayout(style, parentStyle, raw),
121
+ ...(text && { text }),
122
+ ...(fills.length > 0 && { fills }),
123
+ ...(opacity !== 1 && { opacity }),
124
+ ...(blend && blend !== 'normal' && { blend }),
125
+ ...(strokes.length > 0 && { strokes }),
126
+ ...(radius && { radius }),
127
+ ...(outline && { outline }),
128
+ ...(effects.length > 0 && { effects }),
129
+ ...(fx && { fx }),
130
+ ...(state && { state }),
131
+ ...(pseudo && { pseudo }),
132
+ };
133
+ }
134
+ /**
135
+ * The child tree fields.
136
+ *
137
+ * @param raw - Page-side walk
138
+ * @param limit - Rows shown at most
139
+ * @returns Children, hidden count and rows left out
140
+ */
141
+ function treeFields(raw, limit) {
142
+ if (!raw.tree)
143
+ return {};
144
+ const { children, moreRows } = buildTree(raw.tree, limit, raw.treeSkipped);
145
+ return {
146
+ ...(children.length > 0 && { children }),
147
+ ...(raw.hiddenChildren > 0 && { hiddenChildren: raw.hiddenChildren }),
148
+ ...(moreRows > 0 && { moreRows }),
149
+ };
150
+ }
151
+ /**
152
+ * The `--all` list: the element's own non-default longhands, plus its
153
+ * generated pseudo-elements' content and the placeholder color.
154
+ *
155
+ * @param sources - What was read
156
+ * @returns Properties and values
157
+ */
158
+ function allFields(sources) {
159
+ const all = allStyles(sources.style, sources.raw.svg === true);
160
+ for (const pseudo of sources.pseudo) {
161
+ const content = pseudo.style['content'];
162
+ if (content && content !== 'none' && content !== 'normal') {
163
+ all[`${pseudo.type}`] = normalizeCssValue(content);
164
+ }
165
+ }
166
+ if (sources.raw.placeholderColor)
167
+ all['::placeholder'] = `color ${hexColor(sources.raw.placeholderColor)}`;
168
+ return all;
169
+ }
170
+ /**
171
+ * The `bdg dom inspect` result.
172
+ *
173
+ * @param sources - What CDP and the page-side walk read
174
+ * @param request - Selector, index, match count and options
175
+ * @returns Inspect result
176
+ */
177
+ export function buildInspectResult(sources, request) {
178
+ const result = header(sources, request);
179
+ if (request.propValues)
180
+ return { ...result, props: request.propValues };
181
+ const body = request.all ? { all: allFields(sources) } : groups(sources);
182
+ return { ...result, ...body, ...treeFields(sources.raw, request.treeLimit) };
183
+ }
184
+ //# sourceMappingURL=inspectModel.js.map