cbrowser 19.4.0 → 19.4.1

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 (33) hide show
  1. package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
  2. package/dist/analysis/accessibility-empathy.js +38 -6
  3. package/dist/analysis/accessibility-empathy.js.map +1 -1
  4. package/dist/analysis/page-understanding.d.ts.map +1 -1
  5. package/dist/analysis/page-understanding.js +27 -1
  6. package/dist/analysis/page-understanding.js.map +1 -1
  7. package/dist/browser.d.ts.map +1 -1
  8. package/dist/browser.js +6 -0
  9. package/dist/browser.js.map +1 -1
  10. package/dist/mcp-server.d.ts.map +1 -1
  11. package/dist/mcp-server.js +3 -2
  12. package/dist/mcp-server.js.map +1 -1
  13. package/dist/mcp-tools/base/performance-tools.d.ts.map +1 -1
  14. package/dist/mcp-tools/base/performance-tools.js +3 -2
  15. package/dist/mcp-tools/base/performance-tools.js.map +1 -1
  16. package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
  17. package/dist/mcp-tools/base/persona-comparison-tools.js +5 -2
  18. package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
  19. package/dist/performance/metrics.d.ts +8 -1
  20. package/dist/performance/metrics.d.ts.map +1 -1
  21. package/dist/performance/metrics.js +24 -14
  22. package/dist/performance/metrics.js.map +1 -1
  23. package/dist/types.d.ts +7 -0
  24. package/dist/types.d.ts.map +1 -1
  25. package/dist/types.js.map +1 -1
  26. package/dist/visual/regression.d.ts +17 -0
  27. package/dist/visual/regression.d.ts.map +1 -1
  28. package/dist/visual/regression.js +19 -0
  29. package/dist/visual/regression.js.map +1 -1
  30. package/dist/visual/responsive.d.ts.map +1 -1
  31. package/dist/visual/responsive.js +41 -4
  32. package/dist/visual/responsive.js.map +1 -1
  33. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"accessibility-empathy.d.ts","sourceRoot":"","sources":["../../src/analysis/accessibility-empathy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoCH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EAEnB,oBAAoB,EAEpB,4BAA4B,EAK7B,MAAM,aAAa,CAAC;AA8OrB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,4BAA4B,CAAA;CAAE,EAChH,QAAQ,EAAE,CAAC,EAAE,EACb,UAAU,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,GAC7B;IAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC,CAAC,GAAG;QAAE,eAAe,EAAE,IAAI,CAAC;QAAC,kBAAkB,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,CAAA;KAAE,CAAC,CAAA;CAAE,CAmB3G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACnH,QAAQ,EAAE,CAAC,EAAE,EACb,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAWhC;AAqgFD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAuG3E;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CA2UjF;AAsBD,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAE9E;AAmKD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAmB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,KAAK,CAAC;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EAC7E,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,EAChC,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,EACnC,SAAS,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,GAC5B,MAAM,EAAE,CAkBV;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAmY7B"}
1
+ {"version":3,"file":"accessibility-empathy.d.ts","sourceRoot":"","sources":["../../src/analysis/accessibility-empathy.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAoCH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EAEnB,oBAAoB,EAEpB,4BAA4B,EAK7B,MAAM,aAAa,CAAC;AA8OrB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,4BAA4B,CAAA;CAAE,EAChH,QAAQ,EAAE,CAAC,EAAE,EACb,UAAU,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,GAC7B;IAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAAC,UAAU,EAAE,KAAK,CAAC,CAAC,GAAG;QAAE,eAAe,EAAE,IAAI,CAAC;QAAC,kBAAkB,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,CAAA;KAAE,CAAC,CAAA;CAAE,CAmB3G;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,EACnH,QAAQ,EAAE,CAAC,EAAE,EACb,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,CAAC,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAWhC;AAoiFD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAuG3E;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CA2UjF;AAsBD,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,CAAC,EAAE;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGhF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,GAAG,MAAM,CAE9E;AAmKD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAmB,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,KAAK,CAAC;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EAC7E,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,EAChC,sBAAsB,EAAE,GAAG,CAAC,MAAM,CAAC,EACnC,SAAS,EAAE,GAAG,GAAG,IAAI,GAAG,KAAK,GAC5B,MAAM,EAAE,CAkBV;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CAmY7B"}
@@ -289,7 +289,7 @@ async function detectSmallTouchTargets(ctx) {
289
289
  const _motorControl = persona.accessibilityTraits.motorControl ?? 0.5;
290
290
  const smallTargets = await page.$$eval('button, a, input[type="checkbox"], input[type="radio"], [role="button"], [onclick]', (elements, vpOnly) => {
291
291
  const vh = window.innerHeight;
292
- return elements.map(el => {
292
+ const mapped = elements.map(el => {
293
293
  const rect = el.getBoundingClientRect();
294
294
  const text = el.textContent?.trim().slice(0, 50) || '';
295
295
  const href = el.href || el.getAttribute('href') || '';
@@ -348,8 +348,27 @@ async function detectSmallTouchTargets(ctx) {
348
348
  area: rect.width * rect.height,
349
349
  inViewport: rect.bottom > 0 && rect.top < vh,
350
350
  exempt: isSkipLink || isVisuallyHidden || isInlineTextLink,
351
+ spaced: false,
352
+ el,
351
353
  };
352
- }).filter(el => {
354
+ });
355
+ // WCAG 2.5.8's spacing exception: an undersized target passes when a 24px
356
+ // circle centred on it intersects no other target and no other undersized
357
+ // target's circle. Without it a lone 152x20 button was a critical AA failure
358
+ // (v10 Q2). Measured against every live target, on or off screen; a target
359
+ // nested in another (a button in a link) is the same target, not a neighbour.
360
+ const live = mapped.filter((m) => m.area > 0 && !m.exempt);
361
+ const small = (m) => Math.round(m.width) < 24 || Math.round(m.height) < 24;
362
+ const centre = (m) => ({ x: m.x + m.width / 2, y: m.y + m.height / 2 });
363
+ const distToRect = (p, m) => Math.hypot(Math.max(m.x - p.x, 0, p.x - (m.x + m.width)), Math.max(m.y - p.y, 0, p.y - (m.y + m.height)));
364
+ for (const u of live) {
365
+ if (!small(u))
366
+ continue;
367
+ const c = centre(u);
368
+ u.spaced = !live.some((t) => t !== u && !t.el.contains(u.el) && !u.el.contains(t.el) &&
369
+ (distToRect(c, t) < 12 || (small(t) && Math.hypot(c.x - centre(t).x, c.y - centre(t).y) < 24)));
370
+ }
371
+ return mapped.map(({ el: _el, ...rest }) => rest).filter(el => {
353
372
  if (el.area <= 0 || el.exempt)
354
373
  return false;
355
374
  if (vpOnly && !el.inViewport)
@@ -373,7 +392,8 @@ async function detectSmallTouchTargets(ctx) {
373
392
  .map((t) => {
374
393
  const w = Math.round(t.width);
375
394
  const h = Math.round(t.height);
376
- return { ...t, w, h, failsAA: w < aaMinimum || h < aaMinimum, failsAAA: w < aaaTarget || h < aaaTarget };
395
+ const undersized = w < aaMinimum || h < aaMinimum;
396
+ return { ...t, w, h, undersized, failsAA: undersized && !t.spaced, failsAAA: w < aaaTarget || h < aaaTarget };
377
397
  })
378
398
  .filter((t) => t.failsAAA);
379
399
  // AA failures first, THEN the cap, so AAA-only candidates (now more numerous
@@ -393,6 +413,14 @@ async function detectSmallTouchTargets(ctx) {
393
413
  rawSeverity = w < 16 || h < 16 ? "critical" : "major";
394
414
  ctx.wcagViolations.add("2.5.8");
395
415
  }
416
+ else if (target.undersized) {
417
+ // Under 24px but passes 2.5.8 AA by its spacing exception; still under the
418
+ // 44px of 2.5.5 AAA. (v10 Q2)
419
+ wcagCriteria.push("2.5.5");
420
+ description = `Touch target under 24px (${w}x${h}px) — passes WCAG 2.5.8 AA by its spacing exception (nothing within its 24px circle), but under 44px for 2.5.5 AAA`;
421
+ rawSeverity = "minor";
422
+ ctx.wcagViolations.add("2.5.5");
423
+ }
396
424
  else {
397
425
  // Passes AA but fails AAA: at least 24 on both axes, under 44 on one.
398
426
  wcagCriteria.push("2.5.5");
@@ -890,7 +918,10 @@ async function detectMotionWithoutPause(ctx) {
890
918
  function pushClassOnlyMotionBarrier(ctx, selectors) {
891
919
  const n = selectors.length;
892
920
  ctx.barriers.push({
893
- type: "cognitive_load",
921
+ // "timing", the type 2.2.2 is weighted as. "cognitive_load" rated the fix
922
+ // "hard" and fired the ADHD "complex form layout" friction on pages with no
923
+ // form. (v10 B44/B45)
924
+ type: "timing",
894
925
  element: `${n} class-named motion element${n === 1 ? "" : "s"}`,
895
926
  // A page-wide aggregate; each element is in members.
896
927
  pageLevel: true,
@@ -907,7 +938,8 @@ function pushClassOnlyMotionBarrier(ctx, selectors) {
907
938
  /** One 2.2.2 barrier for an uncredited motion group. */
908
939
  function pushMotionBarrier(ctx, g) {
909
940
  ctx.barriers.push({
910
- type: "cognitive_load",
941
+ // See pushClassOnlyMotionBarrier: 2.2.2 is a timing barrier. (v10 B44/B45)
942
+ type: "timing",
911
943
  element: g.selector,
912
944
  description: `Moving content (${g.memberCount} animated element${g.memberCount === 1 ? "" : "s"}, found by ${g.detectedBy}) has no associated pause, stop or hide control - may distract users with attention difficulties`,
913
945
  affectedPersonas: ["cognitive-adhd", "dyslexic-user"],
@@ -3261,7 +3293,7 @@ export async function runEmpathyAudit(url, options) {
3261
3293
  if (!persona) {
3262
3294
  // Try to find as a regular cognitive persona and wrap it
3263
3295
  const { getAnyPersona, createCognitivePersona } = await import("../personas.js");
3264
- let cognitivePersona = getAnyPersona(personaName);
3296
+ const cognitivePersona = getAnyPersona(personaName);
3265
3297
  // No CMS fallback here any more: the account's CMS personas were loaded
3266
3298
  // into the scoped registry above, so getAnyPersona already sees them, and
3267
3299
  // a name nothing resolves was refused before the loop. (2026-10-09)