edgepress 2026.10.12 → 2026.10.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +12 -2
  2. package/config.yml +171 -171
  3. package/content/assets/edgepress/brand/sources/export-manifest.json +181 -181
  4. package/content/assets/edgepress-markdown-guide.svg +21 -21
  5. package/content/guides/markdown-media.md +38 -0
  6. package/content/guides/product-demos.md +30 -30
  7. package/content/pages/deployment/en.json +1 -1
  8. package/content/posts/2026-09-24-edgepress-release-2026-9-1/en.md +1 -1
  9. package/content/posts/2026-09-24-edgepress-release-2026-9-1/zh-cn.md +1 -1
  10. package/languages/base/en.json +98 -98
  11. package/languages/packs/zh-CN.json +98 -98
  12. package/package.json +90 -90
  13. package/src/assets.js +187 -186
  14. package/src/browser-audit.js +158 -158
  15. package/src/build.js +293 -291
  16. package/src/cli.js +364 -364
  17. package/src/content.js +233 -233
  18. package/src/data-saver.js +3 -3
  19. package/src/generators.js +414 -420
  20. package/src/i18n.js +86 -86
  21. package/src/markdown.js +195 -160
  22. package/src/page-check.js +1 -1
  23. package/src/plugin-api.js +77 -77
  24. package/src/report-visuals.js +642 -642
  25. package/src/revision-cards.js +30 -30
  26. package/src/rss.js +100 -0
  27. package/src/theme.js +4 -4
  28. package/src/video-metadata.js +36 -0
  29. package/static/edgepress/fonts/faces.css +2217 -2217
  30. package/static/edgepress/media-viewer.js +67 -10
  31. package/static/edgepress/project-demo.js +83 -83
  32. package/static/edgepress/search.js +84 -84
  33. package/tests/assets-runtime.test.mjs +26 -26
  34. package/tests/audit.test.mjs +142 -142
  35. package/tests/brand-regression.test.mjs +110 -110
  36. package/tests/document-package.test.mjs +2 -2
  37. package/tests/embed-syntax.test.mjs +68 -68
  38. package/tests/image-viewer.test.mjs +36 -36
  39. package/tests/markdown-media.test.mjs +119 -0
  40. package/tests/oembed-layout.test.mjs +6 -1
  41. package/tests/project-demo.test.mjs +73 -73
  42. package/tests/release-version.test.mjs +28 -0
  43. package/tests/rss.test.mjs +54 -0
  44. package/tests/video-metadata.test.mjs +28 -0
  45. package/tests/writing.test.mjs +83 -83
  46. package/themes/atelier/assets/style.css +340 -340
  47. package/themes/default/assets/style.css +371 -371
  48. package/themes/default/layouts/partials/head.html +1 -1
  49. package/themes/folio/assets/style.css +515 -515
  50. package/themes/folio/theme.json +5 -5
  51. package/themes/signal/assets/style.css +332 -332
  52. package/tools/README.md +10 -10
  53. package/tools/assets/generate-brand-assets.py +160 -160
  54. package/tools/assets/video-preview.mjs +15 -0
  55. package/tools/recordings/demo-workbench.mjs +53 -53
  56. package/tools/recordings/desktop-recording.mjs +70 -70
  57. package/tools/recordings/vm-desktop.mjs +59 -59
@@ -1,158 +1,158 @@
1
- export const deviceProfiles = [
2
- { name: 'desktop', width: 1440, height: 900, deviceScaleFactor: 1, mobile: false, touch: false },
3
- { name: 'phone', width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true },
4
- { name: 'tablet', width: 820, height: 1180, deviceScaleFactor: 2, mobile: true, touch: true }
5
- ];
6
-
7
- // CDP input targets only the isolated headless browser, never the user's desktop.
8
- async function key(send, name, modifiers = 0) {
9
- const code = name === 'Enter' ? 13 : 9;
10
- await send('Input.dispatchKeyEvent', { type: name === 'Enter' ? 'keyDown' : 'rawKeyDown',
11
- key: name, code: name, windowsVirtualKeyCode: code, nativeVirtualKeyCode: code, modifiers,
12
- ...(name === 'Enter' ? { text: '\r', unmodifiedText: '\r' } : {}) });
13
- await send('Input.dispatchKeyEvent', { type: 'keyUp', key: name, code: name,
14
- windowsVirtualKeyCode: code, nativeVirtualKeyCode: code, modifiers });
15
- }
16
-
17
- async function evaluate(send, fn) {
18
- const result = await send('Runtime.evaluate', { expression: '(' + fn.toString() + ')()', returnByValue: true, awaitPromise: true });
19
- if (result.exceptionDetails) throw new Error(result.exceptionDetails.text || 'Browser audit evaluation failed');
20
- return result.result.value;
21
- }
22
-
23
- export async function auditBrowser(send, profile) {
24
- const checks = [];
25
- const check = (group, name, passed, detail = '') => checks.push({ group, name, passed: Boolean(passed), ...(detail ? { detail } : {}) });
26
- const trace = [];
27
- const previous = await evaluate(send, () => {
28
- const manager = document.querySelector('[data-consent-ui]');
29
- const display = manager?.style.display;
30
- if (manager) manager.style.display = 'none';
31
- const candidates = [...document.querySelectorAll('a[href],button,input,select,textarea,summary,[tabindex]')];
32
- const visual = element => {
33
- const style = getComputedStyle(element);
34
- return [style.backgroundColor, style.borderColor, style.color, style.textDecorationLine].join('|');
35
- };
36
- window.__edgepressKeyboardAudit = { candidates, elements: [...document.querySelectorAll('*')], visual,
37
- before: new Map(candidates.map(element => [element, visual(element)])) };
38
- document.activeElement?.blur();
39
- return { display: display ?? '', href: location.href };
40
- });
41
- try {
42
- const measured = await evaluate(send, () => ({ width: innerWidth, density: devicePixelRatio, touch: navigator.maxTouchPoints,
43
- overflow: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth) > innerWidth + 1,
44
- mainCount: document.querySelectorAll('main,[role="main"]').length,
45
- h1Count: document.querySelectorAll('h1').length,
46
- heading: document.querySelector('h1')?.textContent.trim() || '',
47
- language: document.documentElement.lang,
48
- schemes: { dark: matchMedia('(prefers-color-scheme: dark)').matches }
49
- }));
50
- check('device', 'Viewport matches the emulated device', measured.width === profile.width, String(measured.width));
51
- check('device', 'Pixel density matches the emulated device', Math.abs(measured.density - profile.deviceScaleFactor) < .01);
52
- check('device', profile.touch ? 'Mobile touch emulation exposes five touch points' : 'Native desktop touch capability is recorded',
53
- profile.touch ? measured.touch === 5 : true, String(measured.touch));
54
- check('device', 'No page overflow at this device size', !measured.overflow);
55
- check('device', 'System color preference is emulated', measured.schemes.dark === (profile.colorScheme === 'dark'));
56
- check('structure', 'One main landmark', measured.mainCount === 1);
57
- check('structure', 'One page-level h1', measured.h1Count === 1);
58
- check('structure', 'Document language is declared', measured.language.trim());
59
-
60
- const { nodes } = await send('Accessibility.getFullAXTree');
61
- const exposed = nodes.filter(node => !node.ignored);
62
- const role = node => node.role?.value;
63
- const name = node => String(node.name?.value || '').trim();
64
- check('semantics', 'Main landmark is exposed to assistive technology', exposed.filter(node => role(node) === 'main').length === 1);
65
- check('semantics', 'Page heading has its accessible name and level', exposed.some(node => role(node) === 'heading' &&
66
- name(node) === measured.heading && node.properties?.some(property => property.name === 'level' && property.value.value === 1)));
67
- const navigation = exposed.filter(node => role(node) === 'navigation');
68
- check('semantics', 'Exposed navigation landmarks have names', navigation.every(node => name(node)));
69
- const namedRoles = new Set(['button', 'link', 'combobox', 'textbox', 'searchbox', 'checkbox', 'radio', 'switch', 'slider', 'spinbutton', 'image']);
70
- const unnamed = exposed.filter(node => namedRoles.has(role(node)) && !name(node));
71
- check('semantics', 'Exposed controls and meaningful images have names', unnamed.length === 0,
72
- unnamed.length ? unnamed.map(node => role(node)).join(', ') : '');
73
-
74
- await send('Emulation.setFocusEmulationEnabled', { enabled: true });
75
- const focus = () => evaluate(send, async () => {
76
- const element = document.activeElement;
77
- if (!element || element === document.body || element === document.documentElement) return null;
78
- // Native Tab can start a smooth scroll; observe its result without scrolling for it.
79
- await new Promise(resolve=>{
80
- const started=performance.now();
81
- const visible=()=>{const box=element.getBoundingClientRect();if((box.bottom>0&&box.top<innerHeight&&box.right>0&&box.left<innerWidth)||performance.now()-started>1500)return resolve();requestAnimationFrame(visible);};
82
- visible();
83
- });
84
- const { elements, before, visual } = window.__edgepressKeyboardAudit;
85
- const style = getComputedStyle(element), box = element.getBoundingClientRect();
86
- const transparent = value => value === 'transparent' || /rgba\([^)]*,\s*0\)$/.test(value);
87
- const outline = style.outlineStyle !== 'none' && parseFloat(style.outlineWidth) > 0 && !transparent(style.outlineColor);
88
- const indicator = outline || style.boxShadow !== 'none' || (before.has(element) && before.get(element) !== visual(element));
89
- const hidden = element.closest('[hidden],[inert],[aria-hidden="true"]');
90
- return { index: elements.indexOf(element), tag: element.tagName.toLowerCase(),
91
- name: (element.getAttribute('aria-label') || element.innerText || element.labels?.[0]?.textContent || '').trim().slice(0, 160),
92
- visible: !hidden && style.visibility === 'visible' && style.display !== 'none' && box.width > 0 && box.height > 0 &&
93
- box.bottom > 0 && box.top < innerHeight && box.right > 0 && box.left < innerWidth,
94
- indicator, skip: element.matches('a[href^="#"]') &&
95
- document.getElementById(element.getAttribute('href').slice(1))?.matches('main,[role="main"]') };
96
- });
97
- let reverseChecked = false;
98
- let unexpectedRepeat = false;
99
- for (let step = 0; step < 12; step += 1) {
100
- await key(send, 'Tab');
101
- const current = await focus();
102
- if (!current) break; // Normal wrap through browser chrome is not a focus trap.
103
- if (trace.length && current.index === trace[0].index) {
104
- // Mobile browser chrome may not appear as a focus stop. A natural wrap
105
- // is valid only after visiting all currently tabbable page controls.
106
- const expected = await evaluate(send, () => {
107
- const { candidates, elements } = window.__edgepressKeyboardAudit;
108
- const visible = candidates.filter(element => {
109
- const style = getComputedStyle(element), box = element.getBoundingClientRect();
110
- return element.tabIndex >= 0 && !element.matches(':disabled') && !element.closest('[hidden],[inert]') &&
111
- style.visibility === 'visible' && box.width > 0 && box.height > 0;
112
- });
113
- return visible.filter(element => {
114
- if (!element.matches('input[type="radio"]') || !element.name) return true;
115
- const group = visible.filter(other => other.matches('input[type="radio"]') && other.name === element.name && other.form === element.form);
116
- return element === (group.find(other => other.checked) || group[0]);
117
- }).map(element => elements.indexOf(element));
118
- });
119
- const visited = new Set(trace.map(item => item.index));
120
- const missing = expected.filter(index => !visited.has(index));
121
- check('keyboard', 'Native page wrap does not skip tabbable controls', missing.length === 0, missing.length ? String(missing.length) + ' unvisited controls' : '');
122
- break;
123
- }
124
- if (trace.some(item => item.index === current.index)) { unexpectedRepeat = true; break; }
125
- trace.push(current);
126
- check('keyboard', 'Tab step ' + (step + 1) + ' lands on visible content', current.visible, current.name);
127
- check('keyboard', 'Tab step ' + (step + 1) + ' has a visible focus indicator', current.indicator, current.name);
128
- if (step === 1) {
129
- await key(send, 'Tab', 8); // Shift modifier, scoped to CDP.
130
- const reverse = await focus();
131
- check('keyboard', 'Shift+Tab returns to the previous focus target', reverse?.index === trace[0].index);
132
- reverseChecked = true;
133
- await key(send, 'Tab');
134
- }
135
- }
136
- check('keyboard', 'Forward and backward keyboard navigation are available', trace.length >= 2 && reverseChecked);
137
- check('keyboard', 'No unexpected focus cycle during the sampled Tab sequence', !unexpectedRepeat);
138
- check('keyboard', 'First Tab reaches the skip-to-main link', trace[0]?.skip);
139
- const hasSkip = await evaluate(send, () => {
140
- const first = window.__edgepressKeyboardAudit.candidates.find(element => element.matches('a[href^="#"]') &&
141
- document.getElementById(element.getAttribute('href').slice(1))?.matches('main,[role="main"]'));
142
- first?.focus();
143
- return Boolean(first && document.activeElement === first);
144
- });
145
- if (hasSkip) await key(send, 'Enter');
146
- const skipReached = hasSkip && await evaluate(send, () => {
147
- if (!location.hash) return false;
148
- const target = document.getElementById(decodeURIComponent(location.hash.slice(1)));
149
- return Boolean(target?.matches('main,[role="main"]') && target.getBoundingClientRect().top < innerHeight);
150
- });
151
- check('keyboard', 'Enter on the skip link reaches the main landmark', skipReached);
152
- return { checks, trace, status: checks.every(item => item.passed) ? 'pass' : 'fail' };
153
- } finally {
154
- await send('Runtime.evaluate', { expression: '(() => { const manager = document.querySelector("[data-consent-ui]"); if (manager) manager.style.display = ' +
155
- JSON.stringify(previous.display) + '; history.replaceState(history.state, "", ' + JSON.stringify(previous.href) +
156
- '); delete window.__edgepressKeyboardAudit; })()' });
157
- }
158
- }
1
+ export const deviceProfiles = [
2
+ { name: 'desktop', width: 1440, height: 900, deviceScaleFactor: 1, mobile: false, touch: false },
3
+ { name: 'phone', width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true },
4
+ { name: 'tablet', width: 820, height: 1180, deviceScaleFactor: 2, mobile: true, touch: true }
5
+ ];
6
+
7
+ // CDP input targets only the isolated headless browser, never the user's desktop.
8
+ async function key(send, name, modifiers = 0) {
9
+ const code = name === 'Enter' ? 13 : 9;
10
+ await send('Input.dispatchKeyEvent', { type: name === 'Enter' ? 'keyDown' : 'rawKeyDown',
11
+ key: name, code: name, windowsVirtualKeyCode: code, nativeVirtualKeyCode: code, modifiers,
12
+ ...(name === 'Enter' ? { text: '\r', unmodifiedText: '\r' } : {}) });
13
+ await send('Input.dispatchKeyEvent', { type: 'keyUp', key: name, code: name,
14
+ windowsVirtualKeyCode: code, nativeVirtualKeyCode: code, modifiers });
15
+ }
16
+
17
+ async function evaluate(send, fn) {
18
+ const result = await send('Runtime.evaluate', { expression: '(' + fn.toString() + ')()', returnByValue: true, awaitPromise: true });
19
+ if (result.exceptionDetails) throw new Error(result.exceptionDetails.text || 'Browser audit evaluation failed');
20
+ return result.result.value;
21
+ }
22
+
23
+ export async function auditBrowser(send, profile) {
24
+ const checks = [];
25
+ const check = (group, name, passed, detail = '') => checks.push({ group, name, passed: Boolean(passed), ...(detail ? { detail } : {}) });
26
+ const trace = [];
27
+ const previous = await evaluate(send, () => {
28
+ const manager = document.querySelector('[data-consent-ui]');
29
+ const display = manager?.style.display;
30
+ if (manager) manager.style.display = 'none';
31
+ const candidates = [...document.querySelectorAll('a[href],button,input,select,textarea,summary,[tabindex]')];
32
+ const visual = element => {
33
+ const style = getComputedStyle(element);
34
+ return [style.backgroundColor, style.borderColor, style.color, style.textDecorationLine].join('|');
35
+ };
36
+ window.__edgepressKeyboardAudit = { candidates, elements: [...document.querySelectorAll('*')], visual,
37
+ before: new Map(candidates.map(element => [element, visual(element)])) };
38
+ document.activeElement?.blur();
39
+ return { display: display ?? '', href: location.href };
40
+ });
41
+ try {
42
+ const measured = await evaluate(send, () => ({ width: innerWidth, density: devicePixelRatio, touch: navigator.maxTouchPoints,
43
+ overflow: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth) > innerWidth + 1,
44
+ mainCount: document.querySelectorAll('main,[role="main"]').length,
45
+ h1Count: document.querySelectorAll('h1').length,
46
+ heading: document.querySelector('h1')?.textContent.trim() || '',
47
+ language: document.documentElement.lang,
48
+ schemes: { dark: matchMedia('(prefers-color-scheme: dark)').matches }
49
+ }));
50
+ check('device', 'Viewport matches the emulated device', measured.width === profile.width, String(measured.width));
51
+ check('device', 'Pixel density matches the emulated device', Math.abs(measured.density - profile.deviceScaleFactor) < .01);
52
+ check('device', profile.touch ? 'Mobile touch emulation exposes five touch points' : 'Native desktop touch capability is recorded',
53
+ profile.touch ? measured.touch === 5 : true, String(measured.touch));
54
+ check('device', 'No page overflow at this device size', !measured.overflow);
55
+ check('device', 'System color preference is emulated', measured.schemes.dark === (profile.colorScheme === 'dark'));
56
+ check('structure', 'One main landmark', measured.mainCount === 1);
57
+ check('structure', 'One page-level h1', measured.h1Count === 1);
58
+ check('structure', 'Document language is declared', measured.language.trim());
59
+
60
+ const { nodes } = await send('Accessibility.getFullAXTree');
61
+ const exposed = nodes.filter(node => !node.ignored);
62
+ const role = node => node.role?.value;
63
+ const name = node => String(node.name?.value || '').trim();
64
+ check('semantics', 'Main landmark is exposed to assistive technology', exposed.filter(node => role(node) === 'main').length === 1);
65
+ check('semantics', 'Page heading has its accessible name and level', exposed.some(node => role(node) === 'heading' &&
66
+ name(node) === measured.heading && node.properties?.some(property => property.name === 'level' && property.value.value === 1)));
67
+ const navigation = exposed.filter(node => role(node) === 'navigation');
68
+ check('semantics', 'Exposed navigation landmarks have names', navigation.every(node => name(node)));
69
+ const namedRoles = new Set(['button', 'link', 'combobox', 'textbox', 'searchbox', 'checkbox', 'radio', 'switch', 'slider', 'spinbutton', 'image']);
70
+ const unnamed = exposed.filter(node => namedRoles.has(role(node)) && !name(node));
71
+ check('semantics', 'Exposed controls and meaningful images have names', unnamed.length === 0,
72
+ unnamed.length ? unnamed.map(node => role(node)).join(', ') : '');
73
+
74
+ await send('Emulation.setFocusEmulationEnabled', { enabled: true });
75
+ const focus = () => evaluate(send, async () => {
76
+ const element = document.activeElement;
77
+ if (!element || element === document.body || element === document.documentElement) return null;
78
+ // Native Tab can start a smooth scroll; observe its result without scrolling for it.
79
+ await new Promise(resolve=>{
80
+ const started=performance.now();
81
+ const visible=()=>{const box=element.getBoundingClientRect();if((box.bottom>0&&box.top<innerHeight&&box.right>0&&box.left<innerWidth)||performance.now()-started>1500)return resolve();requestAnimationFrame(visible);};
82
+ visible();
83
+ });
84
+ const { elements, before, visual } = window.__edgepressKeyboardAudit;
85
+ const style = getComputedStyle(element), box = element.getBoundingClientRect();
86
+ const transparent = value => value === 'transparent' || /rgba\([^)]*,\s*0\)$/.test(value);
87
+ const outline = style.outlineStyle !== 'none' && parseFloat(style.outlineWidth) > 0 && !transparent(style.outlineColor);
88
+ const indicator = outline || style.boxShadow !== 'none' || (before.has(element) && before.get(element) !== visual(element));
89
+ const hidden = element.closest('[hidden],[inert],[aria-hidden="true"]');
90
+ return { index: elements.indexOf(element), tag: element.tagName.toLowerCase(),
91
+ name: (element.getAttribute('aria-label') || element.innerText || element.labels?.[0]?.textContent || '').trim().slice(0, 160),
92
+ visible: !hidden && style.visibility === 'visible' && style.display !== 'none' && box.width > 0 && box.height > 0 &&
93
+ box.bottom > 0 && box.top < innerHeight && box.right > 0 && box.left < innerWidth,
94
+ indicator, skip: element.matches('a[href^="#"]') &&
95
+ document.getElementById(element.getAttribute('href').slice(1))?.matches('main,[role="main"]') };
96
+ });
97
+ let reverseChecked = false;
98
+ let unexpectedRepeat = false;
99
+ for (let step = 0; step < 12; step += 1) {
100
+ await key(send, 'Tab');
101
+ const current = await focus();
102
+ if (!current) break; // Normal wrap through browser chrome is not a focus trap.
103
+ if (trace.length && current.index === trace[0].index) {
104
+ // Mobile browser chrome may not appear as a focus stop. A natural wrap
105
+ // is valid only after visiting all currently tabbable page controls.
106
+ const expected = await evaluate(send, () => {
107
+ const { candidates, elements } = window.__edgepressKeyboardAudit;
108
+ const visible = candidates.filter(element => {
109
+ const style = getComputedStyle(element), box = element.getBoundingClientRect();
110
+ return element.tabIndex >= 0 && !element.matches(':disabled') && !element.closest('[hidden],[inert]') &&
111
+ style.visibility === 'visible' && box.width > 0 && box.height > 0;
112
+ });
113
+ return visible.filter(element => {
114
+ if (!element.matches('input[type="radio"]') || !element.name) return true;
115
+ const group = visible.filter(other => other.matches('input[type="radio"]') && other.name === element.name && other.form === element.form);
116
+ return element === (group.find(other => other.checked) || group[0]);
117
+ }).map(element => elements.indexOf(element));
118
+ });
119
+ const visited = new Set(trace.map(item => item.index));
120
+ const missing = expected.filter(index => !visited.has(index));
121
+ check('keyboard', 'Native page wrap does not skip tabbable controls', missing.length === 0, missing.length ? String(missing.length) + ' unvisited controls' : '');
122
+ break;
123
+ }
124
+ if (trace.some(item => item.index === current.index)) { unexpectedRepeat = true; break; }
125
+ trace.push(current);
126
+ check('keyboard', 'Tab step ' + (step + 1) + ' lands on visible content', current.visible, current.name);
127
+ check('keyboard', 'Tab step ' + (step + 1) + ' has a visible focus indicator', current.indicator, current.name);
128
+ if (step === 1) {
129
+ await key(send, 'Tab', 8); // Shift modifier, scoped to CDP.
130
+ const reverse = await focus();
131
+ check('keyboard', 'Shift+Tab returns to the previous focus target', reverse?.index === trace[0].index);
132
+ reverseChecked = true;
133
+ await key(send, 'Tab');
134
+ }
135
+ }
136
+ check('keyboard', 'Forward and backward keyboard navigation are available', trace.length >= 2 && reverseChecked);
137
+ check('keyboard', 'No unexpected focus cycle during the sampled Tab sequence', !unexpectedRepeat);
138
+ check('keyboard', 'First Tab reaches the skip-to-main link', trace[0]?.skip);
139
+ const hasSkip = await evaluate(send, () => {
140
+ const first = window.__edgepressKeyboardAudit.candidates.find(element => element.matches('a[href^="#"]') &&
141
+ document.getElementById(element.getAttribute('href').slice(1))?.matches('main,[role="main"]'));
142
+ first?.focus();
143
+ return Boolean(first && document.activeElement === first);
144
+ });
145
+ if (hasSkip) await key(send, 'Enter');
146
+ const skipReached = hasSkip && await evaluate(send, () => {
147
+ if (!location.hash) return false;
148
+ const target = document.getElementById(decodeURIComponent(location.hash.slice(1)));
149
+ return Boolean(target?.matches('main,[role="main"]') && target.getBoundingClientRect().top < innerHeight);
150
+ });
151
+ check('keyboard', 'Enter on the skip link reaches the main landmark', skipReached);
152
+ return { checks, trace, status: checks.every(item => item.passed) ? 'pass' : 'fail' };
153
+ } finally {
154
+ await send('Runtime.evaluate', { expression: '(() => { const manager = document.querySelector("[data-consent-ui]"); if (manager) manager.style.display = ' +
155
+ JSON.stringify(previous.display) + '; history.replaceState(history.state, "", ' + JSON.stringify(previous.href) +
156
+ '); delete window.__edgepressKeyboardAudit; })()' });
157
+ }
158
+ }