@riddledc/riddle-proof 0.7.21 → 0.7.23

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.
package/dist/cli.cjs CHANGED
@@ -6818,6 +6818,79 @@ function stringValue2(value) {
6818
6818
  function numberValue(value) {
6819
6819
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
6820
6820
  }
6821
+ function horizontalBoundsOverflowPx(value) {
6822
+ if (!isRecord(value)) return 0;
6823
+ let max = maxPositiveNumber(
6824
+ value.overflow_px,
6825
+ value.overflow,
6826
+ value.bounds_overflow_px,
6827
+ value.horizontal_overflow_px,
6828
+ value.left_overflow_px,
6829
+ value.right_overflow_px
6830
+ );
6831
+ for (const offender of boundsOffendersForEvidence(value)) {
6832
+ max = Math.max(max, horizontalOffenderOverflowPx(offender));
6833
+ }
6834
+ return roundPixels(max);
6835
+ }
6836
+ function horizontalOffenderOverflowPx(value) {
6837
+ if (!isRecord(value)) return 0;
6838
+ let max = maxPositiveNumber(
6839
+ value.overflow,
6840
+ value.overflow_px,
6841
+ value.bounds_overflow_px,
6842
+ value.horizontal_overflow_px,
6843
+ value.left_overflow_px,
6844
+ value.right_overflow_px,
6845
+ value.leftOverflowPx,
6846
+ value.rightOverflowPx
6847
+ );
6848
+ const clipped = isRecord(value.clipped || value.clip || value.clipping) ? value.clipped || value.clip || value.clipping : void 0;
6849
+ if (isRecord(clipped)) {
6850
+ max = Math.max(max, maxPositiveNumber(
6851
+ clipped.left,
6852
+ clipped.right,
6853
+ clipped.left_px,
6854
+ clipped.right_px,
6855
+ clipped.leftPx,
6856
+ clipped.rightPx
6857
+ ));
6858
+ }
6859
+ const rect = isRecord(value.rect || value.bounds || value.bounding_rect || value.boundingRect) ? value.rect || value.bounds || value.bounding_rect || value.boundingRect : void 0;
6860
+ const viewportWidth = numberValue(value.viewport_width ?? value.viewportWidth);
6861
+ if (isRecord(rect) && viewportWidth !== void 0) {
6862
+ const left = numberValue(rect.left);
6863
+ const right = numberValue(rect.right);
6864
+ if (left !== void 0 && left < 0) max = Math.max(max, Math.abs(left));
6865
+ if (right !== void 0 && right > viewportWidth) max = Math.max(max, right - viewportWidth);
6866
+ }
6867
+ return roundPixels(max);
6868
+ }
6869
+ function boundsOffendersForEvidence(value) {
6870
+ if (!isRecord(value)) return [];
6871
+ const offenders = [
6872
+ ...Array.isArray(value.overflow_offenders) ? value.overflow_offenders : [],
6873
+ ...Array.isArray(value.overflowOffenders) ? value.overflowOffenders : [],
6874
+ ...Array.isArray(value.bounds_offenders) ? value.bounds_offenders : [],
6875
+ ...Array.isArray(value.boundsOffenders) ? value.boundsOffenders : [],
6876
+ ...Array.isArray(value.clipped_elements) ? value.clipped_elements : [],
6877
+ ...Array.isArray(value.clippedElements) ? value.clippedElements : [],
6878
+ ...Array.isArray(value.clipping_offenders) ? value.clipping_offenders : [],
6879
+ ...Array.isArray(value.clippingOffenders) ? value.clippingOffenders : []
6880
+ ];
6881
+ return offenders.filter((item) => isRecord(item)).sort((a, b) => horizontalOffenderOverflowPx(b) - horizontalOffenderOverflowPx(a));
6882
+ }
6883
+ function maxPositiveNumber(...values) {
6884
+ let max = 0;
6885
+ for (const value of values) {
6886
+ const number = numberValue(value);
6887
+ if (number !== void 0 && number > max) max = number;
6888
+ }
6889
+ return max;
6890
+ }
6891
+ function roundPixels(value) {
6892
+ return Math.round(value * 100) / 100;
6893
+ }
6821
6894
  function timeoutSecValue(value) {
6822
6895
  const number = numberValue(value);
6823
6896
  return number && number > 0 ? Math.ceil(number) : void 0;
@@ -7160,7 +7233,7 @@ function assessCheckFromEvidence(check, evidence) {
7160
7233
  message: "No applicable viewport evidence was captured for overflow check."
7161
7234
  };
7162
7235
  }
7163
- const failed = applicable.filter((viewport) => (viewport.overflow_px ?? 0) > maxOverflow);
7236
+ const failed = applicable.filter((viewport) => horizontalBoundsOverflowPx(viewport) > maxOverflow);
7164
7237
  return {
7165
7238
  type: check.type,
7166
7239
  label: checkLabel(check),
@@ -7168,9 +7241,11 @@ function assessCheckFromEvidence(check, evidence) {
7168
7241
  evidence: {
7169
7242
  max_overflow_px: maxOverflow,
7170
7243
  overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null),
7244
+ bounds_overflow_px: applicable.map((viewport) => horizontalBoundsOverflowPx(viewport)),
7245
+ overflow_offender_counts: applicable.map((viewport) => boundsOffendersForEvidence(viewport).length),
7171
7246
  viewports: applicable.map((viewport) => viewport.name)
7172
7247
  },
7173
- message: failed.length ? `Horizontal overflow exceeded ${maxOverflow}px in ${failed.length} viewport(s).` : void 0
7248
+ message: failed.length ? `Horizontal bounds overflow exceeded ${maxOverflow}px in ${failed.length} viewport(s).` : void 0
7174
7249
  };
7175
7250
  }
7176
7251
  if (check.type === "no_fatal_console_errors") {
@@ -7376,6 +7451,77 @@ function textMatches(sample, check) {
7376
7451
  }
7377
7452
  return String(sample || "").includes(check.text || "");
7378
7453
  }
7454
+ function numberValue(value) {
7455
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
7456
+ }
7457
+ function maxPositiveNumber() {
7458
+ let max = 0;
7459
+ for (const value of arguments) {
7460
+ const number = numberValue(value);
7461
+ if (number !== undefined && number > max) max = number;
7462
+ }
7463
+ return max;
7464
+ }
7465
+ function roundPixels(value) {
7466
+ return Math.round(value * 100) / 100;
7467
+ }
7468
+ function isRecord(value) {
7469
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
7470
+ }
7471
+ function boundsOffendersForEvidence(value) {
7472
+ if (!isRecord(value)) return [];
7473
+ const offenders = []
7474
+ .concat(Array.isArray(value.overflow_offenders) ? value.overflow_offenders : [])
7475
+ .concat(Array.isArray(value.overflowOffenders) ? value.overflowOffenders : [])
7476
+ .concat(Array.isArray(value.bounds_offenders) ? value.bounds_offenders : [])
7477
+ .concat(Array.isArray(value.boundsOffenders) ? value.boundsOffenders : [])
7478
+ .concat(Array.isArray(value.clipped_elements) ? value.clipped_elements : [])
7479
+ .concat(Array.isArray(value.clippedElements) ? value.clippedElements : [])
7480
+ .concat(Array.isArray(value.clipping_offenders) ? value.clipping_offenders : [])
7481
+ .concat(Array.isArray(value.clippingOffenders) ? value.clippingOffenders : []);
7482
+ return offenders.filter(isRecord).sort((a, b) => horizontalOffenderOverflowPx(b) - horizontalOffenderOverflowPx(a));
7483
+ }
7484
+ function horizontalOffenderOverflowPx(value) {
7485
+ if (!isRecord(value)) return 0;
7486
+ let max = maxPositiveNumber(
7487
+ value.overflow,
7488
+ value.overflow_px,
7489
+ value.bounds_overflow_px,
7490
+ value.horizontal_overflow_px,
7491
+ value.left_overflow_px,
7492
+ value.right_overflow_px,
7493
+ value.leftOverflowPx,
7494
+ value.rightOverflowPx
7495
+ );
7496
+ const clipped = value.clipped || value.clip || value.clipping;
7497
+ if (isRecord(clipped)) {
7498
+ max = Math.max(max, maxPositiveNumber(clipped.left, clipped.right, clipped.left_px, clipped.right_px, clipped.leftPx, clipped.rightPx));
7499
+ }
7500
+ const rect = value.rect || value.bounds || value.bounding_rect || value.boundingRect;
7501
+ const viewportWidth = numberValue(value.viewport_width != null ? value.viewport_width : value.viewportWidth);
7502
+ if (isRecord(rect) && viewportWidth !== undefined) {
7503
+ const left = numberValue(rect.left);
7504
+ const right = numberValue(rect.right);
7505
+ if (left !== undefined && left < 0) max = Math.max(max, Math.abs(left));
7506
+ if (right !== undefined && right > viewportWidth) max = Math.max(max, right - viewportWidth);
7507
+ }
7508
+ return roundPixels(max);
7509
+ }
7510
+ function horizontalBoundsOverflowPx(value) {
7511
+ if (!isRecord(value)) return 0;
7512
+ let max = maxPositiveNumber(
7513
+ value.overflow_px,
7514
+ value.overflow,
7515
+ value.bounds_overflow_px,
7516
+ value.horizontal_overflow_px,
7517
+ value.left_overflow_px,
7518
+ value.right_overflow_px
7519
+ );
7520
+ for (const offender of boundsOffendersForEvidence(value)) {
7521
+ max = Math.max(max, horizontalOffenderOverflowPx(offender));
7522
+ }
7523
+ return roundPixels(max);
7524
+ }
7379
7525
  function assessProfile(profile, evidence) {
7380
7526
  const checks = [];
7381
7527
  const viewports = evidence.viewports || [];
@@ -7493,13 +7639,19 @@ function assessProfile(profile, evidence) {
7493
7639
  });
7494
7640
  continue;
7495
7641
  }
7496
- const failed = applicable.filter((viewport) => (viewport.overflow_px || 0) > maxOverflow);
7642
+ const failed = applicable.filter((viewport) => horizontalBoundsOverflowPx(viewport) > maxOverflow);
7497
7643
  checks.push({
7498
7644
  type: check.type,
7499
7645
  label: check.label || check.type,
7500
7646
  status: failed.length ? "failed" : "passed",
7501
- evidence: { max_overflow_px: maxOverflow, overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null), viewports: applicable.map((viewport) => viewport.name) },
7502
- message: failed.length ? "Horizontal overflow exceeded " + maxOverflow + "px in " + failed.length + " viewport(s)." : undefined,
7647
+ evidence: {
7648
+ max_overflow_px: maxOverflow,
7649
+ overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null),
7650
+ bounds_overflow_px: applicable.map((viewport) => horizontalBoundsOverflowPx(viewport)),
7651
+ overflow_offender_counts: applicable.map((viewport) => boundsOffendersForEvidence(viewport).length),
7652
+ viewports: applicable.map((viewport) => viewport.name)
7653
+ },
7654
+ message: failed.length ? "Horizontal bounds overflow exceeded " + maxOverflow + "px in " + failed.length + " viewport(s)." : undefined,
7503
7655
  });
7504
7656
  continue;
7505
7657
  }
@@ -7729,14 +7881,55 @@ async function captureViewport(viewport) {
7729
7881
  const body = document.body;
7730
7882
  const documentElement = document.documentElement;
7731
7883
  const text = (body ? body.innerText : "").replace(/\s+/g, " ").trim();
7884
+ const clientWidth = documentElement ? documentElement.clientWidth : window.innerWidth;
7885
+ const scrollWidth = documentElement ? documentElement.scrollWidth : 0;
7886
+ const viewportWidth = clientWidth || window.innerWidth;
7887
+ const overflowOffenders = [];
7888
+ for (const element of Array.from(body ? body.querySelectorAll("*") : [])) {
7889
+ const rect = element.getBoundingClientRect();
7890
+ if (!rect || rect.width < 1 || rect.height < 1) continue;
7891
+ const style = window.getComputedStyle(element);
7892
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") continue;
7893
+ const leftOverflow = Math.max(0, -rect.left);
7894
+ const rightOverflow = Math.max(0, rect.right - viewportWidth);
7895
+ const overflow = Math.max(leftOverflow, rightOverflow);
7896
+ if (overflow <= 0.5) continue;
7897
+ const tag = element.tagName ? element.tagName.toLowerCase() : "element";
7898
+ const id = element.id ? "#" + element.id : "";
7899
+ const className = typeof element.className === "string"
7900
+ ? element.className.trim().split(/\s+/).filter(Boolean).slice(0, 2).join(".")
7901
+ : "";
7902
+ overflowOffenders.push({
7903
+ selector: tag + id + (className ? "." + className : ""),
7904
+ tag,
7905
+ text: (element.textContent || "").replace(/\s+/g, " ").trim().slice(0, 120),
7906
+ overflow,
7907
+ left_overflow_px: leftOverflow,
7908
+ right_overflow_px: rightOverflow,
7909
+ viewport_width: viewportWidth,
7910
+ rect: {
7911
+ left: rect.left,
7912
+ right: rect.right,
7913
+ width: rect.width,
7914
+ },
7915
+ });
7916
+ }
7917
+ overflowOffenders.sort((a, b) => b.overflow - a.overflow);
7918
+ const boundsOverflowPx = Math.max(
7919
+ 0,
7920
+ scrollWidth - (clientWidth || viewportWidth),
7921
+ ...overflowOffenders.map((offender) => offender.overflow),
7922
+ );
7732
7923
  return {
7733
7924
  url: location.href,
7734
7925
  pathname: location.pathname,
7735
7926
  title: document.title,
7736
7927
  body_text_length: text.length,
7737
7928
  body_text_sample: text.slice(0, 8000),
7738
- scroll_width: documentElement ? documentElement.scrollWidth : 0,
7739
- client_width: documentElement ? documentElement.clientWidth : window.innerWidth,
7929
+ scroll_width: scrollWidth,
7930
+ client_width: clientWidth,
7931
+ bounds_overflow_px: Math.round(boundsOverflowPx * 100) / 100,
7932
+ overflow_offenders: overflowOffenders.slice(0, 10),
7740
7933
  };
7741
7934
  }).catch((error) => ({
7742
7935
  url: page.url(),
@@ -7746,6 +7939,8 @@ async function captureViewport(viewport) {
7746
7939
  body_text_sample: "",
7747
7940
  scroll_width: 0,
7748
7941
  client_width: viewport.width,
7942
+ bounds_overflow_px: 0,
7943
+ overflow_offenders: [],
7749
7944
  evaluation_error: String(error && error.message ? error.message : error).slice(0, 1000),
7750
7945
  }));
7751
7946
  const selectors = {};
@@ -7784,6 +7979,8 @@ async function captureViewport(viewport) {
7784
7979
  scroll_width: dom.scroll_width,
7785
7980
  client_width: dom.client_width,
7786
7981
  overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
7982
+ bounds_overflow_px: dom.bounds_overflow_px,
7983
+ overflow_offenders: dom.overflow_offenders || [],
7787
7984
  selectors,
7788
7985
  text_matches,
7789
7986
  setup_action_results: setupActionResults,
@@ -7815,6 +8012,8 @@ function buildProfileEvidence(currentViewports) {
7815
8012
  routes: currentViewports.map((viewport) => viewport.route),
7816
8013
  titles: currentViewports.map((viewport) => viewport.title),
7817
8014
  overflow_px: currentViewports.map((viewport) => viewport.overflow_px),
8015
+ bounds_overflow_px: currentViewports.map((viewport) => viewport.bounds_overflow_px),
8016
+ overflow_offender_counts: currentViewports.map((viewport) => (viewport.overflow_offenders || []).length),
7818
8017
  },
7819
8018
  };
7820
8019
  }
@@ -7838,24 +8037,36 @@ return result;
7838
8037
  }
7839
8038
  function collectRiddleProfileArtifactRefs(input) {
7840
8039
  const refs = [];
7841
- const seen = /* @__PURE__ */ new Set();
8040
+ const indexes = /* @__PURE__ */ new Map();
8041
+ const priorities = /* @__PURE__ */ new Map();
7842
8042
  function add(item, source) {
7843
8043
  if (!isRecord(item)) return;
7844
- const name = stringValue2(item.name) || stringValue2(item.filename) || "";
7845
8044
  const url = stringValue2(item.url);
7846
8045
  const path7 = stringValue2(item.path);
8046
+ const rawName = stringValue2(item.name) || stringValue2(item.filename) || artifactNameFromPath(url || path7) || "";
8047
+ const name = normalizeRiddleProfileArtifactName(rawName);
7847
8048
  if (!name && !url && !path7) return;
7848
- const key = `${name}:${url || path7 || ""}`;
7849
- if (seen.has(key)) return;
7850
- seen.add(key);
7851
- refs.push({
8049
+ const key = profileArtifactDedupeKey(name, url || path7 || "");
8050
+ const priority = profileArtifactPriority(rawName, name);
8051
+ const ref = {
7852
8052
  name,
7853
8053
  url,
7854
8054
  path: path7,
7855
8055
  kind: stringValue2(item.kind) || stringValue2(item.type),
7856
8056
  content_type: stringValue2(item.content_type) || stringValue2(item.contentType),
7857
8057
  source
7858
- });
8058
+ };
8059
+ const existingIndex = indexes.get(key);
8060
+ if (existingIndex !== void 0) {
8061
+ if (priority > (priorities.get(key) || 0)) {
8062
+ refs[existingIndex] = ref;
8063
+ priorities.set(key, priority);
8064
+ }
8065
+ return;
8066
+ }
8067
+ indexes.set(key, refs.length);
8068
+ priorities.set(key, priority);
8069
+ refs.push(ref);
7859
8070
  }
7860
8071
  function visit(value, source) {
7861
8072
  if (Array.isArray(value)) {
@@ -7870,6 +8081,31 @@ function collectRiddleProfileArtifactRefs(input) {
7870
8081
  visit(input, "artifacts");
7871
8082
  return refs;
7872
8083
  }
8084
+ function normalizeRiddleProfileArtifactName(name) {
8085
+ return name.replace(/\.json\.json$/i, ".json");
8086
+ }
8087
+ function profileArtifactDedupeKey(name, location) {
8088
+ if (PROFILE_SINGLETON_ARTIFACT_NAMES.has(name.toLowerCase())) return name.toLowerCase();
8089
+ return `${name}:${location}`;
8090
+ }
8091
+ function profileArtifactPriority(rawName, normalizedName) {
8092
+ const lower = normalizedName.toLowerCase();
8093
+ if (!PROFILE_SINGLETON_ARTIFACT_NAMES.has(lower)) return 1;
8094
+ return /\.json\.json$/i.test(rawName) ? 2 : 1;
8095
+ }
8096
+ function artifactNameFromPath(value) {
8097
+ if (!value) return "";
8098
+ try {
8099
+ return new URL(value).pathname.split("/").filter(Boolean).pop() || "";
8100
+ } catch {
8101
+ return value.split(/[\\/]/).filter(Boolean).pop() || "";
8102
+ }
8103
+ }
8104
+ var PROFILE_SINGLETON_ARTIFACT_NAMES = /* @__PURE__ */ new Set([
8105
+ "proof.json",
8106
+ "console.json",
8107
+ "dom-summary.json"
8108
+ ]);
7873
8109
  function extractRiddleProofProfileResult(input) {
7874
8110
  if (!isRecord(input)) return void 0;
7875
8111
  if (input.version === RIDDLE_PROOF_PROFILE_RESULT_VERSION) return input;
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  profileStatusExitCode,
11
11
  resolveRiddleProofProfileTargetUrl,
12
12
  resolveRiddleProofProfileTimeoutSec
13
- } from "./chunk-TPUR67H5.js";
13
+ } from "./chunk-XOM2OYAB.js";
14
14
  import {
15
15
  createRiddleApiClient,
16
16
  parseRiddleViewport