browser-debugger-cli 0.9.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 (133) hide show
  1. package/README.md +4 -1
  2. package/dist/commands/dom/a11y.js +2 -1
  3. package/dist/commands/dom/formInteraction.js +56 -25
  4. package/dist/commands/dom/helpers/keyAttributes.d.ts +20 -0
  5. package/dist/commands/dom/helpers/keyAttributes.js +54 -0
  6. package/dist/commands/dom/helpers/query.d.ts +1 -1
  7. package/dist/commands/dom/helpers/query.js +66 -19
  8. package/dist/commands/dom/helpers/runElementCommand.js +4 -3
  9. package/dist/commands/dom/helpers/screenshot.js +85 -12
  10. package/dist/commands/dom/index.d.ts +1 -0
  11. package/dist/commands/dom/index.js +8 -3
  12. package/dist/commands/dom/inspect.d.ts +15 -0
  13. package/dist/commands/dom/inspect.js +82 -0
  14. package/dist/commands/dom/layout.js +2 -2
  15. package/dist/commands/dom/listeners.js +2 -2
  16. package/dist/commands/dom/semanticUtils.d.ts +14 -1
  17. package/dist/commands/dom/semanticUtils.js +44 -3
  18. package/dist/commands/network/list.js +13 -2
  19. package/dist/commands/optionBehaviors.js +48 -6
  20. package/dist/commands/page.d.ts +1 -1
  21. package/dist/commands/page.js +62 -3
  22. package/dist/commands/shared/commonOptions.d.ts +4 -0
  23. package/dist/commands/shared/commonOptions.js +9 -0
  24. package/dist/commands/shared/optionTypes.d.ts +21 -0
  25. package/dist/commands/shared/startHelpers.d.ts +66 -0
  26. package/dist/commands/shared/startHelpers.js +91 -10
  27. package/dist/commands/shared/validation.d.ts +11 -0
  28. package/dist/commands/shared/validation.js +16 -0
  29. package/dist/daemon/launcher.d.ts +8 -1
  30. package/dist/daemon/launcher.js +3 -1
  31. package/dist/daemon/session/Session.d.ts +7 -0
  32. package/dist/daemon/session/Session.js +23 -1
  33. package/dist/daemon/session/commandRegistry.d.ts +14 -1
  34. package/dist/daemon/session/commandRegistry.js +65 -9
  35. package/dist/daemon/session/interactions.d.ts +18 -5
  36. package/dist/daemon/session/interactions.js +22 -12
  37. package/dist/daemon.js +3565 -329
  38. package/dist/errors/messages.d.ts +69 -0
  39. package/dist/errors/messages.js +102 -1
  40. package/dist/index.js +2416 -1320
  41. package/dist/ipc/client.d.ts +9 -0
  42. package/dist/ipc/client.js +13 -0
  43. package/dist/ipc/protocol/commands.d.ts +56 -1
  44. package/dist/ipc/protocol/commands.js +2 -0
  45. package/dist/ipc/protocol/domTypes.d.ts +35 -2
  46. package/dist/ipc/protocol/inspectTypes.d.ts +388 -0
  47. package/dist/ipc/protocol/inspectTypes.js +10 -0
  48. package/dist/runtime/dom/actionEffects.d.ts +94 -15
  49. package/dist/runtime/dom/actionEffects.js +173 -27
  50. package/dist/runtime/dom/actionEffectsScripts.d.ts +52 -14
  51. package/dist/runtime/dom/actionEffectsScripts.js +224 -32
  52. package/dist/runtime/dom/elementInfo.d.ts +26 -0
  53. package/dist/runtime/dom/elementInfo.js +65 -0
  54. package/dist/runtime/dom/eventListeners.js +14 -4
  55. package/dist/runtime/dom/formFillHelpers/fill.d.ts +3 -4
  56. package/dist/runtime/dom/formFillHelpers/fill.js +77 -28
  57. package/dist/runtime/dom/frameSelection.d.ts +11 -0
  58. package/dist/runtime/dom/frameSelection.js +20 -1
  59. package/dist/runtime/dom/frames.d.ts +38 -5
  60. package/dist/runtime/dom/frames.js +136 -21
  61. package/dist/runtime/dom/inspect.d.ts +28 -0
  62. package/dist/runtime/dom/inspect.js +557 -0
  63. package/dist/runtime/dom/inspectAllStyles.d.ts +62 -0
  64. package/dist/runtime/dom/inspectAllStyles.js +385 -0
  65. package/dist/runtime/dom/inspectCascade.d.ts +94 -0
  66. package/dist/runtime/dom/inspectCascade.js +371 -0
  67. package/dist/runtime/dom/inspectCascadeModel.d.ts +39 -0
  68. package/dist/runtime/dom/inspectCascadeModel.js +232 -0
  69. package/dist/runtime/dom/inspectHints.d.ts +62 -0
  70. package/dist/runtime/dom/inspectHints.js +305 -0
  71. package/dist/runtime/dom/inspectLayoutModel.d.ts +87 -0
  72. package/dist/runtime/dom/inspectLayoutModel.js +346 -0
  73. package/dist/runtime/dom/inspectModel.d.ts +74 -0
  74. package/dist/runtime/dom/inspectModel.js +184 -0
  75. package/dist/runtime/dom/inspectPaintModel.d.ts +157 -0
  76. package/dist/runtime/dom/inspectPaintModel.js +461 -0
  77. package/dist/runtime/dom/inspectRules.d.ts +37 -0
  78. package/dist/runtime/dom/inspectRules.js +101 -0
  79. package/dist/runtime/dom/inspectScripts.d.ts +132 -0
  80. package/dist/runtime/dom/inspectScripts.js +263 -0
  81. package/dist/runtime/dom/inspectTree.d.ts +40 -0
  82. package/dist/runtime/dom/inspectTree.js +134 -0
  83. package/dist/runtime/dom/inspectVariables.d.ts +33 -0
  84. package/dist/runtime/dom/inspectVariables.js +94 -0
  85. package/dist/runtime/dom/inspectWhyModel.d.ts +20 -0
  86. package/dist/runtime/dom/inspectWhyModel.js +134 -0
  87. package/dist/runtime/dom/layout.d.ts +5 -1
  88. package/dist/runtime/dom/layout.js +10 -3
  89. package/dist/runtime/dom/listenerPageScripts.d.ts +11 -5
  90. package/dist/runtime/dom/listenerPageScripts.js +95 -9
  91. package/dist/runtime/dom/listenerSummary.d.ts +4 -0
  92. package/dist/runtime/dom/listenerSummary.js +26 -9
  93. package/dist/runtime/dom/reactEventHelpers.d.ts +5 -0
  94. package/dist/runtime/dom/reactEventHelpers.js +12 -4
  95. package/dist/runtime/page/emulation.d.ts +20 -0
  96. package/dist/runtime/page/emulation.js +37 -0
  97. package/dist/telemetry/a11y.d.ts +10 -0
  98. package/dist/telemetry/a11y.js +78 -1
  99. package/dist/telemetry/console.d.ts +1 -0
  100. package/dist/telemetry/console.js +100 -5
  101. package/dist/telemetry/network.js +3 -1
  102. package/dist/types.d.ts +32 -0
  103. package/dist/ui/formatters/details.d.ts +8 -0
  104. package/dist/ui/formatters/details.js +59 -3
  105. package/dist/ui/formatters/dom.d.ts +2 -1
  106. package/dist/ui/formatters/dom.js +25 -9
  107. package/dist/ui/formatters/inspect.d.ts +39 -0
  108. package/dist/ui/formatters/inspect.js +596 -0
  109. package/dist/ui/formatters/keyAttributes.d.ts +19 -0
  110. package/dist/ui/formatters/keyAttributes.js +84 -0
  111. package/dist/ui/formatters/layout.js +2 -2
  112. package/dist/ui/formatters/networkHeaders.d.ts +13 -0
  113. package/dist/ui/formatters/networkHeaders.js +23 -3
  114. package/dist/ui/formatters/networkList.d.ts +29 -1
  115. package/dist/ui/formatters/networkList.js +86 -20
  116. package/dist/ui/formatters/status.js +1 -1
  117. package/dist/ui/formatting.d.ts +9 -0
  118. package/dist/ui/formatting.js +6 -3
  119. package/dist/ui/messages/commands.d.ts +123 -7
  120. package/dist/ui/messages/commands.js +181 -10
  121. package/dist/ui/messages/networkMessages.d.ts +14 -0
  122. package/dist/ui/messages/networkMessages.js +18 -0
  123. package/dist/ui/messages/session.d.ts +14 -0
  124. package/dist/ui/messages/session.js +20 -0
  125. package/dist/utils/async.d.ts +9 -0
  126. package/dist/utils/async.js +17 -0
  127. package/dist/utils/color.d.ts +84 -0
  128. package/dist/utils/color.js +376 -0
  129. package/dist/utils/cssValues.d.ts +109 -0
  130. package/dist/utils/cssValues.js +236 -0
  131. package/dist/utils/selectorFilters.d.ts +12 -0
  132. package/dist/utils/selectorFilters.js +29 -0
  133. package/package.json +1 -1
@@ -82,15 +82,46 @@ export const NO_VISIBLE_EFFECT = 'no visible effect observed: no DOM change, req
82
82
  * Status line of a DOM action: a check mark only for a clean success.
83
83
  *
84
84
  * @param done - What was done, e.g. "Element Clicked"
85
- * @param warned - Whether the action has warnings (shown right below)
86
- * @param noEffect - Whether the action had no visible effect
87
- * @returns e.g. "✓ Element Clicked", "⚠ Element Clicked (with warnings)" or
85
+ * @param state - Whether the action has warnings (shown right below), had no
86
+ * visible effect, or returned while the page was still changing
87
+ * @returns e.g. "✓ Element Clicked", "⚠ Element Clicked (with warnings)",
88
+ * "⚠ Element Clicked (page still changing)" or
88
89
  * "⚠ Element Clicked (no visible effect observed: no DOM change, requests or navigation within 300 ms)"
89
90
  */
90
- export function actionStatusLine(done, warned, noEffect = false) {
91
- if (noEffect)
91
+ export function actionStatusLine(done, state) {
92
+ if (state.noEffect)
92
93
  return `⚠ ${done} (${NO_VISIBLE_EFFECT})`;
93
- return warned ? `⚠ ${done} (with warnings)` : `✓ ${done}`;
94
+ const notes = [state.warned && 'with warnings', state.stillChanging && 'page still changing'];
95
+ const shown = notes.filter((note) => typeof note === 'string');
96
+ return shown.length > 0 ? `⚠ ${done} (${shown.join('; ')})` : `✓ ${done}`;
97
+ }
98
+ /**
99
+ * Note under the status line of an action that returned while the page was
100
+ * still changing.
101
+ *
102
+ * @param action - What returned, e.g. "click", "key press"
103
+ * @param pending - What the page was still working on
104
+ * @returns e.g. "The page was still changing when the click returned (2 requests pending); wait for the result with bdg dom wait <selector>"
105
+ */
106
+ export function stillChangingNote(action, pending) {
107
+ const parts = [
108
+ pending.requests !== undefined && `${pluralize(pending.requests, 'request')} pending`,
109
+ pending.navigation && 'a new page still loading',
110
+ pending.loading !== undefined && `loading indicator ${pending.loading} shown`,
111
+ pending.domChanging && 'DOM still changing',
112
+ pending.busy && 'page busy running a script',
113
+ ].filter((part) => typeof part === 'string');
114
+ const wait = sessionCommand('bdg dom wait <selector>');
115
+ return `The page was still changing when the ${action} returned (${parts.join(', ')}); wait for the result with ${wait}`;
116
+ }
117
+ /**
118
+ * An element an action showed, for its `Shown:` rows.
119
+ *
120
+ * @param element - Shown element
121
+ * @returns e.g. `div.figcaption "name: user2 View profile"`
122
+ */
123
+ export function shownElementText(element) {
124
+ return `${element.element} "${element.text}"`;
94
125
  }
95
126
  /**
96
127
  * How an action changed the page's location, for its `Page:` row.
@@ -340,11 +371,11 @@ export function layoutPositionLabel(element, viewport) {
340
371
  * comes from.
341
372
  *
342
373
  * @param scheme - Light or dark
343
- * @param emulated - Set with `--color-scheme` (otherwise the system setting)
374
+ * @param emulated - Set with `--color-scheme` or `page emulate` (otherwise the system setting)
344
375
  * @returns e.g. `prefers-color-scheme: dark (from the system setting)`
345
376
  */
346
377
  export function colorSchemeLabel(scheme, emulated) {
347
- const source = emulated ? 'emulated with --color-scheme' : 'from the system setting';
378
+ const source = emulated ? 'emulated' : 'from the system setting';
348
379
  return `prefers-color-scheme: ${scheme} (${source})`;
349
380
  }
350
381
  /**
@@ -393,6 +424,87 @@ export function layoutHeadline(count, listed, selector) {
393
424
  export function indexLayoutHeadline(target) {
394
425
  return `Element at ${target} (page x,y and size in CSS px):`;
395
426
  }
427
+ /** Help text explaining `bdg dom inspect`'s output notation */
428
+ export const INSPECT_OUTPUT_LEGEND = `
429
+ Output notation:
430
+ WxH @x,y rendered border box size and page position (CSS px, no unit)
431
+ m / p / b margin / padding / border widths, 1-4 values in CSS order (top right bottom left)
432
+ in-parent distances to the parent's content edges (l t r b); sib: gaps to the sibling on each side
433
+ scroll WxH the content (pseudo-elements too) is larger than the box
434
+ 16/24 font size / line height; 'webfont loaded' = drawn with a downloaded font;
435
+ (rendered "X") = drawn with another font than declared (a fallback)
436
+ contrast 4.47 WCAG ratio, rounded down, against the background behind the text
437
+ (+N not rendered) children with display: none (or not in the layout)
438
+ hints declarations on this element that have no effect, why, the fix and where they are
439
+ ('none': checked, nothing found)
440
+ ← sel (file:N) --rules: the declaration that sets the value (file:line, or file:line:column in
441
+ minified files); 'over X': rules it beats; '= v': the value of a var() expression
442
+ ✓ / ✗ --why: the winning declaration / ones it beats, highest precedence first;
443
+ [0,2,0]: selector specificity (ids, classes, types); indented --name lines: where
444
+ the winner's custom properties are set
445
+ Sessions follow the system color scheme; start with --color-scheme light|dark to choose.`;
446
+ /**
447
+ * What covers an element: a cover that paints nothing at that point (a
448
+ * transparent box over it) does not hide it, but takes its clicks.
449
+ *
450
+ * @param cover - Description of the covering element
451
+ * @param transparent - The cover paints nothing there
452
+ * @returns e.g. `covered by div#modal`, `under transparent ul.filters (clicks land on it)`
453
+ */
454
+ export function coverText(cover, transparent) {
455
+ return transparent ? `under transparent ${cover} (clicks land on it)` : `covered by ${cover}`;
456
+ }
457
+ /**
458
+ * Note when `bdg dom inspect` could not read the element's matched rules, so
459
+ * no hints, rules or why were computed.
460
+ *
461
+ * @param reason - `timeout` (very large stylesheets) or `failed` (Chrome reported an error)
462
+ * @returns Note
463
+ */
464
+ export function inspectCascadeNote(reason) {
465
+ return reason === 'timeout'
466
+ ? "CSS rules not read: the page's stylesheets took too long (hints wait 1 s; --rules and --why 5 s)"
467
+ : 'CSS rules not read: Chrome could not report the rules matching this element';
468
+ }
469
+ /**
470
+ * Header badge of `bdg dom inspect` when the page is shown in its dark theme
471
+ * because the session follows the system's dark preference: the colors are
472
+ * the dark theme's, not what a light-mode visitor sees.
473
+ *
474
+ * @returns Badge
475
+ */
476
+ export function inspectDarkThemeBadge() {
477
+ return '[dark theme from system; --color-scheme light for light]';
478
+ }
479
+ /**
480
+ * Header badges of `bdg dom inspect` for what keeps an element from being seen.
481
+ *
482
+ * @param visibility - Not rendered, hidden, offscreen, covered
483
+ * @returns e.g. `[not rendered: display: none]`, `[offscreen: below]`, `[covered by div#modal]`
484
+ */
485
+ export function inspectVisibilityBadges(visibility) {
486
+ const reason = (text) => (text ? `: ${text}` : '');
487
+ if (visibility.notRendered) {
488
+ return [`[not rendered${reason(visibility.hidden?.replace(/^not rendered \((.*)\)$/, '$1'))}]`];
489
+ }
490
+ return [
491
+ visibility.hidden && `[hidden: ${visibility.hidden}]`,
492
+ visibility.offscreen && `[offscreen: ${visibility.offscreen}]`,
493
+ visibility.coveredBy && `[${coverText(visibility.coveredBy, visibility.coverTransparent)}]`,
494
+ ].filter((badge) => Boolean(badge));
495
+ }
496
+ /**
497
+ * What `bdg dom inspect` did when several elements matched and no --index was given.
498
+ *
499
+ * @param picked - How the match was chosen
500
+ * @param index - Index of the inspected match
501
+ * @returns e.g. "inspected the first visible one ([2])"
502
+ */
503
+ export function inspectedMatchAction(picked, index) {
504
+ return picked === 'first-visible'
505
+ ? `inspected the first visible one ([${index}])`
506
+ : 'inspected the first';
507
+ }
396
508
  /**
397
509
  * Warning when a selector matched several elements and no --index was given.
398
510
  *
@@ -536,6 +648,13 @@ export const POINTER_ACTION_DONE = {
536
648
  right: 'Right-clicked',
537
649
  hover: 'Hovered',
538
650
  };
651
+ /** What each pointer action is called in notes ("when the click returned") */
652
+ export const POINTER_ACTION_NOUN = {
653
+ click: 'click',
654
+ double: 'double-click',
655
+ right: 'right-click',
656
+ hover: 'hover',
657
+ };
539
658
  /** Headline of each `bdg page` action */
540
659
  export const PAGE_ACTION_DONE = {
541
660
  navigate: 'Navigated',
@@ -543,9 +662,11 @@ export const PAGE_ACTION_DONE = {
543
662
  back: 'Went back',
544
663
  forward: 'Went forward',
545
664
  };
546
- /** Help text of the `bdg page` history commands */
547
665
  /** Description of `bdg page info` */
548
666
  export const PAGE_INFO_DESCRIPTION = 'Show the URL and title of the session page';
667
+ /** Description of `bdg page emulate` */
668
+ export const PAGE_EMULATE_DESCRIPTION = 'Change the viewport or color scheme mid-session (like --viewport and --color-scheme at start), or --reset both';
669
+ /** Help text of the `bdg page` history commands */
549
670
  export const PAGE_ACTION_DESCRIPTIONS = {
550
671
  reload: 'Reload the page',
551
672
  back: 'Go back one page (like the browser button)',
@@ -638,7 +759,7 @@ export function pageLoadingWarning(state) {
638
759
  * Help of `dom click`/`submit`: they wait for the network only, so results a
639
760
  * page shows later (timers, spinners, animations) are waited for with `dom wait`.
640
761
  */
641
- export const CLICK_RESULT_WAIT_HELP = joinLines('', 'Waits only for the requests the action starts (150 ms idle, up to 2 s), not for', 'results the page shows later (timers, spinners, animations). Wait for those with:', " bdg dom wait '#result' --visible # or --text 'Saved', or '.spinner' --gone");
762
+ export const CLICK_RESULT_WAIT_HELP = joinLines('', 'Waits only for the requests the action starts (150 ms idle, up to 2 s), not for', 'results the page shows later (timers, spinners, animations); the result says', '"page still changing" when it saw such work pending. Wait for those with:', " bdg dom wait '#result' --visible # or --text 'Saved', or '.spinner' --gone");
642
763
  /** Examples in the help of `bdg dom wait` */
643
764
  export const WAIT_HELP_EXAMPLES = joinLines('', 'Examples:', " bdg dom wait '#finish' --visible # timer-based loading (a spinner, then the result)", " bdg dom wait '.toast' --text 'Saved' # a match containing the text", " bdg dom wait '#loading' --gone # the spinner went away", ' bdg dom wait --load # the page finished loading');
644
765
  /**
@@ -881,4 +1002,54 @@ export function sessionStillActiveSuggestion(session) {
881
1002
  export function startCommandHelpMessage() {
882
1003
  return joinLines('', buildAgentDiscoveryHelp(), '', buildCommonTaskExamples(), '', buildUrlExamples(), '', buildSessionManagementReminder(), '', 'Not sure which command? Start a session to see all available commands:', ' bdg <url>', '');
883
1004
  }
1005
+ /**
1006
+ * `bdg page emulate` without anything to change.
1007
+ *
1008
+ * @returns Message and suggestion
1009
+ */
1010
+ export function pageEmulateNothingError() {
1011
+ return {
1012
+ message: 'Nothing to emulate',
1013
+ suggestion: 'Give --viewport <WxH>, --color-scheme light|dark, or --reset, e.g. bdg page emulate --viewport 900x700',
1014
+ };
1015
+ }
1016
+ /**
1017
+ * Lines of `bdg page emulate`: what is emulated and what the page now has.
1018
+ *
1019
+ * @param result - Emulation and page appearance
1020
+ * @returns Label/value pairs
1021
+ */
1022
+ export function pageEmulationLines(result) {
1023
+ const size = (v) => `${v.width}x${v.height}`;
1024
+ const { emulated } = result;
1025
+ return [
1026
+ ['Viewport', emulated.viewport ? size(emulated.viewport) : 'the browser window'],
1027
+ ...(result.viewport
1028
+ ? [['Layout', `${size(result.viewport)} (without scrollbars)`]]
1029
+ : []),
1030
+ [
1031
+ 'Scheme',
1032
+ emulated.colorScheme ??
1033
+ `system setting${result.colorScheme ? ` (${result.colorScheme})` : ''}`,
1034
+ ],
1035
+ ];
1036
+ }
1037
+ /**
1038
+ * Header badge of `bdg dom inspect` while CSS transitions or animations run
1039
+ * on the element: the values read are mid-way.
1040
+ *
1041
+ * @param animating - Transitioned properties and animation names
1042
+ * @returns e.g. `[animating: background-color; values are mid-way, inspect again]`
1043
+ */
1044
+ export function inspectAnimatingBadge(animating) {
1045
+ return `[animating: ${animating.join(', ')}; values are mid-way, inspect again]`;
1046
+ }
1047
+ /**
1048
+ * `--why` note on a computed value read during its transition.
1049
+ *
1050
+ * @returns Note
1051
+ */
1052
+ export function inspectMidTransitionNote() {
1053
+ return '(mid-transition: inspect again for the final value)';
1054
+ }
884
1055
  //# sourceMappingURL=commands.js.map
@@ -15,4 +15,18 @@ export declare function followingNetworkMessage(): string;
15
15
  * @returns Status message for stderr
16
16
  */
17
17
  export declare function stoppedFollowingNetworkMessage(): string;
18
+ /**
19
+ * Note after a header value the server sent more than once.
20
+ *
21
+ * @param count - Times it was sent
22
+ * @returns e.g. `(sent 2 times)`
23
+ */
24
+ export declare function headerRepeatedNote(count: number): string;
25
+ /**
26
+ * Note after a loopback remote address of a request to another host and
27
+ * port: Chrome probably connected to a proxy on this machine, not the server.
28
+ *
29
+ * @returns Note text
30
+ */
31
+ export declare function localProxyNote(): string;
18
32
  //# sourceMappingURL=networkMessages.d.ts.map
@@ -19,4 +19,22 @@ export function followingNetworkMessage() {
19
19
  export function stoppedFollowingNetworkMessage() {
20
20
  return '\nStopped following network requests.';
21
21
  }
22
+ /**
23
+ * Note after a header value the server sent more than once.
24
+ *
25
+ * @param count - Times it was sent
26
+ * @returns e.g. `(sent 2 times)`
27
+ */
28
+ export function headerRepeatedNote(count) {
29
+ return `(sent ${count} times)`;
30
+ }
31
+ /**
32
+ * Note after a loopback remote address of a request to another host and
33
+ * port: Chrome probably connected to a proxy on this machine, not the server.
34
+ *
35
+ * @returns Note text
36
+ */
37
+ export function localProxyNote() {
38
+ return '(loopback; likely a local proxy)';
39
+ }
22
40
  //# sourceMappingURL=networkMessages.js.map
@@ -77,4 +77,18 @@ export declare function lastSessionEndText(end: {
77
77
  reason: string;
78
78
  endedAt: number;
79
79
  }): string;
80
+ /**
81
+ * Note after a failed start whose daemon had not exited when bdg stopped waiting.
82
+ *
83
+ * @param pid - Daemon PID, when known
84
+ * @param waitedMs - How long bdg waited
85
+ * @returns Note
86
+ */
87
+ export declare function daemonStillExitingHint(pid: number | undefined, waitedMs: number): string;
88
+ /**
89
+ * What to do about a daemon still shutting down after a failed start.
90
+ *
91
+ * @returns Suggestion
92
+ */
93
+ export declare function daemonStillExitingSuggestion(): string;
80
94
  //# sourceMappingURL=session.d.ts.map
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { joinLines } from '../formatting.js';
8
8
  import { pageLoadingWarning } from './commands.js';
9
+ import { sessionCommand } from './sessionCommand.js';
9
10
  /**
10
11
  * Lines shown under the target in both the full and the quiet start output:
11
12
  * the session name, an HTTP error of the page, a page still loading, and
@@ -96,4 +97,23 @@ export function lastSessionEndText(end) {
96
97
  const at = new Date(end.endedAt).toLocaleTimeString();
97
98
  return `The last session ended at ${at}: ${why[end.reason] ?? end.reason}`;
98
99
  }
100
+ /**
101
+ * Note after a failed start whose daemon had not exited when bdg stopped waiting.
102
+ *
103
+ * @param pid - Daemon PID, when known
104
+ * @param waitedMs - How long bdg waited
105
+ * @returns Note
106
+ */
107
+ export function daemonStillExitingHint(pid, waitedMs) {
108
+ const daemon = pid === undefined ? 'The daemon' : `The daemon (PID ${pid})`;
109
+ return `${daemon} was still shutting down after ${waitedMs / 1000}s`;
110
+ }
111
+ /**
112
+ * What to do about a daemon still shutting down after a failed start.
113
+ *
114
+ * @returns Suggestion
115
+ */
116
+ export function daemonStillExitingSuggestion() {
117
+ return `check with bdg sessions, or end it with ${sessionCommand('bdg cleanup --force')}`;
118
+ }
99
119
  //# sourceMappingURL=session.js.map
@@ -15,4 +15,13 @@ export declare function delay(ms: number): Promise<void>;
15
15
  * @returns The promise's result, or undefined when the time ran out first
16
16
  */
17
17
  export declare function raceTimeout<T>(promise: Promise<T>, ms: number): Promise<T | undefined>;
18
+ /**
19
+ * Poll a condition until it holds or a time runs out.
20
+ *
21
+ * @param condition - Checked first right away, then every `pollMs`
22
+ * @param timeoutMs - Milliseconds to wait at most
23
+ * @param pollMs - Milliseconds between checks
24
+ * @returns True when the condition held, false when the time ran out
25
+ */
26
+ export declare function waitUntil(condition: () => boolean, timeoutMs: number, pollMs?: number): Promise<boolean>;
18
27
  //# sourceMappingURL=async.d.ts.map
@@ -28,4 +28,21 @@ export async function raceTimeout(promise, ms) {
28
28
  clearTimeout(timer);
29
29
  }
30
30
  }
31
+ /**
32
+ * Poll a condition until it holds or a time runs out.
33
+ *
34
+ * @param condition - Checked first right away, then every `pollMs`
35
+ * @param timeoutMs - Milliseconds to wait at most
36
+ * @param pollMs - Milliseconds between checks
37
+ * @returns True when the condition held, false when the time ran out
38
+ */
39
+ export async function waitUntil(condition, timeoutMs, pollMs = 25) {
40
+ const deadline = Date.now() + timeoutMs;
41
+ while (!condition()) {
42
+ if (Date.now() >= deadline)
43
+ return false;
44
+ await delay(Math.min(pollMs, Math.max(0, deadline - Date.now())));
45
+ }
46
+ return true;
47
+ }
31
48
  //# sourceMappingURL=async.js.map
@@ -0,0 +1,84 @@
1
+ /**
2
+ * CSS colors as `bdg dom inspect` reports them: parsed from the computed
3
+ * values Chrome returns (`rgb()`/`rgba()`, and `lab()`, `lch()`, `oklab()`,
4
+ * `oklch()` and `color()` as Tailwind v4 and other modern CSS leave them),
5
+ * converted to sRGB the way Chrome paints them on an sRGB screen (channels
6
+ * outside the gamut are clipped), and printed as short hex. Also the WCAG
7
+ * contrast math over alpha-composited backgrounds.
8
+ *
9
+ * Conversions follow the CSS Color 4 sample code (Bradford D50 → D65, the
10
+ * OKLab matrices of Björn Ottosson).
11
+ */
12
+ /** A color in sRGB: channels 0-1 (unclipped until printed), alpha 0-1 */
13
+ export interface Rgba {
14
+ r: number;
15
+ g: number;
16
+ b: number;
17
+ a: number;
18
+ }
19
+ /**
20
+ * Parse a CSS color as Chrome computes it.
21
+ *
22
+ * @param value - e.g. `rgba(0, 0, 0, 0.2)`, `oklch(0.373 0.034 259.733)`, `#fff`, `transparent`
23
+ * @returns The color in sRGB, or null for anything else (`currentcolor`, keywords, gradients)
24
+ */
25
+ export declare function parseColor(value: string): Rgba | null;
26
+ /**
27
+ * A color as short hex: `#rgb` when every channel's digits repeat, else
28
+ * `#rrggbb`; `#rrggbbaa` when translucent; `transparent` at alpha 0.
29
+ *
30
+ * @param color - Color in sRGB
31
+ * @returns e.g. `#fff`, `#364153`, `#00000033`
32
+ */
33
+ export declare function toHex(color: Rgba): string;
34
+ /**
35
+ * A computed color as short hex ({@link toHex}).
36
+ *
37
+ * @param value - Computed color
38
+ * @returns Hex, or the value unchanged when it is not a color
39
+ */
40
+ export declare function hexColor(value: string): string;
41
+ /**
42
+ * Replace every color inside a value with its hex ({@link toHex}).
43
+ *
44
+ * @param value - e.g. `rgba(0, 0, 0, 0.2) 0px 1px 2px 0px`
45
+ * @returns e.g. `#00000033 0px 1px 2px 0px`
46
+ */
47
+ export declare function hexColorsIn(value: string): string;
48
+ /**
49
+ * Paint a color over another (source-over alpha compositing).
50
+ *
51
+ * @param top - Color on top
52
+ * @param bottom - Color below
53
+ * @returns The color a user sees
54
+ */
55
+ export declare function composite(top: Rgba, bottom: Rgba): Rgba;
56
+ /**
57
+ * WCAG relative luminance of an opaque color (clipped to sRGB).
58
+ *
59
+ * @param color - Color
60
+ * @returns Luminance 0-1
61
+ */
62
+ export declare function relativeLuminance(color: Rgba): number;
63
+ /**
64
+ * WCAG contrast ratio of text over an opaque background; translucent text
65
+ * is composited over the background first.
66
+ *
67
+ * @param text - Text color
68
+ * @param background - Opaque background color
69
+ * @returns Ratio 1-21
70
+ */
71
+ export declare function contrastRatio(text: Rgba, background: Rgba): number;
72
+ /** WCAG 2 conformance of a contrast ratio */
73
+ export type ContrastLevel = 'AAA' | 'AA' | 'AA large' | 'fail';
74
+ /**
75
+ * WCAG 2 level a contrast ratio reaches. Large text (24px, or 18.66px bold)
76
+ * needs 4.5 for AAA and 3 for AA; other text 7 and 4.5.
77
+ *
78
+ * @param ratio - Contrast ratio
79
+ * @param fontSize - Font size in px
80
+ * @param fontWeight - Font weight
81
+ * @returns Level reached
82
+ */
83
+ export declare function contrastLevel(ratio: number, fontSize: number, fontWeight: number): ContrastLevel;
84
+ //# sourceMappingURL=color.d.ts.map