@setsquare/review-sdk 0.0.1 → 0.1.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.
- package/NOTICE +3 -2
- package/README.md +220 -0
- package/dist/autoscan.d.ts +15 -1
- package/dist/autoscan.d.ts.map +1 -1
- package/dist/autoscan.js +168 -13
- package/dist/autoscan.js.map +1 -1
- package/dist/brand.d.ts +51 -2
- package/dist/brand.d.ts.map +1 -1
- package/dist/brand.js +560 -5
- package/dist/brand.js.map +1 -1
- package/dist/checks/context-change.d.ts +96 -0
- package/dist/checks/context-change.d.ts.map +1 -0
- package/dist/checks/context-change.js +655 -0
- package/dist/checks/context-change.js.map +1 -0
- package/dist/checks/focus.d.ts +154 -0
- package/dist/checks/focus.d.ts.map +1 -0
- package/dist/checks/focus.js +1123 -0
- package/dist/checks/focus.js.map +1 -0
- package/dist/checks/heuristics.d.ts +116 -0
- package/dist/checks/heuristics.d.ts.map +1 -0
- package/dist/checks/heuristics.js +931 -0
- package/dist/checks/heuristics.js.map +1 -0
- package/dist/checks/keyboard.d.ts +106 -0
- package/dist/checks/keyboard.d.ts.map +1 -0
- package/dist/checks/keyboard.js +452 -0
- package/dist/checks/keyboard.js.map +1 -0
- package/dist/checks/reflow.d.ts +75 -0
- package/dist/checks/reflow.d.ts.map +1 -0
- package/dist/checks/reflow.js +285 -0
- package/dist/checks/reflow.js.map +1 -0
- package/dist/checks/rule-pack.d.ts +1 -1
- package/dist/checks/rule-pack.d.ts.map +1 -1
- package/dist/checks/rule-pack.js +350 -45
- package/dist/checks/rule-pack.js.map +1 -1
- package/dist/checks/shortcuts.d.ts +71 -0
- package/dist/checks/shortcuts.d.ts.map +1 -0
- package/dist/checks/shortcuts.js +196 -0
- package/dist/checks/shortcuts.js.map +1 -0
- package/dist/checks/versions.d.ts.map +1 -1
- package/dist/checks/versions.js +33 -1
- package/dist/checks/versions.js.map +1 -1
- package/dist/contract.d.ts +18 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/covers.d.ts +56 -0
- package/dist/covers.d.ts.map +1 -0
- package/dist/covers.js +135 -0
- package/dist/covers.js.map +1 -0
- package/dist/dedupe.d.ts +23 -0
- package/dist/dedupe.d.ts.map +1 -1
- package/dist/dedupe.js +96 -2
- package/dist/dedupe.js.map +1 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +144 -0
- package/dist/document.js.map +1 -1
- package/dist/envelope.d.ts +8 -0
- package/dist/envelope.d.ts.map +1 -1
- package/dist/envelope.js +28 -0
- package/dist/envelope.js.map +1 -1
- package/dist/fixture.d.ts.map +1 -1
- package/dist/fixture.js +12 -0
- package/dist/fixture.js.map +1 -1
- package/dist/html-report.d.ts +24 -7
- package/dist/html-report.d.ts.map +1 -1
- package/dist/html-report.js +608 -136
- package/dist/html-report.js.map +1 -1
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +43 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +43 -0
- package/dist/links.js.map +1 -1
- package/dist/observe.d.ts +8 -0
- package/dist/observe.d.ts.map +1 -1
- package/dist/observe.js +45 -1
- package/dist/observe.js.map +1 -1
- package/dist/options.d.ts +53 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +3 -0
- package/dist/options.js.map +1 -1
- package/dist/reading-level.d.ts +22 -1
- package/dist/reading-level.d.ts.map +1 -1
- package/dist/reading-level.js +122 -19
- package/dist/reading-level.js.map +1 -1
- package/dist/reporter.d.ts.map +1 -1
- package/dist/reporter.js +31 -15
- package/dist/reporter.js.map +1 -1
- package/dist/scan.d.ts +36 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +16 -2
- package/dist/scan.js.map +1 -1
- package/dist/screens.d.ts +55 -4
- package/dist/screens.d.ts.map +1 -1
- package/dist/screens.js +243 -43
- package/dist/screens.js.map +1 -1
- package/dist/summary.d.ts +22 -0
- package/dist/summary.d.ts.map +1 -1
- package/dist/summary.js +197 -22
- package/dist/summary.js.map +1 -1
- package/dist/viewports.d.ts +105 -0
- package/dist/viewports.d.ts.map +1 -0
- package/dist/viewports.js +134 -0
- package/dist/viewports.js.map +1 -0
- package/package.json +5 -4
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { CHARACTER_KEY_SHORTCUTS_HELP_URL } from '../links.js';
|
|
2
|
+
import { sanitiseLabel } from '../sanitise.js';
|
|
3
|
+
/**
|
|
4
|
+
* WCAG 2.1.4 Character Key Shortcuts (A): a single-character shortcut with no
|
|
5
|
+
* way to turn it off or remap it makes a page unusable for anyone using speech
|
|
6
|
+
* input, because every dictated word is a volley of shortcuts.
|
|
7
|
+
*
|
|
8
|
+
* A small rule and a real failure — and the only one in this package that
|
|
9
|
+
* needs to run BEFORE the customer's own code. There is no way to enumerate a
|
|
10
|
+
* page's event listeners after the fact: `getEventListeners` is a DevTools
|
|
11
|
+
* API and does not exist in page script. So the only route is to wrap
|
|
12
|
+
* `addEventListener` at init time and watch what gets registered.
|
|
13
|
+
*
|
|
14
|
+
* ---------------------------------------------------------------------------
|
|
15
|
+
* **Opt-in, and off by default, because of the footprint.**
|
|
16
|
+
*
|
|
17
|
+
* Everything else this SDK does happens after a page has loaded and can be
|
|
18
|
+
* undone. This patches a DOM method before any of the customer's scripts run,
|
|
19
|
+
* for the whole life of the page. Even proven inert, that is a larger presence
|
|
20
|
+
* in someone's application than a scanner has any business having by default —
|
|
21
|
+
* and "it is only a pass-through" is exactly the reasoning that precedes a
|
|
22
|
+
* subtle break in someone else's product.
|
|
23
|
+
*
|
|
24
|
+
* So it is a choice, `keyShortcuts: true`, and while it is off the criterion
|
|
25
|
+
* reports as a check that exists and did not run here, which is what it is.
|
|
26
|
+
*
|
|
27
|
+
* **Inertness, concretely.** The wrapper records `(type, target)` and the key
|
|
28
|
+
* literals it can read out of the handler's own source, then delegates with
|
|
29
|
+
* the ORIGINAL arguments — never a wrapped listener. That last part is what
|
|
30
|
+
* keeps `removeEventListener` working: a wrapped listener is a different
|
|
31
|
+
* function object and would never match, so a page that adds and removes a
|
|
32
|
+
* handler would silently keep it forever. The fixture asserts exactly that.
|
|
33
|
+
* ---------------------------------------------------------------------------
|
|
34
|
+
*/
|
|
35
|
+
export const SETSQUARE_SHORTCUTS_CHECK_VERSION = 'setsquare-shortcuts@1';
|
|
36
|
+
export const KEY_SHORTCUTS_RULE_ID = 'setsquare-key-shortcuts';
|
|
37
|
+
/** Handlers to look at. Beyond this a page is instrumenting, not shortcutting. */
|
|
38
|
+
const MAX_HANDLERS = 40;
|
|
39
|
+
/**
|
|
40
|
+
* Installed before any page script. See the class comment for why this is
|
|
41
|
+
* opt-in; see `fixture.ts` for where it is installed.
|
|
42
|
+
*
|
|
43
|
+
* A source string rather than a function, because `addInitScript` serialises
|
|
44
|
+
* it and a closure over anything in this module would not survive.
|
|
45
|
+
*/
|
|
46
|
+
export const KEY_LISTENER_SCRIPT = `
|
|
47
|
+
(() => {
|
|
48
|
+
const found = [];
|
|
49
|
+
Object.defineProperty(window, '__setsquareKeyListeners', {
|
|
50
|
+
value: found,
|
|
51
|
+
// Non-enumerable so it does not appear in a customer's own iteration over
|
|
52
|
+
// window, and non-writable so page code cannot clobber it by accident.
|
|
53
|
+
enumerable: false,
|
|
54
|
+
writable: false,
|
|
55
|
+
configurable: true,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const KEY_EVENTS = new Set(['keydown', 'keypress', 'keyup']);
|
|
59
|
+
const MODIFIER = /\\b(ctrlKey|metaKey|altKey|shiftKey|getModifierState)\\b/;
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* Which keys a handler reacts to, read out of its own source.
|
|
63
|
+
*
|
|
64
|
+
* The instrumentation can see THAT a key listener exists and never which key
|
|
65
|
+
* it cares about — so without this the finding would be "this page has a
|
|
66
|
+
* keydown handler", which is true of most of the web and useful to nobody.
|
|
67
|
+
* Reading the source is a heuristic and is treated as one: everything this
|
|
68
|
+
* rule reports is needs-review.
|
|
69
|
+
*
|
|
70
|
+
* A handler that consults a modifier is not what 2.1.4 is about, so it is
|
|
71
|
+
* left alone. That is most of the false positives.
|
|
72
|
+
*/
|
|
73
|
+
const keysIn = (source) => {
|
|
74
|
+
if (typeof source !== 'string' || source.length === 0) return [];
|
|
75
|
+
if (source.indexOf('[native code]') !== -1) return [];
|
|
76
|
+
if (MODIFIER.test(source)) return [];
|
|
77
|
+
|
|
78
|
+
const keys = new Set();
|
|
79
|
+
const literal = /(?:\\.key\\s*={2,3}\\s*|case\\s+)['"]([^'"\\\\]{1})['"]/g;
|
|
80
|
+
let match;
|
|
81
|
+
while ((match = literal.exec(source)) !== null) {
|
|
82
|
+
const key = match[1];
|
|
83
|
+
// Printable, single character, not whitespace. Enter, Escape and Tab are
|
|
84
|
+
// multi-character names and fall out here, which is right: 2.1.4 is
|
|
85
|
+
// about character keys.
|
|
86
|
+
if (key.trim().length === 1) keys.add(key);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const code = /(?:keyCode|which)\\s*={2,3}\\s*(\\d{2,3})/g;
|
|
90
|
+
while ((match = code.exec(source)) !== null) {
|
|
91
|
+
const value = Number(match[1]);
|
|
92
|
+
// Letters and digits only. The named keys have codes too, and reporting
|
|
93
|
+
// Escape as a character shortcut would be wrong.
|
|
94
|
+
if (value >= 48 && value <= 57) keys.add(String(value - 48));
|
|
95
|
+
else if (value >= 65 && value <= 90) keys.add(String.fromCharCode(value).toLowerCase());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return [...keys];
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const original = EventTarget.prototype.addEventListener;
|
|
102
|
+
EventTarget.prototype.addEventListener = function (type, listener, options) {
|
|
103
|
+
try {
|
|
104
|
+
if (KEY_EVENTS.has(type) && (this === document || this === window) && found.length < 40) {
|
|
105
|
+
let source = '';
|
|
106
|
+
try {
|
|
107
|
+
source = typeof listener === 'function' ? Function.prototype.toString.call(listener) : '';
|
|
108
|
+
} catch {}
|
|
109
|
+
const keys = keysIn(source);
|
|
110
|
+
if (keys.length > 0) {
|
|
111
|
+
found.push({ type, target: this === window ? 'window' : 'document', keys });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} catch {}
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* The original arguments, never a wrapper. A wrapped listener is a
|
|
118
|
+
* different function object, so removeEventListener would never match it
|
|
119
|
+
* and a page that adds and removes a handler would silently keep it for
|
|
120
|
+
* ever. That is the failure this line exists to prevent.
|
|
121
|
+
*/
|
|
122
|
+
return original.call(this, type, listener, options);
|
|
123
|
+
};
|
|
124
|
+
})();
|
|
125
|
+
`;
|
|
126
|
+
/**
|
|
127
|
+
* Read what the instrumentation saw. Returns nothing when it was never
|
|
128
|
+
* installed, which is the honest answer for an opt-in check that is off.
|
|
129
|
+
*/
|
|
130
|
+
export async function runKeyShortcuts(page) {
|
|
131
|
+
try {
|
|
132
|
+
const rows = await page.evaluate(() => {
|
|
133
|
+
const found = window['__setsquareKeyListeners'];
|
|
134
|
+
return Array.isArray(found) ? found.slice(0, 40) : undefined;
|
|
135
|
+
});
|
|
136
|
+
if (rows === undefined)
|
|
137
|
+
return {};
|
|
138
|
+
return keyShortcutEvidence(rows);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const SHORTCUTS_WCAG = { criteria: ['2.1.4'], level: 'A', versionTags: [] };
|
|
145
|
+
/**
|
|
146
|
+
* The verdict, and it is always needs-review or inapplicable — never a
|
|
147
|
+
* violation, and the reason is worth stating rather than assuming.
|
|
148
|
+
*
|
|
149
|
+
* 2.1.4 is satisfied if the shortcut can be turned off, remapped, or is only
|
|
150
|
+
* active when a specific component has focus. All three are page-level
|
|
151
|
+
* affordances: the first two live in a settings screen we are not looking at,
|
|
152
|
+
* and the third is a property of the handler's own logic. We can see that a
|
|
153
|
+
* handler compares against `j`; we cannot see whether the user was ever
|
|
154
|
+
* offered a way to stop it. Reporting a violation from what we CAN see would
|
|
155
|
+
* be asserting the part we cannot.
|
|
156
|
+
*/
|
|
157
|
+
export function keyShortcutEvidence(rows) {
|
|
158
|
+
const usable = rows.filter((row) => row.keys.length > 0).slice(0, MAX_HANDLERS);
|
|
159
|
+
if (usable.length === 0) {
|
|
160
|
+
// The instrumentation ran and found no unmodified character handler. That
|
|
161
|
+
// is a real observation about the page, not an absence of one.
|
|
162
|
+
return { inapplicable: { ruleId: KEY_SHORTCUTS_RULE_ID, wcag: SHORTCUTS_WCAG } };
|
|
163
|
+
}
|
|
164
|
+
const keys = [...new Set(usable.flatMap((row) => row.keys))].sort();
|
|
165
|
+
const first = usable[0];
|
|
166
|
+
return {
|
|
167
|
+
finding: {
|
|
168
|
+
ruleId: KEY_SHORTCUTS_RULE_ID,
|
|
169
|
+
status: 'incomplete',
|
|
170
|
+
impact: 'moderate',
|
|
171
|
+
wcag: SHORTCUTS_WCAG,
|
|
172
|
+
helpUrl: CHARACTER_KEY_SHORTCUTS_HELP_URL,
|
|
173
|
+
evidence: {
|
|
174
|
+
failureSummary: `A ${first.type} handler on ${first.target} reacts to the character key(s) ` +
|
|
175
|
+
`${keys.map((key) => `"${key}"`).join(', ')} without consulting a modifier. ` +
|
|
176
|
+
`${usable.length} handler(s) found. WCAG 2.1.4 is satisfied if the shortcut can be ` +
|
|
177
|
+
`turned off, remapped, or is only active when a specific component has focus — all ` +
|
|
178
|
+
`three are affordances this check cannot see, so it is not reported as a failure. ` +
|
|
179
|
+
`A person confirms one of them exists. This matters most for speech input, where ` +
|
|
180
|
+
`every dictated word is a volley of these.`,
|
|
181
|
+
},
|
|
182
|
+
// Selectors are the wrong shape for a document-level handler, so the
|
|
183
|
+
// targets are the handlers themselves, named by what they listen to.
|
|
184
|
+
targets: {
|
|
185
|
+
nodeCount: usable.length,
|
|
186
|
+
selectors: usable
|
|
187
|
+
.slice(0, 10)
|
|
188
|
+
.map((handler) => `${handler.target} ${handler.type} [${handler.keys.join(' ')}]`)
|
|
189
|
+
.map((label) => sanitiseLabel(label))
|
|
190
|
+
.filter((label) => label !== undefined),
|
|
191
|
+
selectorsTruncated: usable.length > 10,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=shortcuts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../../src/checks/shortcuts.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/checks/versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"versions.d.ts","sourceRoot":"","sources":["../../src/checks/versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAa9C;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAanE;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAyB1E,CAAC"}
|
package/dist/checks/versions.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { readingLevelEnabled } from '../runtime.js';
|
|
2
2
|
import { SETSQUARE_DYNAMIC_CHECKS_VERSION } from './dynamic.js';
|
|
3
|
+
import { SETSQUARE_FOCUS_CHECKS_VERSION } from './focus.js';
|
|
4
|
+
import { SETSQUARE_KEYBOARD_CHECKS_VERSION } from './keyboard.js';
|
|
5
|
+
import { SETSQUARE_CONTEXT_CHECK_VERSION } from './context-change.js';
|
|
6
|
+
import { SETSQUARE_REFLOW_CHECK_VERSION } from './reflow.js';
|
|
7
|
+
import { SETSQUARE_HEURISTICS_VERSION } from './heuristics.js';
|
|
8
|
+
import { SETSQUARE_SHORTCUTS_CHECK_VERSION } from './shortcuts.js';
|
|
3
9
|
import { SETSQUARE_RULE_PACK_VERSION } from './rule-pack.js';
|
|
4
10
|
import { READING_LEVEL_CHECK_VERSION } from '../reading-level.js';
|
|
5
11
|
/**
|
|
@@ -15,7 +21,15 @@ import { READING_LEVEL_CHECK_VERSION } from '../reading-level.js';
|
|
|
15
21
|
* teach people to ignore the warning that exists to catch real drift.
|
|
16
22
|
*/
|
|
17
23
|
export function setsquareCheckVersions(policy) {
|
|
18
|
-
const versions = [
|
|
24
|
+
const versions = [
|
|
25
|
+
SETSQUARE_DYNAMIC_CHECKS_VERSION,
|
|
26
|
+
SETSQUARE_FOCUS_CHECKS_VERSION,
|
|
27
|
+
SETSQUARE_KEYBOARD_CHECKS_VERSION,
|
|
28
|
+
SETSQUARE_REFLOW_CHECK_VERSION,
|
|
29
|
+
SETSQUARE_CONTEXT_CHECK_VERSION,
|
|
30
|
+
SETSQUARE_SHORTCUTS_CHECK_VERSION,
|
|
31
|
+
SETSQUARE_HEURISTICS_VERSION,
|
|
32
|
+
];
|
|
19
33
|
if (policy.target === 'AAA')
|
|
20
34
|
versions.push(SETSQUARE_RULE_PACK_VERSION);
|
|
21
35
|
if (readingLevelEnabled())
|
|
@@ -41,5 +55,23 @@ export const SETSQUARE_CHECK_CRITERIA = new Map([
|
|
|
41
55
|
['setsquare-target-size-aaa', ['2.5.5']],
|
|
42
56
|
['setsquare-visual-presentation', ['1.4.8']],
|
|
43
57
|
['setsquare-link-purpose', ['2.4.9']],
|
|
58
|
+
['setsquare-focus-obscured', ['2.4.11']],
|
|
59
|
+
['setsquare-focus-obscured-enhanced', ['2.4.12']],
|
|
60
|
+
['setsquare-focus-visible', ['2.4.7']],
|
|
61
|
+
['setsquare-focus-appearance', ['2.4.13']],
|
|
62
|
+
['setsquare-keyboard-trap', ['2.1.2']],
|
|
63
|
+
['setsquare-reflow', ['1.4.10']],
|
|
64
|
+
['setsquare-on-focus', ['3.2.1']],
|
|
65
|
+
['setsquare-on-input', ['3.2.2']],
|
|
66
|
+
['setsquare-key-shortcuts', ['2.1.4']],
|
|
67
|
+
['setsquare-meaningful-sequence', ['1.3.2']],
|
|
68
|
+
['setsquare-sensory-characteristics', ['1.3.3']],
|
|
69
|
+
['setsquare-headings-and-labels', ['2.4.6']],
|
|
70
|
+
['setsquare-section-headings', ['2.4.10']],
|
|
71
|
+
['setsquare-abbreviations', ['3.1.4']],
|
|
72
|
+
['setsquare-location', ['2.4.8']],
|
|
73
|
+
['setsquare-captions', ['1.2.1', '1.2.2', '1.2.3']],
|
|
74
|
+
['setsquare-captions-aa', ['1.2.4', '1.2.5']],
|
|
75
|
+
['setsquare-captions-aaa', ['1.2.6', '1.2.7', '1.2.8', '1.2.9']],
|
|
44
76
|
]);
|
|
45
77
|
//# sourceMappingURL=versions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/checks/versions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gCAAgC,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IACvD,MAAM,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"versions.js","sourceRoot":"","sources":["../../src/checks/versions.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,gCAAgC,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,EAAE,iCAAiC,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,iCAAiC,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAkB;IACvD,MAAM,QAAQ,GAAG;QACf,gCAAgC;QAChC,8BAA8B;QAC9B,iCAAiC;QACjC,8BAA8B;QAC9B,+BAA+B;QAC/B,iCAAiC;QACjC,4BAA4B;KAC7B,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK;QAAE,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACxE,IAAI,mBAAmB,EAAE;QAAE,QAAQ,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACtE,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAA2C,IAAI,GAAG,CAAC;IACtF,CAAC,wBAAwB,EAAE,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC,2BAA2B,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,2BAA2B,EAAE,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC,+BAA+B,EAAE,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,wBAAwB,EAAE,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC,0BAA0B,EAAE,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC,mCAAmC,EAAE,CAAC,QAAQ,CAAC,CAAC;IACjD,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,4BAA4B,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,kBAAkB,EAAE,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,oBAAoB,EAAE,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC,oBAAoB,EAAE,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,+BAA+B,EAAE,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,mCAAmC,EAAE,CAAC,OAAO,CAAC,CAAC;IAChD,CAAC,+BAA+B,EAAE,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC,4BAA4B,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC,oBAAoB,EAAE,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC,oBAAoB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC,uBAAuB,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC,wBAAwB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;CACjE,CAAC,CAAC"}
|
package/dist/contract.d.ts
CHANGED
|
@@ -165,6 +165,24 @@ export interface ScanResultRecord {
|
|
|
165
165
|
};
|
|
166
166
|
/** How the page was judged ready. Absent on explicit scans — no heuristic ran. */
|
|
167
167
|
settle?: AxeScan['settle'];
|
|
168
|
+
/**
|
|
169
|
+
* This record carries ONLY Setsquare's driven checks — no axe run happened.
|
|
170
|
+
*
|
|
171
|
+
* Emitted at teardown for a page that was already scanned mid-test and has
|
|
172
|
+
* not changed since. That skip is right for axe (nothing to find twice) and
|
|
173
|
+
* wrong for the driven checks, which never run mid-test at all: focusing,
|
|
174
|
+
* pressing Tab and resizing are unsafe while a test is still asserting, so
|
|
175
|
+
* they only ever happen at teardown. Without this record a page that settled
|
|
176
|
+
* during its test got no focus, keyboard, reflow or context evidence — which
|
|
177
|
+
* was quietly true of text-spacing and status messages for months, and
|
|
178
|
+
* meant the criteria those checks exist for stayed at "no automated result"
|
|
179
|
+
* on exactly the fast, static pages most suites are made of.
|
|
180
|
+
*
|
|
181
|
+
* `toScans` MERGES these into the scan sharing their `visitRef` rather than
|
|
182
|
+
* emitting a second row: two rows for one context would collide in dedupe
|
|
183
|
+
* and one kind of evidence would silently win.
|
|
184
|
+
*/
|
|
185
|
+
checksOnly?: true;
|
|
168
186
|
}
|
|
169
187
|
export type ScanRecord = ObservationRecord | ScanResultRecord;
|
|
170
188
|
/**
|
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"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"}
|
package/dist/covers.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Level 3: a test says which success criteria it covers.
|
|
3
|
+
*
|
|
4
|
+
* Auto-scan gets a grid from a suite nobody edited, and `setsquare.scan()`
|
|
5
|
+
* reaches the states auto-scan cannot. This reaches the CRITERIA neither can:
|
|
6
|
+
* the ones no automated engine evaluates at all.
|
|
7
|
+
*
|
|
8
|
+
* A suite that checks reflow at 320px, drives focus across a soft navigation
|
|
9
|
+
* or asserts that a focus ring is visible is already covering criteria axe
|
|
10
|
+
* has no rule for — and until this existed, the conformance report said "no
|
|
11
|
+
* automated result" for every one of them. Not because anyone decided that:
|
|
12
|
+
* a Playwright spec lands in the envelope as a pass/fail row with no
|
|
13
|
+
* criterion attached, so the projection could not see it. This is the join.
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* test('no horizontal overflow at 320px', async ({ page }) => {
|
|
17
|
+
* setsquare.covers('1.4.10');
|
|
18
|
+
* await page.setViewportSize({ width: 320, height: 800 });
|
|
19
|
+
* …
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* **What this is not.** We do not check that a test declaring `1.4.10` tests
|
|
24
|
+
* reflow, and we never will — there is no way to. So the report renders it as
|
|
25
|
+
* your assertion and not as our finding: its own cell state, worded "covered
|
|
26
|
+
* by your own test", never merged into the state that means every automated
|
|
27
|
+
* rule passed. The declaration is exactly as strong as the test behind it,
|
|
28
|
+
* and the report says whose claim it is.
|
|
29
|
+
*/
|
|
30
|
+
export declare function covers(...criteria: string[]): void;
|
|
31
|
+
/**
|
|
32
|
+
* The annotation type the declaration travels under.
|
|
33
|
+
*
|
|
34
|
+
* Defined beside both the writer above and the reader below so the string
|
|
35
|
+
* cannot drift between them — the same reasoning that keeps the sanitisation
|
|
36
|
+
* limits in one file shared by the schema and the SDK.
|
|
37
|
+
*/
|
|
38
|
+
export declare const COVERS_ANNOTATION = "setsquare-covers";
|
|
39
|
+
/**
|
|
40
|
+
* Read the declarations back off one attempt's annotations.
|
|
41
|
+
*
|
|
42
|
+
* Tolerates a missing `annotations` array rather than assuming it: the SDK's
|
|
43
|
+
* declared peer range reaches back to Playwright 1.45, and `TestResult.annotations`
|
|
44
|
+
* only arrived in 1.49. On an older runner the declarations are simply not
|
|
45
|
+
* there, which is the right degradation — the report loses a state it never had.
|
|
46
|
+
*
|
|
47
|
+
* Unknown ids are dropped here rather than thrown, because by this point the
|
|
48
|
+
* throw has already happened in the worker. Anything invalid reaching the
|
|
49
|
+
* reporter came from a hand-written annotation, and a reporter is the wrong
|
|
50
|
+
* place to fail a run that has finished.
|
|
51
|
+
*/
|
|
52
|
+
export declare function coversFromAnnotations(annotations: readonly {
|
|
53
|
+
type: string;
|
|
54
|
+
description?: string;
|
|
55
|
+
}[] | undefined): string[];
|
|
56
|
+
//# sourceMappingURL=covers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"covers.d.ts","sourceRoot":"","sources":["../src/covers.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,MAAM,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CA4DlD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAEpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,SAAS,GACzE,MAAM,EAAE,CAUV"}
|
package/dist/covers.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { test } from '@playwright/test';
|
|
2
|
+
import { MAX_CRITERIA_PER_TEST } from '@setsquare/schema/limits';
|
|
3
|
+
import { WCAG22_CRITERION_IDS, wcagCriterion } from '@setsquare/schema/wcag22';
|
|
4
|
+
import { WCAG22_SPEC_URL } from './links.js';
|
|
5
|
+
import { isDisabled } from './options.js';
|
|
6
|
+
/**
|
|
7
|
+
* Level 3: a test says which success criteria it covers.
|
|
8
|
+
*
|
|
9
|
+
* Auto-scan gets a grid from a suite nobody edited, and `setsquare.scan()`
|
|
10
|
+
* reaches the states auto-scan cannot. This reaches the CRITERIA neither can:
|
|
11
|
+
* the ones no automated engine evaluates at all.
|
|
12
|
+
*
|
|
13
|
+
* A suite that checks reflow at 320px, drives focus across a soft navigation
|
|
14
|
+
* or asserts that a focus ring is visible is already covering criteria axe
|
|
15
|
+
* has no rule for — and until this existed, the conformance report said "no
|
|
16
|
+
* automated result" for every one of them. Not because anyone decided that:
|
|
17
|
+
* a Playwright spec lands in the envelope as a pass/fail row with no
|
|
18
|
+
* criterion attached, so the projection could not see it. This is the join.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* test('no horizontal overflow at 320px', async ({ page }) => {
|
|
22
|
+
* setsquare.covers('1.4.10');
|
|
23
|
+
* await page.setViewportSize({ width: 320, height: 800 });
|
|
24
|
+
* …
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* **What this is not.** We do not check that a test declaring `1.4.10` tests
|
|
29
|
+
* reflow, and we never will — there is no way to. So the report renders it as
|
|
30
|
+
* your assertion and not as our finding: its own cell state, worded "covered
|
|
31
|
+
* by your own test", never merged into the state that means every automated
|
|
32
|
+
* rule passed. The declaration is exactly as strong as the test behind it,
|
|
33
|
+
* and the report says whose claim it is.
|
|
34
|
+
*/
|
|
35
|
+
export function covers(...criteria) {
|
|
36
|
+
if (criteria.length === 0) {
|
|
37
|
+
throw new TypeError('setsquare.covers() needs at least one WCAG success criterion id.');
|
|
38
|
+
}
|
|
39
|
+
const seen = new Set();
|
|
40
|
+
for (const criterion of criteria) {
|
|
41
|
+
/*
|
|
42
|
+
* An unknown id throws, and that is the one place this SDK deliberately
|
|
43
|
+
* does throw into a customer's test.
|
|
44
|
+
*
|
|
45
|
+
* Everywhere else the discipline is absolute: a scan that fails warns and
|
|
46
|
+
* returns "not scanned", because our evidence-gathering has no standing to
|
|
47
|
+
* overturn the suite's own verdict. This is a different thing. A typo here
|
|
48
|
+
* is not our code failing on their page — it is a claim that cannot be
|
|
49
|
+
* satisfied, and the only alternative to throwing is dropping it silently,
|
|
50
|
+
* which leaves someone believing they have coverage they do not have. That
|
|
51
|
+
* is the failure mode this whole feature exists to close, so it cannot be
|
|
52
|
+
* the failure mode of the feature itself.
|
|
53
|
+
*
|
|
54
|
+
* It can never fire on a correct declaration, so it can never turn a build
|
|
55
|
+
* red for an accessibility reason. WCAG 2.2 is a frozen Recommendation;
|
|
56
|
+
* the valid set will not change under anyone.
|
|
57
|
+
*/
|
|
58
|
+
const known = wcagCriterion(criterion);
|
|
59
|
+
if (!known || known.removedIn) {
|
|
60
|
+
throw new TypeError(`setsquare.covers("${criterion}") is not a WCAG 2.2 success criterion. ` +
|
|
61
|
+
`Ids look like "1.4.10" or "2.4.11"` +
|
|
62
|
+
(known?.removedIn
|
|
63
|
+
? `; ${criterion} was removed in WCAG ${known.removedIn}.`
|
|
64
|
+
: `. See ${WCAG22_SPEC_URL}`));
|
|
65
|
+
}
|
|
66
|
+
seen.add(criterion);
|
|
67
|
+
}
|
|
68
|
+
if (seen.size > MAX_CRITERIA_PER_TEST) {
|
|
69
|
+
throw new TypeError(`setsquare.covers() accepts at most ${MAX_CRITERIA_PER_TEST} criteria per test; ` +
|
|
70
|
+
`this test declared ${seen.size}. A test asserting twenty of the eighty-six ` +
|
|
71
|
+
`is claiming more than one test can plausibly check.`);
|
|
72
|
+
}
|
|
73
|
+
// Off means off, here as everywhere: the switch exists so somebody can answer
|
|
74
|
+
// "is it you or is it me" in one command. Validation still runs, because a
|
|
75
|
+
// typo is a typo whether or not evidence is being gathered.
|
|
76
|
+
if (isDisabled())
|
|
77
|
+
return;
|
|
78
|
+
const info = test.info();
|
|
79
|
+
for (const criterion of seen) {
|
|
80
|
+
/*
|
|
81
|
+
* Carried on Playwright's own annotation channel rather than an attachment.
|
|
82
|
+
* Annotations are already on `TestResult` where the reporter reads outcomes,
|
|
83
|
+
* they survive into Playwright's own HTML report — so the declaration is
|
|
84
|
+
* visible even to someone not using Setsquare's — and they cost nothing.
|
|
85
|
+
*/
|
|
86
|
+
info.annotations.push({ type: COVERS_ANNOTATION, description: criterion });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The annotation type the declaration travels under.
|
|
91
|
+
*
|
|
92
|
+
* Defined beside both the writer above and the reader below so the string
|
|
93
|
+
* cannot drift between them — the same reasoning that keeps the sanitisation
|
|
94
|
+
* limits in one file shared by the schema and the SDK.
|
|
95
|
+
*/
|
|
96
|
+
export const COVERS_ANNOTATION = 'setsquare-covers';
|
|
97
|
+
/**
|
|
98
|
+
* Read the declarations back off one attempt's annotations.
|
|
99
|
+
*
|
|
100
|
+
* Tolerates a missing `annotations` array rather than assuming it: the SDK's
|
|
101
|
+
* declared peer range reaches back to Playwright 1.45, and `TestResult.annotations`
|
|
102
|
+
* only arrived in 1.49. On an older runner the declarations are simply not
|
|
103
|
+
* there, which is the right degradation — the report loses a state it never had.
|
|
104
|
+
*
|
|
105
|
+
* Unknown ids are dropped here rather than thrown, because by this point the
|
|
106
|
+
* throw has already happened in the worker. Anything invalid reaching the
|
|
107
|
+
* reporter came from a hand-written annotation, and a reporter is the wrong
|
|
108
|
+
* place to fail a run that has finished.
|
|
109
|
+
*/
|
|
110
|
+
export function coversFromAnnotations(annotations) {
|
|
111
|
+
if (!annotations)
|
|
112
|
+
return [];
|
|
113
|
+
const valid = new Set(WCAG22_CRITERION_IDS);
|
|
114
|
+
const found = new Set();
|
|
115
|
+
for (const annotation of annotations) {
|
|
116
|
+
if (annotation.type !== COVERS_ANNOTATION)
|
|
117
|
+
continue;
|
|
118
|
+
const id = annotation.description?.trim();
|
|
119
|
+
if (id && valid.has(id))
|
|
120
|
+
found.add(id);
|
|
121
|
+
}
|
|
122
|
+
return [...found].sort(compareCriteria).slice(0, MAX_CRITERIA_PER_TEST);
|
|
123
|
+
}
|
|
124
|
+
/** Dotted ids sort numerically: 1.4.10 after 1.4.9, not after 1.4.1. */
|
|
125
|
+
function compareCriteria(a, b) {
|
|
126
|
+
const pa = a.split('.').map(Number);
|
|
127
|
+
const pb = b.split('.').map(Number);
|
|
128
|
+
for (let i = 0; i < Math.max(pa.length, pb.length); i += 1) {
|
|
129
|
+
const d = (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
130
|
+
if (d !== 0)
|
|
131
|
+
return d;
|
|
132
|
+
}
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=covers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"covers.js","sourceRoot":"","sources":["../src/covers.ts"],"names":[],"mappings":"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"}
|
package/dist/dedupe.d.ts
CHANGED
|
@@ -43,6 +43,29 @@ export interface DedupeInput {
|
|
|
43
43
|
* `/items/:id/edit`), so it collapses exactly what should collapse. The surface
|
|
44
44
|
* name then comes from whichever scan WINS, which is how an explicit label ends
|
|
45
45
|
* up on the row instead of competing with an inferred one for a place in the list.
|
|
46
|
+
*
|
|
47
|
+
* ## The viewport joined the tuple on 2026-09-12, and it had to
|
|
48
|
+
*
|
|
49
|
+
* It was missing, and the consequence was not theoretical: adding a tablet and
|
|
50
|
+
* a mobile Playwright project to this repository's own marketing site produced
|
|
51
|
+
* three scans of every surface and this function collapsed them to one. Ties
|
|
52
|
+
* break LAST-wins, so the last project configured won every bucket and the
|
|
53
|
+
* entire grid became mobile evidence — with the desktop and tablet scans
|
|
54
|
+
* silently dropped and the report showing no sign that anything had been lost.
|
|
55
|
+
* A run that looked at three widths reported one, and the two it discarded were
|
|
56
|
+
* the two the reader would have assumed were there.
|
|
57
|
+
*
|
|
58
|
+
* The argument is the one already made above for the theme: collapsing two
|
|
59
|
+
* themes reports a themed surface as clean when only one of its themes was
|
|
60
|
+
* looked at, and a viewport is the same shape of claim. A rule only ever sees
|
|
61
|
+
* the viewport it ran in — a navigation that collapses into a menu below a
|
|
62
|
+
* breakpoint is a different DOM, not a narrower one — so a scan at 1280 has no
|
|
63
|
+
* opinion whatsoever about the same page at 390.
|
|
64
|
+
*
|
|
65
|
+
* A single-viewport run is unaffected: every scan carries the same value, so
|
|
66
|
+
* every key is unchanged. It costs the common case nothing and it is the
|
|
67
|
+
* difference between viewport evidence existing and viewport evidence being
|
|
68
|
+
* thrown away.
|
|
46
69
|
*/
|
|
47
70
|
export declare function contextKey(scan: AxeScan): string;
|
|
48
71
|
/**
|
package/dist/dedupe.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dedupe.d.ts","sourceRoot":"","sources":["../src/dedupe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;CACf;AAED
|
|
1
|
+
{"version":3,"file":"dedupe.d.ts","sourceRoot":"","sources":["../src/dedupe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAShD;AA6BD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG;IAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA0BvF;AA8DD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,GACtE,GAAG,CAAC,MAAM,CAAC,CAQb"}
|