@riddledc/riddle-proof 0.7.128 → 0.7.130

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/index.cjs CHANGED
@@ -9340,6 +9340,17 @@ function normalizeSetupActionCoordinateMode(value, index) {
9340
9340
  if (normalized === "ratio" || normalized === "relative" || normalized === "fraction") return "ratio";
9341
9341
  throw new Error(`target.setup_actions[${index}].coordinate_mode ${String(value)} is not supported. Supported coordinate modes: pixels, ratio.`);
9342
9342
  }
9343
+ function normalizeSetupActionPointerType(value, type, index) {
9344
+ if (value === void 0 || value === null || value === "") return void 0;
9345
+ if (type !== "drag") {
9346
+ throw new Error(`target.setup_actions[${index}].pointer_type is only supported for drag actions.`);
9347
+ }
9348
+ const normalized = String(value).trim().replace(/-/g, "_").toLowerCase();
9349
+ if (normalized === "mouse") return "mouse";
9350
+ if (normalized === "touch" || normalized === "finger") return "touch";
9351
+ if (normalized === "pen" || normalized === "stylus") return "pen";
9352
+ throw new Error(`target.setup_actions[${index}].pointer_type ${String(value)} is not supported. Supported pointer types: mouse, touch, pen.`);
9353
+ }
9343
9354
  function normalizeSetupAction(input, index) {
9344
9355
  if (!isRecord2(input)) throw new Error(`target.setup_actions[${index}] must be an object.`);
9345
9356
  const type = normalizeSetupActionType(stringValue5(input.type), index);
@@ -9358,6 +9369,7 @@ function normalizeSetupAction(input, index) {
9358
9369
  const toX = numberValue3(valueFromOwn(input, "to_x", "toX", "end_x", "endX", "x2"));
9359
9370
  const toY = numberValue3(valueFromOwn(input, "to_y", "toY", "end_y", "endY", "y2"));
9360
9371
  const coordinateMode = normalizeSetupActionCoordinateMode(valueFromOwn(input, "coordinate_mode", "coordinateMode", "coords", "units"), index);
9372
+ const pointerType = normalizeSetupActionPointerType(valueFromOwn(input, "pointer_type", "pointerType", "input_type", "inputType"), type, index);
9361
9373
  if (type === "drag") {
9362
9374
  if (fromX === void 0 || fromY === void 0 || toX === void 0 || toY === void 0) {
9363
9375
  throw new Error(`target.setup_actions[${index}] drag requires from_x, from_y, to_x, and to_y.`);
@@ -9442,6 +9454,7 @@ function normalizeSetupAction(input, index) {
9442
9454
  force: type === "click" && (input.force === true || input.force_click === true || input.forceClick === true),
9443
9455
  click_count: normalizeSetupActionClickCount(input, type, index),
9444
9456
  coordinate_mode: coordinateMode,
9457
+ pointer_type: pointerType,
9445
9458
  from_x: fromX,
9446
9459
  from_y: fromY,
9447
9460
  to_x: toX,
@@ -10587,6 +10600,49 @@ function matchText(sample, check) {
10587
10600
  }
10588
10601
  return sample.includes(check.text || "");
10589
10602
  }
10603
+ function compactTextEvidenceSample(value) {
10604
+ return String(value || "").replace(/\s+/g, " ").trim();
10605
+ }
10606
+ function textSampleAroundMatch(sample, index, length) {
10607
+ if (index < 0) return void 0;
10608
+ const source = String(sample || "");
10609
+ const context = 120;
10610
+ const start = Math.max(0, index - context);
10611
+ const end = Math.min(source.length, index + Math.max(length, 1) + context);
10612
+ const prefix = start > 0 ? "..." : "";
10613
+ const suffix = end < source.length ? "..." : "";
10614
+ const compacted = compactTextEvidenceSample(`${prefix}${source.slice(start, end)}${suffix}`);
10615
+ return compacted ? compacted.slice(0, 240) : void 0;
10616
+ }
10617
+ function textMatchSamples(sample, check) {
10618
+ const source = String(sample || "");
10619
+ if (!source) return [];
10620
+ if (check.pattern) {
10621
+ try {
10622
+ const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
10623
+ const match = new RegExp(check.pattern, flags).exec(source);
10624
+ const sampleText2 = match ? textSampleAroundMatch(source, match.index, match[0]?.length || 1) : void 0;
10625
+ return sampleText2 ? [sampleText2] : [];
10626
+ } catch {
10627
+ return [];
10628
+ }
10629
+ }
10630
+ const text = check.text || "";
10631
+ if (!text) return [];
10632
+ const index = source.indexOf(text);
10633
+ const sampleText = textSampleAroundMatch(source, index, text.length);
10634
+ return sampleText ? [sampleText] : [];
10635
+ }
10636
+ function textCheckFailureSamples(viewport, check) {
10637
+ const key = textKey(check);
10638
+ const captured = viewport.text_match_samples?.[key] || [];
10639
+ const capturedSamples = captured.map((sample) => compactTextEvidenceSample(sample).slice(0, 240)).filter(Boolean);
10640
+ if (capturedSamples.length) return capturedSamples.slice(0, 3);
10641
+ const matchedSamples = textMatchSamples(viewport.body_text_sample || "", check);
10642
+ if (matchedSamples.length) return matchedSamples.slice(0, 3);
10643
+ const fallback = compactTextEvidenceSample(viewport.body_text_sample || "").slice(0, 240);
10644
+ return fallback ? [fallback] : [];
10645
+ }
10590
10646
  function allowedMessageSample(input) {
10591
10647
  if (!isRecord2(input)) return String(input || "");
10592
10648
  const parts = [
@@ -11031,10 +11087,17 @@ function assessCheckFromEvidence(check, evidence) {
11031
11087
  if (check.type === "text_visible" || check.type === "text_absent") {
11032
11088
  const key = textKey(check);
11033
11089
  const expectedVisible = check.type === "text_visible";
11034
- const matches = viewports.map((viewport) => {
11090
+ const results = viewports.map((viewport) => {
11035
11091
  const fromEvidence = viewport.text_matches?.[key];
11036
- return typeof fromEvidence === "boolean" ? fromEvidence : matchText(viewport.body_text_sample || "", check);
11092
+ const matched = typeof fromEvidence === "boolean" ? fromEvidence : matchText(viewport.body_text_sample || "", check);
11093
+ const failedAgainstExpectation = matched !== expectedVisible;
11094
+ return {
11095
+ viewport: viewport.name,
11096
+ matched,
11097
+ samples: failedAgainstExpectation ? textCheckFailureSamples(viewport, check) : []
11098
+ };
11037
11099
  });
11100
+ const matches = results.map((result) => result.matched);
11038
11101
  const failed = matches.filter((matched) => matched !== expectedVisible).length;
11039
11102
  return {
11040
11103
  type: check.type,
@@ -11043,7 +11106,8 @@ function assessCheckFromEvidence(check, evidence) {
11043
11106
  evidence: {
11044
11107
  text: check.text || null,
11045
11108
  pattern: check.pattern || null,
11046
- matches
11109
+ matches,
11110
+ viewports: results.map((result) => toJsonValue(result))
11047
11111
  },
11048
11112
  message: failed ? `Text assertion failed in ${failed} viewport(s).` : void 0
11049
11113
  };
@@ -11630,6 +11694,48 @@ function textMatches(sample, check) {
11630
11694
  }
11631
11695
  return String(sample || "").includes(check.text || "");
11632
11696
  }
11697
+ function compactTextEvidenceSample(value) {
11698
+ return String(value || "").replace(/\s+/g, " ").trim();
11699
+ }
11700
+ function textSampleAroundMatch(sample, index, length) {
11701
+ if (index < 0) return undefined;
11702
+ const source = String(sample || "");
11703
+ const context = 120;
11704
+ const start = Math.max(0, index - context);
11705
+ const end = Math.min(source.length, index + Math.max(length, 1) + context);
11706
+ const prefix = start > 0 ? "..." : "";
11707
+ const suffix = end < source.length ? "..." : "";
11708
+ const compacted = compactTextEvidenceSample(prefix + source.slice(start, end) + suffix);
11709
+ return compacted ? compacted.slice(0, 240) : undefined;
11710
+ }
11711
+ function textMatchSamples(sample, check) {
11712
+ const source = String(sample || "");
11713
+ if (!source) return [];
11714
+ if (check.pattern) {
11715
+ try {
11716
+ const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
11717
+ const match = new RegExp(check.pattern, flags).exec(source);
11718
+ const sampleText = match ? textSampleAroundMatch(source, match.index, match[0] ? match[0].length : 1) : undefined;
11719
+ return sampleText ? [sampleText] : [];
11720
+ } catch { return []; }
11721
+ }
11722
+ const text = check.text || "";
11723
+ if (!text) return [];
11724
+ const sampleText = textSampleAroundMatch(source, source.indexOf(text), text.length);
11725
+ return sampleText ? [sampleText] : [];
11726
+ }
11727
+ function textCheckFailureSamples(viewport, check) {
11728
+ const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
11729
+ const captured = viewport && viewport.text_match_samples && Array.isArray(viewport.text_match_samples[key]) ? viewport.text_match_samples[key] : [];
11730
+ const capturedSamples = captured
11731
+ .map((sample) => compactTextEvidenceSample(sample).slice(0, 240))
11732
+ .filter(Boolean);
11733
+ if (capturedSamples.length) return capturedSamples.slice(0, 3);
11734
+ const matchedSamples = textMatchSamples(viewport && viewport.body_text_sample || "", check);
11735
+ if (matchedSamples.length) return matchedSamples.slice(0, 3);
11736
+ const fallback = compactTextEvidenceSample(viewport && viewport.body_text_sample || "").slice(0, 240);
11737
+ return fallback ? [fallback] : [];
11738
+ }
11633
11739
  function allowedMessageSample(input) {
11634
11740
  if (!input || typeof input !== "object" || Array.isArray(input)) return String(input || "");
11635
11741
  const parts = [
@@ -12707,13 +12813,22 @@ function assessProfile(profile, evidence) {
12707
12813
  if (check.type === "text_visible" || check.type === "text_absent") {
12708
12814
  const key = check.pattern ? "pattern:" + check.pattern + "/" + (check.flags || "") : "text:" + (check.text || "");
12709
12815
  const expectedVisible = check.type === "text_visible";
12710
- const matches = checkViewports.map((viewport) => viewport.text_matches && typeof viewport.text_matches[key] === "boolean" ? viewport.text_matches[key] : textMatches(viewport.body_text_sample || "", check));
12816
+ const results = checkViewports.map((viewport) => {
12817
+ const matched = viewport.text_matches && typeof viewport.text_matches[key] === "boolean" ? viewport.text_matches[key] : textMatches(viewport.body_text_sample || "", check);
12818
+ const failedAgainstExpectation = matched !== expectedVisible;
12819
+ return {
12820
+ viewport: viewport.name,
12821
+ matched,
12822
+ samples: failedAgainstExpectation ? textCheckFailureSamples(viewport, check) : [],
12823
+ };
12824
+ });
12825
+ const matches = results.map((result) => result.matched);
12711
12826
  const failed = matches.filter((matched) => matched !== expectedVisible).length;
12712
12827
  checks.push({
12713
12828
  type: check.type,
12714
12829
  label: check.label || check.type,
12715
12830
  status: failed ? "failed" : "passed",
12716
- evidence: { text: check.text, pattern: check.pattern, matches },
12831
+ evidence: { text: check.text, pattern: check.pattern, matches, viewports: results },
12717
12832
  message: failed ? "Text assertion failed in " + failed + " viewport(s)." : undefined,
12718
12833
  });
12719
12834
  continue;
@@ -13033,6 +13148,36 @@ function textMatches(sample, check) {
13033
13148
  }
13034
13149
  return String(sample || "").includes(check.text || "");
13035
13150
  }
13151
+ function compactTextEvidenceSample(value) {
13152
+ return String(value || "").replace(/\s+/g, " ").trim();
13153
+ }
13154
+ function textSampleAroundMatch(sample, index, length) {
13155
+ if (index < 0) return undefined;
13156
+ const source = String(sample || "");
13157
+ const context = 120;
13158
+ const start = Math.max(0, index - context);
13159
+ const end = Math.min(source.length, index + Math.max(length, 1) + context);
13160
+ const prefix = start > 0 ? "..." : "";
13161
+ const suffix = end < source.length ? "..." : "";
13162
+ const compacted = compactTextEvidenceSample(prefix + source.slice(start, end) + suffix);
13163
+ return compacted ? compacted.slice(0, 240) : undefined;
13164
+ }
13165
+ function textMatchSamples(sample, check) {
13166
+ const source = String(sample || "");
13167
+ if (!source) return [];
13168
+ if (check.pattern) {
13169
+ try {
13170
+ const flags = Array.from(new Set(String(check.flags || "").replace(/[gy]/g, "").split(""))).join("");
13171
+ const match = new RegExp(check.pattern, flags).exec(source);
13172
+ const sampleText = match ? textSampleAroundMatch(source, match.index, match[0] ? match[0].length : 1) : undefined;
13173
+ return sampleText ? [sampleText] : [];
13174
+ } catch { return []; }
13175
+ }
13176
+ const text = check.text || "";
13177
+ if (!text) return [];
13178
+ const sampleText = textSampleAroundMatch(source, source.indexOf(text), text.length);
13179
+ return sampleText ? [sampleText] : [];
13180
+ }
13036
13181
  function profileCheckAppliesToViewport(check, viewport) {
13037
13182
  if (!Array.isArray(check.viewports) || !check.viewports.length) return true;
13038
13183
  return Boolean(viewport && viewport.name && check.viewports.includes(viewport.name));
@@ -13510,23 +13655,75 @@ async function executeSetupAction(action, ordinal, viewport) {
13510
13655
  const requestedSteps = setupNumber(action.steps, 8);
13511
13656
  const steps = Math.min(100, Math.max(1, Math.floor(requestedSteps || 8)));
13512
13657
  const durationMs = setupNumber(action.duration_ms ?? action.durationMs, 0);
13513
- await page.mouse.move(start.x, start.y);
13514
- await page.mouse.down();
13515
- try {
13516
- if (durationMs && steps > 1) {
13517
- for (let step = 1; step <= steps; step += 1) {
13518
- const progress = step / steps;
13519
- await page.mouse.move(
13520
- start.x + (end.x - start.x) * progress,
13521
- start.y + (end.y - start.y) * progress,
13522
- );
13523
- await page.waitForTimeout(durationMs / steps);
13658
+ const pointerType = String(action.pointer_type || action.pointerType || "mouse").trim().toLowerCase();
13659
+ if (pointerType === "touch" || pointerType === "pen") {
13660
+ const localStart = {
13661
+ x: coordinate(fromX, box.width),
13662
+ y: coordinate(fromY, box.height),
13663
+ };
13664
+ const localEnd = {
13665
+ x: coordinate(toX, box.width),
13666
+ y: coordinate(toY, box.height),
13667
+ };
13668
+ await target.evaluate(async (element, payload) => {
13669
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
13670
+ const rect = element.getBoundingClientRect();
13671
+ const pointerId = payload.pointerType === "touch" ? 11 : 12;
13672
+ const point = (progress) => ({
13673
+ clientX: rect.left + payload.start.x + (payload.end.x - payload.start.x) * progress,
13674
+ clientY: rect.top + payload.start.y + (payload.end.y - payload.start.y) * progress,
13675
+ });
13676
+ const dispatch = (type, progress) => {
13677
+ const coords = point(progress);
13678
+ element.dispatchEvent(new PointerEvent(type, {
13679
+ bubbles: true,
13680
+ cancelable: true,
13681
+ composed: true,
13682
+ pointerId,
13683
+ pointerType: payload.pointerType,
13684
+ isPrimary: true,
13685
+ buttons: type === "pointerup" ? 0 : 1,
13686
+ button: type === "pointerup" ? 0 : 0,
13687
+ clientX: coords.clientX,
13688
+ clientY: coords.clientY,
13689
+ }));
13690
+ };
13691
+ dispatch("pointerover", 0);
13692
+ dispatch("pointerenter", 0);
13693
+ dispatch("pointerdown", 0);
13694
+ for (let step = 1; step <= payload.steps; step += 1) {
13695
+ dispatch("pointermove", step / payload.steps);
13696
+ if (payload.durationMs && payload.steps > 1) await wait(payload.durationMs / payload.steps);
13524
13697
  }
13525
- } else {
13526
- await page.mouse.move(end.x, end.y, { steps });
13698
+ dispatch("pointerup", 1);
13699
+ dispatch("pointerout", 1);
13700
+ dispatch("pointerleave", 1);
13701
+ }, {
13702
+ pointerType,
13703
+ start: localStart,
13704
+ end: localEnd,
13705
+ steps,
13706
+ durationMs,
13707
+ });
13708
+ } else {
13709
+ await page.mouse.move(start.x, start.y);
13710
+ await page.mouse.down();
13711
+ try {
13712
+ if (durationMs && steps > 1) {
13713
+ for (let step = 1; step <= steps; step += 1) {
13714
+ const progress = step / steps;
13715
+ await page.mouse.move(
13716
+ start.x + (end.x - start.x) * progress,
13717
+ start.y + (end.y - start.y) * progress,
13718
+ );
13719
+ await page.waitForTimeout(durationMs / steps);
13720
+ }
13721
+ } else {
13722
+ await page.mouse.move(end.x, end.y, { steps });
13723
+ }
13724
+ } finally {
13725
+ await page.mouse.up().catch(() => {});
13527
13726
  }
13528
- } finally {
13529
- await page.mouse.up().catch(() => {});
13530
13727
  }
13531
13728
  return {
13532
13729
  ...base,
@@ -13539,6 +13736,7 @@ async function executeSetupAction(action, ordinal, viewport) {
13539
13736
  from_y: fromY,
13540
13737
  to_x: toX,
13541
13738
  to_y: toY,
13739
+ pointer_type: pointerType,
13542
13740
  steps,
13543
13741
  duration_ms: durationMs || undefined,
13544
13742
  };
@@ -14984,6 +15182,7 @@ async function captureViewport(viewport) {
14984
15182
  const frames = {};
14985
15183
  const text_sequences = {};
14986
15184
  const text_matches = {};
15185
+ const text_match_samples = {};
14987
15186
  const http_statuses = {};
14988
15187
  const link_statuses = {};
14989
15188
  for (const check of profile.checks || []) {
@@ -15005,7 +15204,10 @@ async function captureViewport(viewport) {
15005
15204
  text_sequences[check.selector] = await selectorTextSequence(check.selector);
15006
15205
  }
15007
15206
  if ((check.type === "text_visible" || check.type === "text_absent") && (check.text || check.pattern)) {
15008
- text_matches[textKey(check)] = textMatches(dom.body_text || dom.body_text_sample || "", check);
15207
+ const key = textKey(check);
15208
+ const sample = dom.body_text || dom.body_text_sample || "";
15209
+ text_matches[key] = textMatches(sample, check);
15210
+ text_match_samples[key] = textMatchSamples(sample, check);
15009
15211
  }
15010
15212
  if ((check.type === "frame_text_visible" || check.type === "frame_url_equals" || check.type === "frame_url_matches" || check.type === "frame_no_horizontal_overflow") && check.selector) {
15011
15213
  selectors[check.selector] = selectors[check.selector] || await selectorStats(check.selector);
@@ -15082,6 +15284,7 @@ async function captureViewport(viewport) {
15082
15284
  frames,
15083
15285
  text_sequences,
15084
15286
  text_matches,
15287
+ text_match_samples,
15085
15288
  http_statuses,
15086
15289
  link_statuses,
15087
15290
  route_inventory: routeInventory,
package/dist/index.js CHANGED
@@ -62,7 +62,7 @@ import {
62
62
  resolveRiddleProofProfileTimeoutSec,
63
63
  slugifyRiddleProofProfileName,
64
64
  summarizeRiddleProofProfileResult
65
- } from "./chunk-TO3FVF5S.js";
65
+ } from "./chunk-ZJNM3YAB.js";
66
66
  import {
67
67
  DEFAULT_RIDDLE_API_BASE_URL,
68
68
  DEFAULT_RIDDLE_API_KEY_FILE,