@riddledc/riddle-proof 0.7.21 → 0.7.22
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/basic-gameplay.cjs +128 -8
- package/dist/basic-gameplay.d.cts +28 -5
- package/dist/basic-gameplay.d.ts +28 -5
- package/dist/basic-gameplay.js +1 -1
- package/dist/{chunk-E6O3EOEI.js → chunk-ELZSPOWV.js} +128 -8
- package/dist/{chunk-TPUR67H5.js → chunk-WTHSVHG5.js} +206 -7
- package/dist/cli.cjs +206 -7
- package/dist/cli.js +1 -1
- package/dist/index.cjs +334 -15
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/profile.cjs +206 -7
- package/dist/profile.d.cts +19 -1
- package/dist/profile.d.ts +19 -1
- package/dist/profile.js +1 -1
- package/package.json +1 -1
|
@@ -38,6 +38,79 @@ function stringValue(value) {
|
|
|
38
38
|
function numberValue(value) {
|
|
39
39
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
40
40
|
}
|
|
41
|
+
function horizontalBoundsOverflowPx(value) {
|
|
42
|
+
if (!isRecord(value)) return 0;
|
|
43
|
+
let max = maxPositiveNumber(
|
|
44
|
+
value.overflow_px,
|
|
45
|
+
value.overflow,
|
|
46
|
+
value.bounds_overflow_px,
|
|
47
|
+
value.horizontal_overflow_px,
|
|
48
|
+
value.left_overflow_px,
|
|
49
|
+
value.right_overflow_px
|
|
50
|
+
);
|
|
51
|
+
for (const offender of boundsOffendersForEvidence(value)) {
|
|
52
|
+
max = Math.max(max, horizontalOffenderOverflowPx(offender));
|
|
53
|
+
}
|
|
54
|
+
return roundPixels(max);
|
|
55
|
+
}
|
|
56
|
+
function horizontalOffenderOverflowPx(value) {
|
|
57
|
+
if (!isRecord(value)) return 0;
|
|
58
|
+
let max = maxPositiveNumber(
|
|
59
|
+
value.overflow,
|
|
60
|
+
value.overflow_px,
|
|
61
|
+
value.bounds_overflow_px,
|
|
62
|
+
value.horizontal_overflow_px,
|
|
63
|
+
value.left_overflow_px,
|
|
64
|
+
value.right_overflow_px,
|
|
65
|
+
value.leftOverflowPx,
|
|
66
|
+
value.rightOverflowPx
|
|
67
|
+
);
|
|
68
|
+
const clipped = isRecord(value.clipped || value.clip || value.clipping) ? value.clipped || value.clip || value.clipping : void 0;
|
|
69
|
+
if (isRecord(clipped)) {
|
|
70
|
+
max = Math.max(max, maxPositiveNumber(
|
|
71
|
+
clipped.left,
|
|
72
|
+
clipped.right,
|
|
73
|
+
clipped.left_px,
|
|
74
|
+
clipped.right_px,
|
|
75
|
+
clipped.leftPx,
|
|
76
|
+
clipped.rightPx
|
|
77
|
+
));
|
|
78
|
+
}
|
|
79
|
+
const rect = isRecord(value.rect || value.bounds || value.bounding_rect || value.boundingRect) ? value.rect || value.bounds || value.bounding_rect || value.boundingRect : void 0;
|
|
80
|
+
const viewportWidth = numberValue(value.viewport_width ?? value.viewportWidth);
|
|
81
|
+
if (isRecord(rect) && viewportWidth !== void 0) {
|
|
82
|
+
const left = numberValue(rect.left);
|
|
83
|
+
const right = numberValue(rect.right);
|
|
84
|
+
if (left !== void 0 && left < 0) max = Math.max(max, Math.abs(left));
|
|
85
|
+
if (right !== void 0 && right > viewportWidth) max = Math.max(max, right - viewportWidth);
|
|
86
|
+
}
|
|
87
|
+
return roundPixels(max);
|
|
88
|
+
}
|
|
89
|
+
function boundsOffendersForEvidence(value) {
|
|
90
|
+
if (!isRecord(value)) return [];
|
|
91
|
+
const offenders = [
|
|
92
|
+
...Array.isArray(value.overflow_offenders) ? value.overflow_offenders : [],
|
|
93
|
+
...Array.isArray(value.overflowOffenders) ? value.overflowOffenders : [],
|
|
94
|
+
...Array.isArray(value.bounds_offenders) ? value.bounds_offenders : [],
|
|
95
|
+
...Array.isArray(value.boundsOffenders) ? value.boundsOffenders : [],
|
|
96
|
+
...Array.isArray(value.clipped_elements) ? value.clipped_elements : [],
|
|
97
|
+
...Array.isArray(value.clippedElements) ? value.clippedElements : [],
|
|
98
|
+
...Array.isArray(value.clipping_offenders) ? value.clipping_offenders : [],
|
|
99
|
+
...Array.isArray(value.clippingOffenders) ? value.clippingOffenders : []
|
|
100
|
+
];
|
|
101
|
+
return offenders.filter((item) => isRecord(item)).sort((a, b) => horizontalOffenderOverflowPx(b) - horizontalOffenderOverflowPx(a));
|
|
102
|
+
}
|
|
103
|
+
function maxPositiveNumber(...values) {
|
|
104
|
+
let max = 0;
|
|
105
|
+
for (const value of values) {
|
|
106
|
+
const number = numberValue(value);
|
|
107
|
+
if (number !== void 0 && number > max) max = number;
|
|
108
|
+
}
|
|
109
|
+
return max;
|
|
110
|
+
}
|
|
111
|
+
function roundPixels(value) {
|
|
112
|
+
return Math.round(value * 100) / 100;
|
|
113
|
+
}
|
|
41
114
|
function timeoutSecValue(value) {
|
|
42
115
|
const number = numberValue(value);
|
|
43
116
|
return number && number > 0 ? Math.ceil(number) : void 0;
|
|
@@ -380,7 +453,7 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
380
453
|
message: "No applicable viewport evidence was captured for overflow check."
|
|
381
454
|
};
|
|
382
455
|
}
|
|
383
|
-
const failed = applicable.filter((viewport) => (viewport
|
|
456
|
+
const failed = applicable.filter((viewport) => horizontalBoundsOverflowPx(viewport) > maxOverflow);
|
|
384
457
|
return {
|
|
385
458
|
type: check.type,
|
|
386
459
|
label: checkLabel(check),
|
|
@@ -388,9 +461,11 @@ function assessCheckFromEvidence(check, evidence) {
|
|
|
388
461
|
evidence: {
|
|
389
462
|
max_overflow_px: maxOverflow,
|
|
390
463
|
overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null),
|
|
464
|
+
bounds_overflow_px: applicable.map((viewport) => horizontalBoundsOverflowPx(viewport)),
|
|
465
|
+
overflow_offender_counts: applicable.map((viewport) => boundsOffendersForEvidence(viewport).length),
|
|
391
466
|
viewports: applicable.map((viewport) => viewport.name)
|
|
392
467
|
},
|
|
393
|
-
message: failed.length ? `Horizontal overflow exceeded ${maxOverflow}px in ${failed.length} viewport(s).` : void 0
|
|
468
|
+
message: failed.length ? `Horizontal bounds overflow exceeded ${maxOverflow}px in ${failed.length} viewport(s).` : void 0
|
|
394
469
|
};
|
|
395
470
|
}
|
|
396
471
|
if (check.type === "no_fatal_console_errors") {
|
|
@@ -612,6 +687,77 @@ function textMatches(sample, check) {
|
|
|
612
687
|
}
|
|
613
688
|
return String(sample || "").includes(check.text || "");
|
|
614
689
|
}
|
|
690
|
+
function numberValue(value) {
|
|
691
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
692
|
+
}
|
|
693
|
+
function maxPositiveNumber() {
|
|
694
|
+
let max = 0;
|
|
695
|
+
for (const value of arguments) {
|
|
696
|
+
const number = numberValue(value);
|
|
697
|
+
if (number !== undefined && number > max) max = number;
|
|
698
|
+
}
|
|
699
|
+
return max;
|
|
700
|
+
}
|
|
701
|
+
function roundPixels(value) {
|
|
702
|
+
return Math.round(value * 100) / 100;
|
|
703
|
+
}
|
|
704
|
+
function isRecord(value) {
|
|
705
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
706
|
+
}
|
|
707
|
+
function boundsOffendersForEvidence(value) {
|
|
708
|
+
if (!isRecord(value)) return [];
|
|
709
|
+
const offenders = []
|
|
710
|
+
.concat(Array.isArray(value.overflow_offenders) ? value.overflow_offenders : [])
|
|
711
|
+
.concat(Array.isArray(value.overflowOffenders) ? value.overflowOffenders : [])
|
|
712
|
+
.concat(Array.isArray(value.bounds_offenders) ? value.bounds_offenders : [])
|
|
713
|
+
.concat(Array.isArray(value.boundsOffenders) ? value.boundsOffenders : [])
|
|
714
|
+
.concat(Array.isArray(value.clipped_elements) ? value.clipped_elements : [])
|
|
715
|
+
.concat(Array.isArray(value.clippedElements) ? value.clippedElements : [])
|
|
716
|
+
.concat(Array.isArray(value.clipping_offenders) ? value.clipping_offenders : [])
|
|
717
|
+
.concat(Array.isArray(value.clippingOffenders) ? value.clippingOffenders : []);
|
|
718
|
+
return offenders.filter(isRecord).sort((a, b) => horizontalOffenderOverflowPx(b) - horizontalOffenderOverflowPx(a));
|
|
719
|
+
}
|
|
720
|
+
function horizontalOffenderOverflowPx(value) {
|
|
721
|
+
if (!isRecord(value)) return 0;
|
|
722
|
+
let max = maxPositiveNumber(
|
|
723
|
+
value.overflow,
|
|
724
|
+
value.overflow_px,
|
|
725
|
+
value.bounds_overflow_px,
|
|
726
|
+
value.horizontal_overflow_px,
|
|
727
|
+
value.left_overflow_px,
|
|
728
|
+
value.right_overflow_px,
|
|
729
|
+
value.leftOverflowPx,
|
|
730
|
+
value.rightOverflowPx
|
|
731
|
+
);
|
|
732
|
+
const clipped = value.clipped || value.clip || value.clipping;
|
|
733
|
+
if (isRecord(clipped)) {
|
|
734
|
+
max = Math.max(max, maxPositiveNumber(clipped.left, clipped.right, clipped.left_px, clipped.right_px, clipped.leftPx, clipped.rightPx));
|
|
735
|
+
}
|
|
736
|
+
const rect = value.rect || value.bounds || value.bounding_rect || value.boundingRect;
|
|
737
|
+
const viewportWidth = numberValue(value.viewport_width != null ? value.viewport_width : value.viewportWidth);
|
|
738
|
+
if (isRecord(rect) && viewportWidth !== undefined) {
|
|
739
|
+
const left = numberValue(rect.left);
|
|
740
|
+
const right = numberValue(rect.right);
|
|
741
|
+
if (left !== undefined && left < 0) max = Math.max(max, Math.abs(left));
|
|
742
|
+
if (right !== undefined && right > viewportWidth) max = Math.max(max, right - viewportWidth);
|
|
743
|
+
}
|
|
744
|
+
return roundPixels(max);
|
|
745
|
+
}
|
|
746
|
+
function horizontalBoundsOverflowPx(value) {
|
|
747
|
+
if (!isRecord(value)) return 0;
|
|
748
|
+
let max = maxPositiveNumber(
|
|
749
|
+
value.overflow_px,
|
|
750
|
+
value.overflow,
|
|
751
|
+
value.bounds_overflow_px,
|
|
752
|
+
value.horizontal_overflow_px,
|
|
753
|
+
value.left_overflow_px,
|
|
754
|
+
value.right_overflow_px
|
|
755
|
+
);
|
|
756
|
+
for (const offender of boundsOffendersForEvidence(value)) {
|
|
757
|
+
max = Math.max(max, horizontalOffenderOverflowPx(offender));
|
|
758
|
+
}
|
|
759
|
+
return roundPixels(max);
|
|
760
|
+
}
|
|
615
761
|
function assessProfile(profile, evidence) {
|
|
616
762
|
const checks = [];
|
|
617
763
|
const viewports = evidence.viewports || [];
|
|
@@ -729,13 +875,19 @@ function assessProfile(profile, evidence) {
|
|
|
729
875
|
});
|
|
730
876
|
continue;
|
|
731
877
|
}
|
|
732
|
-
const failed = applicable.filter((viewport) => (viewport
|
|
878
|
+
const failed = applicable.filter((viewport) => horizontalBoundsOverflowPx(viewport) > maxOverflow);
|
|
733
879
|
checks.push({
|
|
734
880
|
type: check.type,
|
|
735
881
|
label: check.label || check.type,
|
|
736
882
|
status: failed.length ? "failed" : "passed",
|
|
737
|
-
evidence: {
|
|
738
|
-
|
|
883
|
+
evidence: {
|
|
884
|
+
max_overflow_px: maxOverflow,
|
|
885
|
+
overflow_px: applicable.map((viewport) => viewport.overflow_px ?? null),
|
|
886
|
+
bounds_overflow_px: applicable.map((viewport) => horizontalBoundsOverflowPx(viewport)),
|
|
887
|
+
overflow_offender_counts: applicable.map((viewport) => boundsOffendersForEvidence(viewport).length),
|
|
888
|
+
viewports: applicable.map((viewport) => viewport.name)
|
|
889
|
+
},
|
|
890
|
+
message: failed.length ? "Horizontal bounds overflow exceeded " + maxOverflow + "px in " + failed.length + " viewport(s)." : undefined,
|
|
739
891
|
});
|
|
740
892
|
continue;
|
|
741
893
|
}
|
|
@@ -965,14 +1117,55 @@ async function captureViewport(viewport) {
|
|
|
965
1117
|
const body = document.body;
|
|
966
1118
|
const documentElement = document.documentElement;
|
|
967
1119
|
const text = (body ? body.innerText : "").replace(/\s+/g, " ").trim();
|
|
1120
|
+
const clientWidth = documentElement ? documentElement.clientWidth : window.innerWidth;
|
|
1121
|
+
const scrollWidth = documentElement ? documentElement.scrollWidth : 0;
|
|
1122
|
+
const viewportWidth = clientWidth || window.innerWidth;
|
|
1123
|
+
const overflowOffenders = [];
|
|
1124
|
+
for (const element of Array.from(body ? body.querySelectorAll("*") : [])) {
|
|
1125
|
+
const rect = element.getBoundingClientRect();
|
|
1126
|
+
if (!rect || rect.width < 1 || rect.height < 1) continue;
|
|
1127
|
+
const style = window.getComputedStyle(element);
|
|
1128
|
+
if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") continue;
|
|
1129
|
+
const leftOverflow = Math.max(0, -rect.left);
|
|
1130
|
+
const rightOverflow = Math.max(0, rect.right - viewportWidth);
|
|
1131
|
+
const overflow = Math.max(leftOverflow, rightOverflow);
|
|
1132
|
+
if (overflow <= 0.5) continue;
|
|
1133
|
+
const tag = element.tagName ? element.tagName.toLowerCase() : "element";
|
|
1134
|
+
const id = element.id ? "#" + element.id : "";
|
|
1135
|
+
const className = typeof element.className === "string"
|
|
1136
|
+
? element.className.trim().split(/\s+/).filter(Boolean).slice(0, 2).join(".")
|
|
1137
|
+
: "";
|
|
1138
|
+
overflowOffenders.push({
|
|
1139
|
+
selector: tag + id + (className ? "." + className : ""),
|
|
1140
|
+
tag,
|
|
1141
|
+
text: (element.textContent || "").replace(/\s+/g, " ").trim().slice(0, 120),
|
|
1142
|
+
overflow,
|
|
1143
|
+
left_overflow_px: leftOverflow,
|
|
1144
|
+
right_overflow_px: rightOverflow,
|
|
1145
|
+
viewport_width: viewportWidth,
|
|
1146
|
+
rect: {
|
|
1147
|
+
left: rect.left,
|
|
1148
|
+
right: rect.right,
|
|
1149
|
+
width: rect.width,
|
|
1150
|
+
},
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
overflowOffenders.sort((a, b) => b.overflow - a.overflow);
|
|
1154
|
+
const boundsOverflowPx = Math.max(
|
|
1155
|
+
0,
|
|
1156
|
+
scrollWidth - (clientWidth || viewportWidth),
|
|
1157
|
+
...overflowOffenders.map((offender) => offender.overflow),
|
|
1158
|
+
);
|
|
968
1159
|
return {
|
|
969
1160
|
url: location.href,
|
|
970
1161
|
pathname: location.pathname,
|
|
971
1162
|
title: document.title,
|
|
972
1163
|
body_text_length: text.length,
|
|
973
1164
|
body_text_sample: text.slice(0, 8000),
|
|
974
|
-
scroll_width:
|
|
975
|
-
client_width:
|
|
1165
|
+
scroll_width: scrollWidth,
|
|
1166
|
+
client_width: clientWidth,
|
|
1167
|
+
bounds_overflow_px: Math.round(boundsOverflowPx * 100) / 100,
|
|
1168
|
+
overflow_offenders: overflowOffenders.slice(0, 10),
|
|
976
1169
|
};
|
|
977
1170
|
}).catch((error) => ({
|
|
978
1171
|
url: page.url(),
|
|
@@ -982,6 +1175,8 @@ async function captureViewport(viewport) {
|
|
|
982
1175
|
body_text_sample: "",
|
|
983
1176
|
scroll_width: 0,
|
|
984
1177
|
client_width: viewport.width,
|
|
1178
|
+
bounds_overflow_px: 0,
|
|
1179
|
+
overflow_offenders: [],
|
|
985
1180
|
evaluation_error: String(error && error.message ? error.message : error).slice(0, 1000),
|
|
986
1181
|
}));
|
|
987
1182
|
const selectors = {};
|
|
@@ -1020,6 +1215,8 @@ async function captureViewport(viewport) {
|
|
|
1020
1215
|
scroll_width: dom.scroll_width,
|
|
1021
1216
|
client_width: dom.client_width,
|
|
1022
1217
|
overflow_px: Math.max(0, (dom.scroll_width || 0) - (dom.client_width || viewport.width)),
|
|
1218
|
+
bounds_overflow_px: dom.bounds_overflow_px,
|
|
1219
|
+
overflow_offenders: dom.overflow_offenders || [],
|
|
1023
1220
|
selectors,
|
|
1024
1221
|
text_matches,
|
|
1025
1222
|
setup_action_results: setupActionResults,
|
|
@@ -1051,6 +1248,8 @@ function buildProfileEvidence(currentViewports) {
|
|
|
1051
1248
|
routes: currentViewports.map((viewport) => viewport.route),
|
|
1052
1249
|
titles: currentViewports.map((viewport) => viewport.title),
|
|
1053
1250
|
overflow_px: currentViewports.map((viewport) => viewport.overflow_px),
|
|
1251
|
+
bounds_overflow_px: currentViewports.map((viewport) => viewport.bounds_overflow_px),
|
|
1252
|
+
overflow_offender_counts: currentViewports.map((viewport) => (viewport.overflow_offenders || []).length),
|
|
1054
1253
|
},
|
|
1055
1254
|
};
|
|
1056
1255
|
}
|
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
|
|
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
|
|
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: {
|
|
7502
|
-
|
|
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:
|
|
7739
|
-
client_width:
|
|
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
|
}
|
package/dist/cli.js
CHANGED