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
@@ -1,28 +1,17 @@
1
+ import { keyAttributeItems } from './keyAttributes.js';
1
2
  import { OutputFormatter } from '../formatting.js';
2
- import { evalFrameLine, frameLabel, moreMatchesNote, noFramesMessage, } from '../messages/commands.js';
3
- import { parseSelectorFilters } from '../../utils/selectorFilters.js';
3
+ import { frameLabel, moreMatchesNote, framesStillLoadingNote, noFramesMessage, queryNextSteps, screenshotGrownNote, viewportPositionHint, } from '../messages/commands.js';
4
4
  /** Matches listed in human output (JSON has all of them) */
5
5
  const QUERY_DISPLAY_LIMIT = 50;
6
- /**
7
- * A shell-quoted `dom eval` script reading the text (or a field's value) of
8
- * the n-th match in the main document, as rendered (null for matches inside iframes or
9
- * shadow roots, which `document.querySelectorAll` does not reach).
10
- *
11
- * @param selector - CSS selector
12
- * @param index - Match to read
13
- * @returns Single-quoted script, safe to paste into a shell
14
- */
15
- function textExtractionScript(selector, index) {
16
- const script = `(el => el && (el.value ?? el.innerText))(document.querySelectorAll(${JSON.stringify(selector)})[${index}])`;
17
- return `'${script.replace(/'/g, `'\\''`)}'`;
18
- }
19
6
  /**
20
7
  * Format DOM query results for human-readable output.
21
8
  *
22
- * Displays found nodes with their index, tag, classes, and preview text,
23
- * up to {@link QUERY_DISPLAY_LIMIT} of them (no match is an error, exit 83).
24
- * The text extraction hint is left out for selectors with text or visibility
25
- * filters, which `document.querySelectorAll` does not understand.
9
+ * Displays found nodes with their index, tag, identifying attributes
10
+ * ({@link queryTagAttributes}), classes, and preview text
11
+ * (plus where they are when outside the viewport or hidden, e.g.
12
+ * `(below fold)`), up to {@link QUERY_DISPLAY_LIMIT} of them (no match is an error, exit 83).
13
+ * One line of next commands follows; they take the match's index, so they
14
+ * work for matches in shadow roots and iframes too.
26
15
  *
27
16
  * @param data - DOM query result containing selector, count, and matching nodes
28
17
  * @returns Formatted output string
@@ -47,33 +36,43 @@ export function formatDomQuery(data) {
47
36
  const { count, nodes, selector } = data;
48
37
  const fmt = new OutputFormatter();
49
38
  const nodeLines = nodes.slice(0, QUERY_DISPLAY_LIMIT).map((node) => {
50
- const attributes = [
51
- node.id && ` id="${node.id}"`,
52
- node.name && ` name="${node.name}"`,
53
- node.type && ` type="${node.type}"`,
54
- node.classes?.length && ` class="${node.classes.join(' ')}"`,
55
- ]
56
- .filter(Boolean)
39
+ const attributes = queryTagAttributes(node)
40
+ .map((item) => ` ${item}`)
57
41
  .join('');
58
42
  const context = node.context ? ` (in ${node.context})` : '';
59
43
  const preview = node.preview ? ` ${node.preview}` : '';
60
- return `[${node.index}] <${node.tag}${attributes}>${context}${preview}`;
44
+ const position = node.inViewport && viewportPositionHint(node.inViewport, node.clippedBy);
45
+ const location = position ? ` (${position})` : '';
46
+ return `[${node.index}] <${node.tag}${attributes}>${context}${preview}${location}`;
61
47
  });
62
- const hasMultipleResults = count > 1;
63
- const exampleIndex = hasMultipleResults ? (nodes[0]?.index ?? 0) : 0;
48
+ const exampleIndex = nodes[0]?.index ?? 0;
64
49
  return fmt
65
50
  .text(`Found ${count} node${count === 1 ? '' : 's'} matching "${selector}":`)
66
51
  .list(nodeLines)
67
52
  .list(count > QUERY_DISPLAY_LIMIT ? [moreMatchesNote(count - QUERY_DISPLAY_LIMIT)] : [])
68
- .hints('Next steps:', [
69
- `Get HTML: bdg dom get ${exampleIndex} --raw`,
70
- `Accessibility: bdg dom get ${exampleIndex}`,
71
- ...(parseSelectorFilters(selector)
72
- ? []
73
- : [`Extract text: bdg dom eval ${textExtractionScript(selector, exampleIndex)}`]),
74
- ])
53
+ .tip(queryNextSteps(exampleIndex))
75
54
  .build();
76
55
  }
56
+ /**
57
+ * The attributes shown in a `dom query` match's tag: id, then name, type and
58
+ * the key attributes of its type ({@link keyAttributeItems}: an image's file
59
+ * name and alt, a link's href, a field's placeholder and value), then class.
60
+ *
61
+ * @param node - Query match
62
+ * @returns `name="value"` items
63
+ */
64
+ function queryTagAttributes(node) {
65
+ const identifying = {
66
+ ...(node.name && { name: node.name }),
67
+ ...(node.type && { type: node.type }),
68
+ ...(node.value !== undefined && { value: node.value }),
69
+ };
70
+ return [
71
+ ...(node.id ? [`id="${node.id}"`] : []),
72
+ ...keyAttributeItems(node.tag ?? '', { ...identifying, ...node.attributes }),
73
+ ...(node.classes?.length ? [`class="${node.classes.join(' ')}"`] : []),
74
+ ];
75
+ }
77
76
  /**
78
77
  * Format DOM get results for human-readable output.
79
78
  *
@@ -118,18 +117,23 @@ export function formatDomGet(data) {
118
117
  /**
119
118
  * Format DOM eval results for human-readable output.
120
119
  *
121
- * Outputs the evaluated JavaScript result as formatted JSON, preceded by a
122
- * `Frame: <url>` line when it ran in an iframe (`--frame`).
120
+ * A string result is printed as is (not JSON-quoted), so text reads and
121
+ * pipes like `echo`, unless that would read as another value (empty,
122
+ * `undefined`, or valid JSON such as `42` or `[1,2]`): then it stays
123
+ * JSON-quoted. Other values are formatted JSON, and values Chrome only
124
+ * describes (functions, DOM nodes) their description. The iframe it ran in
125
+ * (`--frame`) is reported on stderr, so stdout stays the bare value. `--json`
126
+ * output is unchanged (the value in `data.result`).
123
127
  *
124
- * @param data - DOM eval result containing the evaluated value (and its frame)
125
- * @returns Formatted JSON string
128
+ * @param data - DOM eval result containing the evaluated value
129
+ * @returns The string, or formatted JSON
126
130
  *
127
131
  * @example
128
132
  * ```typescript
129
- * formatDomEval({ result: 'My Page Title' });
130
- * // Output: "My Page Title"
133
+ * formatDomEval({ result: 'My Page Title', type: 'string' });
134
+ * // Output: My Page Title
131
135
  *
132
- * formatDomEval({ result: { url: 'https://example.com', title: 'Example' } });
136
+ * formatDomEval({ result: { url: 'https://example.com', title: 'Example' }, type: 'object' });
133
137
  * // Output:
134
138
  * // {
135
139
  * // "url": "https://example.com",
@@ -138,39 +142,58 @@ export function formatDomGet(data) {
138
142
  * ```
139
143
  */
140
144
  export function formatDomEval(data) {
141
- const value = formatEvalValue(data);
142
- return data.frame === undefined ? value : `${evalFrameLine(data.frame)}\n${value}`;
145
+ if (data.type === 'undefined')
146
+ return 'undefined';
147
+ const { result } = data;
148
+ if (typeof result === 'string' && (data.type !== 'string' || !looksLikeOtherValue(result))) {
149
+ return result;
150
+ }
151
+ return JSON.stringify(result ?? null, null, 2);
143
152
  }
144
153
  /**
145
- * Format an eval result value: descriptions as is, JSON values pretty-printed.
154
+ * Whether a string printed as is would read as another value: empty,
155
+ * `undefined`, or valid JSON (`42`, `true`, `null`, `[1,2]`, `{"a":1}`).
146
156
  *
147
- * @param data - Result value and its JavaScript type
148
- * @returns Formatted value
157
+ * @param text - String result
158
+ * @returns True when it must be JSON-quoted to read as a string
149
159
  */
150
- function formatEvalValue(data) {
151
- if (data.type === 'undefined')
152
- return 'undefined';
153
- const isDescription = typeof data.result === 'string' && data.type !== 'string';
154
- if (isDescription)
155
- return data.result;
156
- return JSON.stringify(data.result ?? null, null, 2);
160
+ function looksLikeOtherValue(text) {
161
+ if (text === '' || text === 'undefined')
162
+ return true;
163
+ try {
164
+ JSON.parse(text);
165
+ return true;
166
+ }
167
+ catch {
168
+ return false;
169
+ }
157
170
  }
158
171
  /**
159
- * Format the page's iframes, one per line.
172
+ * Format the page's iframes, one per line, nested frames indented below
173
+ * their parent. While the page is still loading (`readyState` set), the list
174
+ * may be incomplete, and says so.
160
175
  *
161
- * @param data - Frames from `bdg dom frames`
176
+ * @param data - Frames from `bdg dom frames`, with the readyState of a page still loading
162
177
  * @returns Formatted list
163
178
  *
164
179
  * @example
165
180
  * ```
166
181
  * [0] http://localhost:3000/widget name=widget same-origin
167
182
  * [1] https://pay.example/ #checkout cross-origin, out-of-process
183
+ * [2] about:blank same-origin
168
184
  * ```
169
185
  */
170
186
  export function formatDomFrames(data) {
187
+ const loading = data.readyState !== undefined && data.readyState !== 'complete';
171
188
  if (data.frames.length === 0)
172
- return noFramesMessage();
173
- return data.frames.map(frameLabel).join('\n');
189
+ return loading ? framesStillLoadingNote(true) : noFramesMessage();
190
+ const depthOf = new Map();
191
+ const lines = data.frames.map((frame) => {
192
+ const depth = frame.parentIndex === undefined ? 0 : (depthOf.get(frame.parentIndex) ?? 0) + 1;
193
+ depthOf.set(frame.index, depth);
194
+ return ' '.repeat(depth) + frameLabel(frame);
195
+ });
196
+ return [...lines, ...(loading ? [framesStillLoadingNote(false)] : [])].join('\n');
174
197
  }
175
198
  /**
176
199
  * Format screenshot capture result for human-readable display.
@@ -187,6 +210,9 @@ export function formatDomFrames(data) {
187
210
  *
188
211
  * formatDomScreenshot({ path: './page.png', fullPageSkipped: { reason: 'page_too_tall', ... } });
189
212
  * // Output: Screenshot saved to ./page.png (viewport only - page too tall)
213
+ *
214
+ * // An element whose floated children overflow it
215
+ * // Output: Screenshot saved to ./el.png (grown from 940×37 to 940×285 to include content overflowing the element)
190
216
  * ```
191
217
  */
192
218
  export function formatDomScreenshot(data) {
@@ -194,6 +220,9 @@ export function formatDomScreenshot(data) {
194
220
  if (data.fullPageSkipped && !data.scrolledTo) {
195
221
  output += ' (viewport only - page too tall)';
196
222
  }
223
+ if (data.element?.captured) {
224
+ output += ` (${screenshotGrownNote(data.element.bounds, data.element.captured)})`;
225
+ }
197
226
  return output;
198
227
  }
199
228
  //# sourceMappingURL=dom.js.map
@@ -5,6 +5,7 @@
5
5
  * values, validation state, and suggested commands.
6
6
  */
7
7
  import { OutputFormatter, areHintsHidden } from '../formatting.js';
8
+ import { REQUIRED_FIELD_EMPTY_REASON, formReadinessMessage, requiredFieldsEmptyMessage, } from '../messages/commands.js';
8
9
  const COLUMN_WIDTHS = {
9
10
  index: 4,
10
11
  type: 12,
@@ -64,6 +65,9 @@ function formatFieldValue(field) {
64
65
  * @returns Status string with icon
65
66
  */
66
67
  function formatFieldStatus(field) {
68
+ if (field.hidden) {
69
+ return 'hidden';
70
+ }
67
71
  if (field.disabled) {
68
72
  return 'disabled';
69
73
  }
@@ -127,12 +131,23 @@ function formatButtonRow(button) {
127
131
  * @returns Header string
128
132
  */
129
133
  function formatFormHeader(form) {
130
- let header = `Form: "${form.name ?? 'Unnamed'}"`;
134
+ let header = `Form: "${form.name ?? 'Unnamed'}"${formVisibilityMarker(form)}`;
131
135
  if (form.step) {
132
136
  header += ` (step ${form.step.current} of ${form.step.total})`;
133
137
  }
134
138
  return header;
135
139
  }
140
+ /**
141
+ * Marker of a form shown in an open dialog or not shown at all.
142
+ *
143
+ * @param form - Form (or its listing in "Other forms")
144
+ * @returns ` (in dialog)`, ` (hidden)`, or empty
145
+ */
146
+ function formVisibilityMarker(form) {
147
+ if (form.hidden)
148
+ return ' (hidden)';
149
+ return form.inDialog ? ' (in dialog)' : '';
150
+ }
136
151
  /**
137
152
  * Format table header row.
138
153
  *
@@ -147,7 +162,9 @@ function formatTableHeader() {
147
162
  return `${idx} ${type} ${label} ${value} ${status}`;
148
163
  }
149
164
  /**
150
- * Format summary line.
165
+ * Format summary line, e.g. "Summary: 1/3 fields filled | 2 required fields
166
+ * empty: Last Name, Zip | NOT ready" (a radio or checkbox group counts as one
167
+ * field).
151
168
  *
152
169
  * @param summary - Form summary
153
170
  * @returns Summary string
@@ -158,15 +175,12 @@ function formatSummaryLine(summary) {
158
175
  if (summary.invalidFields > 0) {
159
176
  parts.push(`${summary.invalidFields} invalid`);
160
177
  }
161
- if (summary.requiredRemaining > 0) {
162
- parts.push(`${summary.requiredRemaining} required remaining`);
163
- }
164
- if (summary.readyToSubmit) {
165
- parts.push('READY to submit');
166
- }
167
- else {
168
- parts.push('NOT ready');
169
- }
178
+ const requiredEmpty = summary.blockers
179
+ .filter((blocker) => blocker.reason === REQUIRED_FIELD_EMPTY_REASON)
180
+ .map((blocker) => blocker.label);
181
+ if (requiredEmpty.length > 0)
182
+ parts.push(requiredFieldsEmptyMessage(requiredEmpty));
183
+ parts.push(formReadinessMessage(summary));
170
184
  return `Summary: ${parts.join(' | ')}`;
171
185
  }
172
186
  /**
@@ -197,9 +211,7 @@ function formatSingleForm(form, fmt, brief = false) {
197
211
  fmt.text(formatTableHeader());
198
212
  fmt.text('─'.repeat(70));
199
213
  for (const field of form.fields) {
200
- if (!field.hidden) {
201
- fmt.text(formatFieldRow(field));
202
- }
214
+ fmt.text(formatFieldRow(field));
203
215
  }
204
216
  if (form.buttons.length > 0) {
205
217
  fmt.text('─'.repeat(70));
@@ -228,13 +240,12 @@ function formatBriefFields(form, fmt) {
228
240
  fmt.text('IDX TYPE LABEL REQ VALUE');
229
241
  fmt.text('─'.repeat(70));
230
242
  for (const field of form.fields) {
231
- if (field.hidden)
232
- continue;
233
243
  const idx = `[${field.index}]`.padEnd(4);
234
244
  const type = (field.inputType ?? field.type).slice(0, 11).padEnd(12);
235
245
  const label = (field.label ?? field.name ?? '(no label)').slice(0, 23).padEnd(24);
236
246
  const req = (field.required ? '*' : '').padEnd(3);
237
- fmt.text(`${idx} ${type} ${label} ${req} ${formatFieldValue(field)}`);
247
+ const hidden = field.hidden ? ' (hidden)' : '';
248
+ fmt.text(`${idx} ${type} ${label} ${req} ${formatFieldValue(field)}${hidden}`);
238
249
  }
239
250
  if (form.buttons.length > 0) {
240
251
  fmt.text('─'.repeat(70));
@@ -258,7 +269,7 @@ function formatOtherForms(others, fmt) {
258
269
  fmt.blank();
259
270
  fmt.text('Other forms on page:');
260
271
  for (const form of others) {
261
- fmt.text(` Form ${form.index}: "${form.name ?? 'Unnamed'}" - ${form.fieldCount} field(s)`);
272
+ fmt.text(` Form ${form.index}: "${form.name ?? 'Unnamed'}"${formVisibilityMarker(form)} - ${form.fieldCount} field(s)`);
262
273
  }
263
274
  fmt.blank();
264
275
  fmt.text('Use --all to see all forms');
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Human output of `bdg dom inspect`: a header line, then one line per group
3
+ * in Figma's order with DevTools' names (box, layout, parent, text, fill,
4
+ * border, fx, state, pseudo), then the child tree. Fields within a line are
5
+ * separated by ` · `; lengths are CSS px without the unit.
6
+ *
7
+ * ```
8
+ * button#buy.btn "Buy now" 120x41 @20,20 [flex] [prefers light]
9
+ * box p 12 24 · b 1
10
+ * layout inline-flex row · gap 8
11
+ * parent div.card flex column · gap 16 · in-parent l0 t0 r180 b0 · sib b16
12
+ * text Inter (webfont) 600 16/24 · color #fff · contrast 5.17 AA
13
+ * fill bg #1c69e3
14
+ * border 1 solid #32447f · radius 8
15
+ * ```
16
+ */
17
+ import type { InspectResult } from '../../ipc/protocol/inspectTypes.js';
18
+ import type { IndexSource } from '../../types.js';
19
+ /** `bdg dom inspect` data (the `success` flag is implied by the envelope), with the list an index refers to */
20
+ export type InspectOutput = Omit<InspectResult, 'success'> & {
21
+ indexSource?: IndexSource | undefined;
22
+ };
23
+ /**
24
+ * The header: label, text, size and position, layout badge, what keeps it
25
+ * from being seen, where it lives and the color scheme.
26
+ *
27
+ * @param data - Inspect result
28
+ * @returns Header line
29
+ */
30
+ export declare function inspectHeader(data: InspectOutput): string;
31
+ /**
32
+ * Format `bdg dom inspect` output (`--why` answers only its question:
33
+ * the header, hints and the declarations, no style groups or tree).
34
+ *
35
+ * @param data - Inspect result
36
+ * @returns Formatted output
37
+ */
38
+ export declare function formatInspect(data: InspectOutput): string;
39
+ //# sourceMappingURL=inspect.d.ts.map