@crvy/rprtr 0.2.3 → 0.3.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 (49) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +33 -0
  3. package/dist/{chunk-HAFWYUNO.js → chunk-4YJL655E.js} +16 -4
  4. package/dist/{chunk-473CWZ4V.js → chunk-IFHYWPXG.js} +710 -281
  5. package/dist/cli.d.ts +7 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +57 -6
  8. package/dist/index.css +7 -0
  9. package/dist/index.js +152 -105
  10. package/dist/reporter-artifact-ops.d.ts +0 -2
  11. package/dist/reporter-artifact-ops.d.ts.map +1 -1
  12. package/dist/reporter.cjs +32 -38
  13. package/dist/reporter.d.ts +2 -1
  14. package/dist/reporter.d.ts.map +1 -1
  15. package/dist/reporter.js +27 -43
  16. package/dist/schemas/http.d.ts +2 -0
  17. package/dist/schemas/http.d.ts.map +1 -1
  18. package/dist/schemas.d.ts +14 -0
  19. package/dist/schemas.d.ts.map +1 -1
  20. package/dist/server/app.d.ts +6 -0
  21. package/dist/server/app.d.ts.map +1 -1
  22. package/dist/server/artifact-routes.d.ts.map +1 -1
  23. package/dist/server/docker-launcher.d.ts +27 -0
  24. package/dist/server/docker-launcher.d.ts.map +1 -0
  25. package/dist/server/docker-support.d.ts +66 -0
  26. package/dist/server/docker-support.d.ts.map +1 -0
  27. package/dist/server/handlers.d.ts +1 -1
  28. package/dist/server/handlers.d.ts.map +1 -1
  29. package/dist/server/launcher-resolver.d.ts +23 -0
  30. package/dist/server/launcher-resolver.d.ts.map +1 -0
  31. package/dist/server/playwright-config.d.ts +6 -0
  32. package/dist/server/playwright-config.d.ts.map +1 -1
  33. package/dist/server/routes-context.d.ts +6 -1
  34. package/dist/server/routes-context.d.ts.map +1 -1
  35. package/dist/server/routes.d.ts +7 -0
  36. package/dist/server/routes.d.ts.map +1 -1
  37. package/dist/server/run-controller.d.ts +19 -19
  38. package/dist/server/run-controller.d.ts.map +1 -1
  39. package/dist/server/run-launcher.d.ts +45 -0
  40. package/dist/server/run-launcher.d.ts.map +1 -0
  41. package/dist/server/run-mode.d.ts +15 -0
  42. package/dist/server/run-mode.d.ts.map +1 -0
  43. package/dist/server/server-factories.d.ts +21 -0
  44. package/dist/server/server-factories.d.ts.map +1 -0
  45. package/dist/server.cjs +885 -446
  46. package/dist/server.js +2 -2
  47. package/dist/types.d.ts +2 -0
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19336,13 +19336,14 @@ var RunTestDescriptorSchema = external_exports.object({
19336
19336
  titlePath: external_exports.array(external_exports.string())
19337
19337
  });
19338
19338
  var RunRequestBodySchema = external_exports.object({
19339
- tests: external_exports.array(RunTestDescriptorSchema).optional()
19339
+ tests: external_exports.array(RunTestDescriptorSchema).optional(),
19340
+ update: external_exports.boolean().optional()
19340
19341
  });
19341
19342
  var RunResponseSchema = external_exports.discriminatedUnion("ok", [
19342
19343
  external_exports.object({ ok: external_exports.literal(true) }),
19343
19344
  external_exports.object({
19344
19345
  ok: external_exports.literal(false),
19345
- reason: external_exports.enum(["no-config", "already-running", "no-tests"])
19346
+ reason: external_exports.enum(["no-config", "already-running", "no-tests", "docker-unavailable"])
19346
19347
  })
19347
19348
  ]);
19348
19349
  var StopResponseSchema = external_exports.discriminatedUnion("ok", [
@@ -19449,7 +19450,9 @@ var WebSocketMessageSchema = external_exports.discriminatedUnion("type", [
19449
19450
  external_exports.object({
19450
19451
  type: external_exports.literal("run-status"),
19451
19452
  data: external_exports.object({
19452
- running: external_exports.boolean()
19453
+ running: external_exports.boolean(),
19454
+ mode: external_exports.enum(["local", "docker"]).optional(),
19455
+ phase: external_exports.string().optional()
19453
19456
  })
19454
19457
  })
19455
19458
  ]);
@@ -19479,6 +19482,7 @@ var RunEndDataSchema = external_exports.object({
19479
19482
  var RegisterDataSchema = external_exports.object({
19480
19483
  playwrightSnapshotDir: external_exports.string().optional(),
19481
19484
  playwrightTestDir: external_exports.string().optional(),
19485
+ playwrightRootDir: external_exports.string().optional(),
19482
19486
  playwrightSnapshotPathTemplate: external_exports.string().optional(),
19483
19487
  playwrightToHaveScreenshotPathTemplate: external_exports.string().optional(),
19484
19488
  configFile: external_exports.string().optional(),
@@ -19511,7 +19515,8 @@ var ReportApiResponseSchema = external_exports.object({
19511
19515
  tests: external_exports.record(external_exports.string(), TestDataSchema),
19512
19516
  isUpdateMode: external_exports.boolean().optional(),
19513
19517
  isRunning: external_exports.boolean().optional(),
19514
- runEnabled: external_exports.boolean().optional()
19518
+ runEnabled: external_exports.boolean().optional(),
19519
+ runMode: external_exports.enum(["local", "docker"]).optional()
19515
19520
  });
19516
19521
  var ClientBootstrapDataSchema = external_exports.object({
19517
19522
  report: ReportApiResponseSchema.extend({
@@ -20338,18 +20343,19 @@ function TreeItem_1($$anchor, $$props) {
20338
20343
  delegate(["click", "keydown"]);
20339
20344
 
20340
20345
  // src/client/components/Sidebar.svelte
20341
- var root_12 = from_html(`<div class="text-xs mb-2 px-2 py-1 text-success bg-success/10 rounded-sm">Review and approve screenshots</div>`);
20342
- var root_22 = from_html(`<button><span></span> <span> </span></button>`);
20343
- var root_32 = from_html(`<button><span class="size-2 rounded-full inline-block shrink-0 bg-info"></span> <span> </span></button>`);
20344
- var root_5 = from_html(`<button class="size-9 flex items-center justify-center bg-surface-input border border-edge rounded text-error cursor-pointer text-sm transition-colors hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent" aria-label="Stop tests">&#9632;</button>`);
20345
- var root_6 = from_html(`<button class="size-9 flex items-center justify-center bg-surface-input border border-edge rounded text-success cursor-pointer text-sm transition-colors hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent" aria-label="Start tests">&#9654;</button>`);
20346
- var root_4 = from_html(`<div class="mt-1"><!></div>`);
20347
- var root_7 = from_html(`<div class="mt-2 text-center text-xs text-fg-muted"> </div>`);
20348
- var root_9 = from_html(`<div class="py-6 px-4 text-center text-fg-muted text-ui">No tests match filter</div>`);
20349
- var root_10 = from_html(`<button class="flex-1 px-4 py-1.5 border border-edge rounded text-ui cursor-pointer transition-colors text-center bg-transparent text-fg hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Next &#8250;</button>`);
20350
- var root_11 = from_html(`<button class="flex-1 px-4 py-1.5 border border-success rounded text-ui cursor-pointer transition-colors text-center bg-success text-white font-semibold hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Approve &#8250;</button>`);
20351
- var root_122 = from_html(`<div class="mt-2 text-center text-xs text-fg-muted"> </div>`);
20352
- var root2 = from_html(`<div class="w-[300px] min-w-[300px] max-md:w-full max-md:min-w-0 max-md:max-h-[40vh] max-md:border-b max-md:border-r-0 bg-surface-alt border-r border-edge flex flex-col overflow-hidden"><div class="p-4 border-b border-edge bg-surface-alt shrink-0"><div class="flex justify-between items-start"><div><h1 class="m-0 mb-2 text-base font-normal text-fg-bright">Crvy Rprtr</h1> <!> <div class="flex gap-2 text-xs mb-3 tabular-nums"><!> <!></div></div> <!></div> <input type="text" class="w-full px-2.5 py-1.5 bg-surface-input border border-edge rounded text-fg text-ui outline-none focus-visible:ring-2 focus-visible:ring-accent transition-colors focus:border-accent placeholder:text-fg-muted" placeholder="Filter tests\u2026 (status:failed)" aria-label="Filter tests" autocomplete="off"/> <!></div> <div class="flex-1 overflow-y-auto overscroll-y-contain py-1" role="tree"><!> <!></div> <div class="py-3 px-4 border-t border-edge bg-surface-alt shrink-0"><div class="flex gap-2"><!> <button class="flex-1 px-4 py-1.5 border border-edge rounded text-ui cursor-pointer transition-colors text-center bg-transparent text-fg hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Approve All</button></div> <!></div></div>`);
20346
+ var root_12 = from_html(`<div class="text-[10px] uppercase tracking-wide text-fg-muted mb-1"> </div>`);
20347
+ var root_22 = from_html(`<div class="text-xs mb-2 px-2 py-1 text-success bg-success/10 rounded-sm">Review and approve screenshots</div>`);
20348
+ var root_32 = from_html(`<button><span></span> <span> </span></button>`);
20349
+ var root_4 = from_html(`<button><span class="size-2 rounded-full inline-block shrink-0 bg-info"></span> <span> </span></button>`);
20350
+ var root_6 = from_html(`<button class="size-9 flex items-center justify-center bg-surface-input border border-edge rounded text-error cursor-pointer text-sm transition-colors hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent" aria-label="Stop tests">&#9632;</button>`);
20351
+ var root_7 = from_html(`<button class="size-9 flex items-center justify-center bg-surface-input border border-edge rounded text-success cursor-pointer text-sm transition-colors hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent disabled:opacity-40 disabled:cursor-not-allowed" aria-label="Start tests">&#9654;</button> <button class="size-9 flex items-center justify-center bg-surface-input border border-edge rounded text-success cursor-pointer text-sm transition-colors hover:bg-surface-hover focus-visible:ring-2 focus-visible:ring-accent disabled:opacity-40 disabled:cursor-not-allowed" aria-label="Run and update baselines" title="Run &amp; update baselines">&#9654;&#8635;</button>`, 1);
20352
+ var root_5 = from_html(`<div class="mt-1 flex gap-1"><!></div>`);
20353
+ var root_8 = from_html(`<div class="mt-2 text-center text-xs text-fg-muted"> </div>`);
20354
+ var root_10 = from_html(`<div class="py-6 px-4 text-center text-fg-muted text-ui">No tests match filter</div>`);
20355
+ var root_11 = from_html(`<button class="flex-1 px-4 py-1.5 border border-edge rounded text-ui cursor-pointer transition-colors text-center bg-transparent text-fg hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Next &#8250;</button>`);
20356
+ var root_122 = from_html(`<button class="flex-1 px-4 py-1.5 border border-success rounded text-ui cursor-pointer transition-colors text-center bg-success text-white font-semibold hover:brightness-110 disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Approve &#8250;</button>`);
20357
+ var root_13 = from_html(`<div class="mt-2 text-center text-xs text-fg-muted"> </div>`);
20358
+ var root2 = from_html(`<div class="w-[300px] min-w-[300px] max-md:w-full max-md:min-w-0 max-md:max-h-[40vh] max-md:border-b max-md:border-r-0 bg-surface-alt border-r border-edge flex flex-col overflow-hidden"><div class="p-4 border-b border-edge bg-surface-alt shrink-0"><div class="flex justify-between items-start"><div><h1 class="m-0 mb-2 text-base font-normal text-fg-bright">Crvy Rprtr</h1> <!> <!> <div class="flex gap-2 text-xs mb-3 tabular-nums"><!> <!></div></div> <!></div> <input type="text" class="w-full px-2.5 py-1.5 bg-surface-input border border-edge rounded text-fg text-ui outline-none focus-visible:ring-2 focus-visible:ring-accent transition-colors focus:border-accent placeholder:text-fg-muted" placeholder="Filter tests\u2026 (status:failed)" aria-label="Filter tests" autocomplete="off"/> <!></div> <div class="flex-1 overflow-y-auto overscroll-y-contain py-1" role="tree"><!> <!></div> <div class="py-3 px-4 border-t border-edge bg-surface-alt shrink-0"><div class="flex gap-2"><!> <button class="flex-1 px-4 py-1.5 border border-edge rounded text-ui cursor-pointer transition-colors text-center bg-transparent text-fg hover:bg-surface-hover disabled:opacity-40 disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-accent">Approve All</button></div> <!></div></div>`);
20353
20359
  function Sidebar($$anchor, $$props) {
20354
20360
  push($$props, true);
20355
20361
  let filterInput = state("");
@@ -20400,16 +20406,29 @@ function Sidebar($$anchor, $$props) {
20400
20406
  {
20401
20407
  var consequent = ($$anchor2) => {
20402
20408
  var div_4 = root_12();
20409
+ var text2 = child(div_4, true);
20410
+ reset(div_4);
20411
+ template_effect(() => set_text(text2, $$props.runMode));
20403
20412
  append($$anchor2, div_4);
20404
20413
  };
20405
20414
  if_block(node, ($$render) => {
20406
- if ($$props.isUpdateMode) $$render(consequent);
20415
+ if ($$props.runEnabled && $$props.runMode !== void 0) $$render(consequent);
20407
20416
  });
20408
20417
  }
20409
- var div_5 = sibling(node, 2);
20410
- var node_1 = child(div_5);
20418
+ var node_1 = sibling(node, 2);
20419
+ {
20420
+ var consequent_1 = ($$anchor2) => {
20421
+ var div_5 = root_22();
20422
+ append($$anchor2, div_5);
20423
+ };
20424
+ if_block(node_1, ($$render) => {
20425
+ if ($$props.isUpdateMode) $$render(consequent_1);
20426
+ });
20427
+ }
20428
+ var div_6 = sibling(node_1, 2);
20429
+ var node_2 = child(div_6);
20411
20430
  each(
20412
- node_1,
20431
+ node_2,
20413
20432
  17,
20414
20433
  () => [
20415
20434
  { key: "success", count: get2(status).successCount },
@@ -20420,17 +20439,17 @@ function Sidebar($$anchor, $$props) {
20420
20439
  ($$anchor2, $$item) => {
20421
20440
  let key2 = () => get2($$item).key;
20422
20441
  let count = () => get2($$item).count;
20423
- var button = root_22();
20442
+ var button = root_32();
20424
20443
  var span = child(button);
20425
20444
  var span_1 = sibling(span, 2);
20426
- var text2 = child(span_1, true);
20445
+ var text_1 = child(span_1, true);
20427
20446
  reset(span_1);
20428
20447
  reset(button);
20429
20448
  template_effect(
20430
20449
  ($0, $1) => {
20431
20450
  set_class(button, 1, $0);
20432
20451
  set_class(span, 1, $1);
20433
- set_text(text2, count());
20452
+ set_text(text_1, count());
20434
20453
  },
20435
20454
  [
20436
20455
  () => clsx2(cn("flex items-center gap-1 px-2 py-1 min-h-[28px] bg-transparent border border-transparent rounded-sm text-fg cursor-pointer text-xs transition-colors hover:border-edge focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1", $$props.filter.status === key2() && "border-accent! bg-accent/15")),
@@ -20441,18 +20460,18 @@ function Sidebar($$anchor, $$props) {
20441
20460
  append($$anchor2, button);
20442
20461
  }
20443
20462
  );
20444
- var node_2 = sibling(node_1, 2);
20463
+ var node_3 = sibling(node_2, 2);
20445
20464
  {
20446
- var consequent_1 = ($$anchor2) => {
20447
- var button_1 = root_32();
20465
+ var consequent_2 = ($$anchor2) => {
20466
+ var button_1 = root_4();
20448
20467
  var span_2 = sibling(child(button_1), 2);
20449
- var text_1 = child(span_2, true);
20468
+ var text_2 = child(span_2, true);
20450
20469
  reset(span_2);
20451
20470
  reset(button_1);
20452
20471
  template_effect(
20453
20472
  ($0) => {
20454
20473
  set_class(button_1, 1, $0);
20455
- set_text(text_1, get2(status).approvedCount);
20474
+ set_text(text_2, get2(status).approvedCount);
20456
20475
  },
20457
20476
  [
20458
20477
  () => clsx2(cn("flex items-center gap-1 px-2 py-1 min-h-[28px] bg-transparent border border-transparent rounded-sm text-fg cursor-pointer text-xs transition-colors hover:border-edge focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1", $$props.filter.status === "approved" && "border-accent! bg-accent/15"))
@@ -20461,64 +20480,73 @@ function Sidebar($$anchor, $$props) {
20461
20480
  delegated("click", button_1, () => handleClickByStatus("approved"));
20462
20481
  append($$anchor2, button_1);
20463
20482
  };
20464
- if_block(node_2, ($$render) => {
20465
- if (get2(status).approvedCount > 0) $$render(consequent_1);
20483
+ if_block(node_3, ($$render) => {
20484
+ if (get2(status).approvedCount > 0) $$render(consequent_2);
20466
20485
  });
20467
20486
  }
20468
- reset(div_5);
20487
+ reset(div_6);
20469
20488
  reset(div_3);
20470
- var node_3 = sibling(div_3, 2);
20489
+ var node_4 = sibling(div_3, 2);
20471
20490
  {
20472
- var consequent_3 = ($$anchor2) => {
20473
- var div_6 = root_4();
20474
- var node_4 = child(div_6);
20491
+ var consequent_4 = ($$anchor2) => {
20492
+ var div_7 = root_5();
20493
+ var node_5 = child(div_7);
20475
20494
  {
20476
- var consequent_2 = ($$anchor3) => {
20477
- var button_2 = root_5();
20495
+ var consequent_3 = ($$anchor3) => {
20496
+ var button_2 = root_6();
20478
20497
  delegated("click", button_2, function(...$$args) {
20479
20498
  $$props.onStop?.apply(this, $$args);
20480
20499
  });
20481
20500
  append($$anchor3, button_2);
20482
20501
  };
20483
20502
  var alternate = ($$anchor3) => {
20484
- var button_3 = root_6();
20503
+ var fragment = root_7();
20504
+ var button_3 = first_child(fragment);
20505
+ var button_4 = sibling(button_3, 2);
20506
+ template_effect(() => {
20507
+ button_3.disabled = $$props.isPreparing === true;
20508
+ button_4.disabled = $$props.isPreparing === true;
20509
+ });
20485
20510
  delegated("click", button_3, function(...$$args) {
20486
20511
  $$props.onStart?.apply(this, $$args);
20487
20512
  });
20488
- append($$anchor3, button_3);
20513
+ delegated("click", button_4, function(...$$args) {
20514
+ $$props.onUpdate?.apply(this, $$args);
20515
+ });
20516
+ append($$anchor3, fragment);
20489
20517
  };
20490
- if_block(node_4, ($$render) => {
20491
- if ($$props.isRunning) $$render(consequent_2);
20518
+ if_block(node_5, ($$render) => {
20519
+ if ($$props.isRunning) $$render(consequent_3);
20492
20520
  else $$render(alternate, -1);
20493
20521
  });
20494
20522
  }
20495
- reset(div_6);
20496
- append($$anchor2, div_6);
20523
+ reset(div_7);
20524
+ append($$anchor2, div_7);
20497
20525
  };
20498
- if_block(node_3, ($$render) => {
20499
- if ($$props.runEnabled) $$render(consequent_3);
20526
+ if_block(node_4, ($$render) => {
20527
+ if ($$props.runEnabled) $$render(consequent_4);
20500
20528
  });
20501
20529
  }
20502
20530
  reset(div_2);
20503
20531
  var input = sibling(div_2, 2);
20504
20532
  remove_input_defaults(input);
20505
- var node_5 = sibling(input, 2);
20533
+ var node_6 = sibling(input, 2);
20506
20534
  {
20507
- var consequent_4 = ($$anchor2) => {
20508
- var div_7 = root_7();
20509
- var text_2 = child(div_7, true);
20510
- reset(div_7);
20511
- template_effect(() => set_text(text_2, $$props.runMessage));
20512
- append($$anchor2, div_7);
20535
+ var consequent_5 = ($$anchor2) => {
20536
+ var div_8 = root_8();
20537
+ var text_3 = child(div_8, true);
20538
+ reset(div_8);
20539
+ template_effect(() => set_text(text_3, $$props.runMessage));
20540
+ append($$anchor2, div_8);
20513
20541
  };
20514
- if_block(node_5, ($$render) => {
20515
- if ($$props.runMessage) $$render(consequent_4);
20542
+ if_block(node_6, ($$render) => {
20543
+ if ($$props.runMessage) $$render(consequent_5);
20516
20544
  });
20517
20545
  }
20518
20546
  reset(div_1);
20519
- var div_8 = sibling(div_1, 2);
20520
- var node_6 = child(div_8);
20521
- each(node_6, 17, () => get2(visibleChildren), index, ($$anchor2, child2) => {
20547
+ var div_9 = sibling(div_1, 2);
20548
+ var node_7 = child(div_9);
20549
+ each(node_7, 17, () => get2(visibleChildren), index, ($$anchor2, child2) => {
20522
20550
  TreeItem_1($$anchor2, {
20523
20551
  get item() {
20524
20552
  return get2(child2);
@@ -20553,65 +20581,65 @@ function Sidebar($$anchor, $$props) {
20553
20581
  }
20554
20582
  });
20555
20583
  });
20556
- var node_7 = sibling(node_6, 2);
20584
+ var node_8 = sibling(node_7, 2);
20557
20585
  {
20558
- var consequent_5 = ($$anchor2) => {
20559
- var div_9 = root_9();
20560
- append($$anchor2, div_9);
20586
+ var consequent_6 = ($$anchor2) => {
20587
+ var div_10 = root_10();
20588
+ append($$anchor2, div_10);
20561
20589
  };
20562
- if_block(node_7, ($$render) => {
20563
- if (get2(visibleChildren).length === 0) $$render(consequent_5);
20590
+ if_block(node_8, ($$render) => {
20591
+ if (get2(visibleChildren).length === 0) $$render(consequent_6);
20564
20592
  });
20565
20593
  }
20566
- reset(div_8);
20567
- var div_10 = sibling(div_8, 2);
20568
- var div_11 = child(div_10);
20569
- var node_8 = child(div_11);
20594
+ reset(div_9);
20595
+ var div_11 = sibling(div_9, 2);
20596
+ var div_12 = child(div_11);
20597
+ var node_9 = child(div_12);
20570
20598
  {
20571
- var consequent_6 = ($$anchor2) => {
20572
- var button_4 = root_10();
20573
- template_effect(() => button_4.disabled = !$$props.canApprove);
20574
- delegated("click", button_4, function(...$$args) {
20599
+ var consequent_7 = ($$anchor2) => {
20600
+ var button_5 = root_11();
20601
+ template_effect(() => button_5.disabled = !$$props.canApprove);
20602
+ delegated("click", button_5, function(...$$args) {
20575
20603
  $$props.onNext?.apply(this, $$args);
20576
20604
  });
20577
- append($$anchor2, button_4);
20605
+ append($$anchor2, button_5);
20578
20606
  };
20579
20607
  var alternate_1 = ($$anchor2) => {
20580
- var button_5 = root_11();
20581
- template_effect(() => button_5.disabled = !$$props.canApprove);
20582
- delegated("click", button_5, function(...$$args) {
20608
+ var button_6 = root_122();
20609
+ template_effect(() => button_6.disabled = !$$props.canApprove);
20610
+ delegated("click", button_6, function(...$$args) {
20583
20611
  $$props.onApprove?.apply(this, $$args);
20584
20612
  });
20585
- append($$anchor2, button_5);
20613
+ append($$anchor2, button_6);
20586
20614
  };
20587
- if_block(node_8, ($$render) => {
20588
- if (get2(isAlt)) $$render(consequent_6);
20615
+ if_block(node_9, ($$render) => {
20616
+ if (get2(isAlt)) $$render(consequent_7);
20589
20617
  else $$render(alternate_1, -1);
20590
20618
  });
20591
20619
  }
20592
- var button_6 = sibling(node_8, 2);
20593
- reset(div_11);
20594
- var node_9 = sibling(div_11, 2);
20620
+ var button_7 = sibling(node_9, 2);
20621
+ reset(div_12);
20622
+ var node_10 = sibling(div_12, 2);
20595
20623
  {
20596
- var consequent_7 = ($$anchor2) => {
20597
- var div_12 = root_122();
20598
- var text_3 = child(div_12, true);
20599
- reset(div_12);
20600
- template_effect(() => set_text(text_3, $$props.approvalMessage));
20601
- append($$anchor2, div_12);
20624
+ var consequent_8 = ($$anchor2) => {
20625
+ var div_13 = root_13();
20626
+ var text_4 = child(div_13, true);
20627
+ reset(div_13);
20628
+ template_effect(() => set_text(text_4, $$props.approvalMessage));
20629
+ append($$anchor2, div_13);
20602
20630
  };
20603
- if_block(node_9, ($$render) => {
20604
- if (!$$props.approvalEnabled && $$props.approvalMessage) $$render(consequent_7);
20631
+ if_block(node_10, ($$render) => {
20632
+ if (!$$props.approvalEnabled && $$props.approvalMessage) $$render(consequent_8);
20605
20633
  });
20606
20634
  }
20607
- reset(div_10);
20635
+ reset(div_11);
20608
20636
  reset(div);
20609
20637
  template_effect(() => {
20610
20638
  set_value(input, get2(filterInput));
20611
- button_6.disabled = !$$props.approvalEnabled;
20639
+ button_7.disabled = !$$props.approvalEnabled;
20612
20640
  });
20613
20641
  delegated("input", input, handleFilterInput);
20614
- delegated("click", button_6, () => {
20642
+ delegated("click", button_7, () => {
20615
20643
  if (confirm("Approve all failed screenshots?")) $$props.onApproveAll();
20616
20644
  });
20617
20645
  append($$anchor, div);
@@ -20620,7 +20648,7 @@ function Sidebar($$anchor, $$props) {
20620
20648
  delegate(["click", "input"]);
20621
20649
 
20622
20650
  // src/client/components/SlideView.svelte
20623
- var root_13 = from_html(`<div class="relative flex w-fit"><input class="slide-input" style="z-index: 30" type="range" aria-label="Slide comparison"/> <div class="absolute inset-0 rounded-xl border-2 border-error pointer-events-none z-10"><div class="h-9 px-3 flex items-center justify-end rounded-t-xl" style="background:color-mix(in srgb,var(--c-error) 15%,var(--c-surface))"><span class="text-xs font-bold text-error uppercase tracking-wider select-none">Actual</span></div></div> <div class="absolute overflow-hidden"><img class="max-w-full block" alt="actual"/></div> <div class="absolute inset-0 z-20"><div class="absolute inset-0 rounded-xl border-2 border-success pointer-events-none z-10"><div class="h-9 px-3 flex items-center rounded-t-xl" style="background:color-mix(in srgb,var(--c-success) 15%,var(--c-surface))"><span class="text-xs font-bold text-success uppercase tracking-wider select-none">Expected</span></div></div> <div class="absolute overflow-hidden"><img class="max-w-full block" alt="expect"/></div></div> <img class="opacity-0 max-w-full block" alt="diff"/></div>`);
20651
+ var root_14 = from_html(`<div class="relative flex w-fit"><input class="slide-input" style="z-index: 30" type="range" aria-label="Slide comparison"/> <div class="absolute inset-0 rounded-xl border-2 border-error pointer-events-none z-10"><div class="h-9 px-3 flex items-center justify-end rounded-t-xl" style="background:color-mix(in srgb,var(--c-error) 15%,var(--c-surface))"><span class="text-xs font-bold text-error uppercase tracking-wider select-none">Actual</span></div></div> <div class="absolute overflow-hidden"><img class="max-w-full block" alt="actual"/></div> <div class="absolute inset-0 z-20"><div class="absolute inset-0 rounded-xl border-2 border-success pointer-events-none z-10"><div class="h-9 px-3 flex items-center rounded-t-xl" style="background:color-mix(in srgb,var(--c-success) 15%,var(--c-surface))"><span class="text-xs font-bold text-success uppercase tracking-wider select-none">Expected</span></div></div> <div class="absolute overflow-hidden"><img class="max-w-full block" alt="expect"/></div></div> <img class="opacity-0 max-w-full block" alt="diff"/></div>`);
20624
20652
  var root_23 = from_html(`<div class="flex items-center justify-center p-10 text-fg-muted"></div>`);
20625
20653
  function SlideView($$anchor, $$props) {
20626
20654
  push($$props, true);
@@ -20655,7 +20683,7 @@ function SlideView($$anchor, $$props) {
20655
20683
  var node = first_child(fragment);
20656
20684
  {
20657
20685
  var consequent = ($$anchor2) => {
20658
- var div = root_13();
20686
+ var div = root_14();
20659
20687
  var input = child(div);
20660
20688
  remove_input_defaults(input);
20661
20689
  set_attribute2(input, "min", 0);
@@ -20701,7 +20729,7 @@ function SlideView($$anchor, $$props) {
20701
20729
  delegate(["input"]);
20702
20730
 
20703
20731
  // src/client/components/SideBySideView.svelte
20704
- var root_14 = from_html(`<div class="flex-1 flex flex-col bg-surface-panel rounded-md overflow-hidden min-w-0 border-2 border-green-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-green-500/25 text-green-800 dark:text-green-200 uppercase tracking-wider"> </h3> <div class="flex items-center justify-center p-2"><img alt="Expected" class="w-auto max-w-full object-contain mx-auto" loading="lazy"/></div></div>`);
20732
+ var root_15 = from_html(`<div class="flex-1 flex flex-col bg-surface-panel rounded-md overflow-hidden min-w-0 border-2 border-green-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-green-500/25 text-green-800 dark:text-green-200 uppercase tracking-wider"> </h3> <div class="flex items-center justify-center p-2"><img alt="Expected" class="w-auto max-w-full object-contain mx-auto" loading="lazy"/></div></div>`);
20705
20733
  var root_24 = from_html(`<div class="flex-1 flex flex-col bg-surface-panel rounded-md overflow-hidden min-w-0 border-2 border-yellow-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-yellow-500/25 text-yellow-800 dark:text-yellow-200 uppercase tracking-wider">Diff</h3> <div class="flex items-center justify-center p-2"><img alt="Diff" class="w-auto max-w-full object-contain mx-auto" loading="lazy"/></div></div>`);
20706
20734
  var root_33 = from_html(`<div class="flex-1 flex flex-col bg-surface-panel rounded-md overflow-hidden min-w-0 border-2 border-red-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-red-500/25 text-red-800 dark:text-red-200 uppercase tracking-wider">Actual</h3> <div class="flex items-center justify-center p-2"><img alt="Actual" class="w-auto max-w-full object-contain mx-auto" loading="lazy"/></div></div>`);
20707
20735
  var root3 = from_html(`<div><!> <!> <!></div>`);
@@ -20725,7 +20753,7 @@ function SideBySideView($$anchor, $$props) {
20725
20753
  var node = child(div);
20726
20754
  {
20727
20755
  var consequent = ($$anchor2) => {
20728
- var div_1 = root_14();
20756
+ var div_1 = root_15();
20729
20757
  var h3 = child(div_1);
20730
20758
  var text2 = child(h3, true);
20731
20759
  reset(h3);
@@ -20783,7 +20811,7 @@ function SideBySideView($$anchor, $$props) {
20783
20811
  }
20784
20812
 
20785
20813
  // src/client/components/SwapView.svelte
20786
- var root_15 = from_html(`<img alt="Expected" class="col-start-1 row-start-1 block transition-opacity w-auto max-w-full mx-auto"/>`);
20814
+ var root_16 = from_html(`<img alt="Expected" class="col-start-1 row-start-1 block transition-opacity w-auto max-w-full mx-auto"/>`);
20787
20815
  var root_25 = from_html(`<img alt="Actual" class="col-start-1 row-start-1 block transition-opacity w-auto max-w-full mx-auto"/>`);
20788
20816
  var root4 = from_html(`<div class="flex flex-col gap-3 items-center"><div><h3> </h3> <div class="cursor-pointer p-2" role="button" tabindex="0"><div class="grid"><!> <!></div></div></div></div>`);
20789
20817
  function SwapView($$anchor, $$props) {
@@ -20808,7 +20836,7 @@ function SwapView($$anchor, $$props) {
20808
20836
  var node = child(div_3);
20809
20837
  {
20810
20838
  var consequent = ($$anchor2) => {
20811
- var img = root_15();
20839
+ var img = root_16();
20812
20840
  let styles;
20813
20841
  template_effect(() => {
20814
20842
  set_attribute2(img, "src", $$props.image.expect);
@@ -20860,7 +20888,7 @@ function SwapView($$anchor, $$props) {
20860
20888
  delegate(["click", "keydown"]);
20861
20889
 
20862
20890
  // src/client/components/BlendView.svelte
20863
- var root_16 = from_html(`<div class="absolute w-full h-full flex"><img alt="Expected" class="max-w-full border border-green-500 invert"/></div>`);
20891
+ var root_17 = from_html(`<div class="absolute w-full h-full flex"><img alt="Expected" class="max-w-full border border-green-500 invert"/></div>`);
20864
20892
  var root_26 = from_html(`<img alt="Diff" class="border border-transparent max-w-full invert opacity-0"/>`);
20865
20893
  var root_34 = from_html(`<div class="absolute w-full h-full flex"><img alt="Actual" class="max-w-full border border-red-500 mix-blend-difference invert"/></div>`);
20866
20894
  var root5 = from_html(`<div class="flex flex-col gap-3 items-center"><div class="flex flex-col bg-surface-panel rounded-md overflow-hidden w-fit max-w-full border-2 border-purple-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-purple-500/25 text-purple-800 dark:text-purple-400 uppercase tracking-wider">Blend (Difference)</h3> <div class="p-2"><div class="relative flex invert"><!> <!> <!></div></div></div></div>`);
@@ -20873,7 +20901,7 @@ function BlendView($$anchor, $$props) {
20873
20901
  var node = child(div_3);
20874
20902
  {
20875
20903
  var consequent = ($$anchor2) => {
20876
- var div_4 = root_16();
20904
+ var div_4 = root_17();
20877
20905
  var img = child(div_4);
20878
20906
  reset(div_4);
20879
20907
  template_effect(() => set_attribute2(img, "src", $$props.image.expect));
@@ -20923,7 +20951,7 @@ var root_52 = from_html(`<div class="flex-1 flex items-center justify-center tex
20923
20951
  var root_62 = from_html(`<div class="max-w-xl w-full rounded-md border border-edge bg-surface-panel px-5 py-6 text-center"><h3 class="m-0 text-sm font-semibold text-fg-bright uppercase tracking-wide">Passed Visual Assertion</h3> <p class="mt-3 text-sm leading-6 text-fg-muted">Playwright reported this screenshot assertion, but did not emit an actual, expected, or diff artifact for the passing comparison.</p></div>`);
20924
20952
  var root_72 = from_html(`<div class="w-full flex flex-col gap-3"><!></div>`);
20925
20953
  var root_112 = from_html(`<div class="flex flex-col bg-surface-panel rounded-md overflow-hidden min-w-0 border-2 border-red-500/60"><h3 class="m-0 px-3 py-2 text-xs font-bold bg-red-500/25 text-red-800 dark:text-red-200 uppercase tracking-wider">Actual</h3> <div class="flex items-center justify-center p-2"><img alt="Actual" class="w-auto max-w-full object-contain mx-auto" loading="lazy"/></div></div>`);
20926
- var root_92 = from_html(`<div class="flex flex-col gap-3"><!></div>`);
20954
+ var root_9 = from_html(`<div class="flex flex-col gap-3"><!></div>`);
20927
20955
  var root_123 = from_html(`<div class="w-full flex flex-col gap-3"><!></div>`);
20928
20956
  var root_152 = from_html(`<button> </button>`);
20929
20957
  var root_162 = from_html(`<span class="px-1 text-fg-muted text-xs"></span>`);
@@ -21052,7 +21080,7 @@ function ResultsPage($$anchor, $$props) {
21052
21080
  });
21053
21081
  };
21054
21082
  var consequent_8 = ($$anchor2) => {
21055
- var div_10 = root_92();
21083
+ var div_10 = root_9();
21056
21084
  var node_5 = child(div_10);
21057
21085
  {
21058
21086
  var consequent_6 = ($$anchor3) => {
@@ -21177,7 +21205,7 @@ function ResultsPage($$anchor, $$props) {
21177
21205
  delegate(["click"]);
21178
21206
 
21179
21207
  // src/client/components/Toggle.svelte
21180
- var root_17 = from_svg(`<svg class="block size-3 text-surface" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"></path></svg>`);
21208
+ var root_18 = from_svg(`<svg class="block size-3 text-surface" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M21.752 15.002A9.72 9.72 0 0 1 18 15.75c-5.385 0-9.75-4.365-9.75-9.75 0-1.33.266-2.597.748-3.752A9.753 9.753 0 0 0 3 11.25C3 16.635 7.365 21 12.75 21a9.753 9.753 0 0 0 9.002-5.998Z"></path></svg>`);
21181
21209
  var root_28 = from_svg(`<svg class="block size-3 text-surface" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 2.25a.75.75 0 0 1 .75.75v2.25a.75.75 0 0 1-1.5 0V3a.75.75 0 0 1 .75-.75ZM7.5 12a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0ZM18.894 6.166a.75.75 0 0 0-1.06-1.06l-1.591 1.59a.75.75 0 1 0 1.06 1.061l1.591-1.59ZM21.75 12a.75.75 0 0 1-.75.75h-2.25a.75.75 0 0 1 0-1.5H21a.75.75 0 0 1 .75.75ZM17.834 18.894a.75.75 0 0 0 1.06-1.06l-1.59-1.591a.75.75 0 1 0-1.061 1.06l1.59 1.591ZM12 18a.75.75 0 0 1 .75.75V21a.75.75 0 0 1-1.5 0v-2.25A.75.75 0 0 1 12 18ZM7.758 17.303a.75.75 0 0 0-1.061-1.06l-1.591 1.59a.75.75 0 0 0 1.06 1.061l1.591-1.59ZM6 12a.75.75 0 0 1-.75.75H3a.75.75 0 0 1 0-1.5h2.25A.75.75 0 0 1 6 12ZM6.697 7.757a.75.75 0 0 0 1.06-1.06l-1.59-1.591a.75.75 0 0 0-1.061 1.06l1.59 1.591Z"></path></svg>`);
21182
21210
  var root7 = from_html(`<label class="relative inline-block w-12 h-6 cursor-pointer has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-accent has-[:focus-visible]:ring-offset-1"><input type="checkbox" aria-label="Toggle theme" class="opacity-0 w-0 h-0 absolute"/> <span class="absolute inset-0 bg-surface-input border border-edge rounded-full transition-colors"><span><!></span></span></label>`);
21183
21211
  function Toggle($$anchor, $$props) {
@@ -21190,7 +21218,7 @@ function Toggle($$anchor, $$props) {
21190
21218
  var node = child(span_1);
21191
21219
  {
21192
21220
  var consequent = ($$anchor2) => {
21193
- var svg = root_17();
21221
+ var svg = root_18();
21194
21222
  append($$anchor2, svg);
21195
21223
  };
21196
21224
  var alternate = ($$anchor2) => {
@@ -21223,6 +21251,7 @@ function App($$anchor, $$props) {
21223
21251
  let tests = proxy($$props.initialTests);
21224
21252
  let isRunning = state(proxy($$props.isRunning));
21225
21253
  let runMessage = state(null);
21254
+ let isPreparing = state(false);
21226
21255
  let runSnapshot = null;
21227
21256
  let runEventIds = /* @__PURE__ */ new Set();
21228
21257
  let openedTestPath = state(proxy([]));
@@ -21474,6 +21503,9 @@ function App($$anchor, $$props) {
21474
21503
  async function handleStop() {
21475
21504
  await fetch("/api/stop", { method: "POST" });
21476
21505
  }
21506
+ async function handleUpdate() {
21507
+ await handleStart({ update: true });
21508
+ }
21477
21509
  function handleImageChange(name) {
21478
21510
  set(imageName, name, true);
21479
21511
  }
@@ -21536,6 +21568,12 @@ function App($$anchor, $$props) {
21536
21568
  case "approve":
21537
21569
  break;
21538
21570
  case "run-status": {
21571
+ if (msg.data.phase === "pulling") {
21572
+ set(isPreparing, true);
21573
+ set(runMessage, "Pulling Docker image\u2026");
21574
+ break;
21575
+ }
21576
+ set(isPreparing, false);
21539
21577
  if (msg.data.running) {
21540
21578
  set(isRunning, true);
21541
21579
  set(runMessage, null);
@@ -21598,6 +21636,13 @@ function App($$anchor, $$props) {
21598
21636
  onOpen: handleSuiteOpen,
21599
21637
  onToggle: handleSuiteToggle,
21600
21638
  onStart: handleStart,
21639
+ onUpdate: handleUpdate,
21640
+ get isPreparing() {
21641
+ return get2(isPreparing);
21642
+ },
21643
+ get runMode() {
21644
+ return $$props.runMode;
21645
+ },
21601
21646
  onStop: handleStop,
21602
21647
  onRun: handleRunItem,
21603
21648
  onApprove: handleApproveAndGoNext,
@@ -21694,7 +21739,8 @@ async function loadReportData() {
21694
21739
  liveUpdates: true,
21695
21740
  approvalEnabled: true,
21696
21741
  runEnabled: parsed.runEnabled ?? false,
21697
- isRunning: parsed.isRunning ?? false
21742
+ isRunning: parsed.isRunning ?? false,
21743
+ runMode: parsed.runMode
21698
21744
  };
21699
21745
  }
21700
21746
  var handleApprove = async (id, retry, image) => {
@@ -21724,6 +21770,7 @@ mount(App, {
21724
21770
  approvalMessage: initialState.approvalMessage,
21725
21771
  runEnabled: initialState.runEnabled,
21726
21772
  isRunning: initialState.isRunning,
21773
+ runMode: initialState.runMode,
21727
21774
  onApprove: handleApprove,
21728
21775
  onApproveAll: handleApproveAll
21729
21776
  }
@@ -4,8 +4,6 @@ export type RunEvent = {
4
4
  type: 'test-begin' | 'test-end' | 'run-end';
5
5
  data: unknown;
6
6
  };
7
- export declare function encodeArtifactPathSegment(segment: string): string;
8
- export declare function safeArtifactPath(name: string): string;
9
7
  export declare function sanitizeId(id: string): string;
10
8
  export declare function copyResolvedBaseline(safeTestId: string, testScreenshotDir: string, target: ResolvedBaselineTarget, savedAttachments: AttachmentData[]): Promise<void>;
11
9
  export declare function saveAttachments(screenshotDir: string, testId: string, result: {
@@ -1 +1 @@
1
- {"version":3,"file":"reporter-artifact-ops.d.ts","sourceRoot":"","sources":["../src/reporter-artifact-ops.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAOzE,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErF,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,sBAAsB,EAC9B,gBAAgB,EAAE,cAAc,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAUf;AAED,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;IAAE,WAAW,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,GAC/E,OAAO,CAAC,cAAc,EAAE,CAAC,CAoC3B;AAED,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,QAAQ,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAOf"}
1
+ {"version":3,"file":"reporter-artifact-ops.d.ts","sourceRoot":"","sources":["../src/reporter-artifact-ops.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAIzE,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErF,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE7C;AAaD,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,sBAAsB,EAC9B,gBAAgB,EAAE,cAAc,EAAE,GACjC,OAAO,CAAC,IAAI,CAAC,CAOf;AAED,wBAAsB,eAAe,CACnC,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE;IAAE,WAAW,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE,GAC/E,OAAO,CAAC,cAAc,EAAE,CAAC,CAiC3B;AAED,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,QAAQ,EAAE,EACrB,iBAAiB,EAAE,MAAM,EACzB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAiBf;AAED,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAOf"}