accessify-widget 0.2.1 → 0.2.3
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/accessify.min.js +1 -1
- package/dist/accessify.min.js.map +1 -1
- package/dist/accessify.mjs +1 -1
- package/dist/{index-qmiN2JAz.js → index-CsJDqdBW.js} +1864 -1083
- package/dist/index-CsJDqdBW.js.map +1 -0
- package/dist/{keyboard-nav-DH4qBThF.js → keyboard-nav-CkAYxUc1.js} +2 -2
- package/dist/{keyboard-nav-DH4qBThF.js.map → keyboard-nav-CkAYxUc1.js.map} +1 -1
- package/dist/{page-structure-DTBqkrYs.js → page-structure-yWkBKmwo.js} +2 -2
- package/dist/{page-structure-DTBqkrYs.js.map → page-structure-yWkBKmwo.js.map} +1 -1
- package/dist/text-simplify-C9gzE3t0.js +632 -0
- package/dist/text-simplify-C9gzE3t0.js.map +1 -0
- package/dist/{tts-02b9iV0h.js → tts-CjszLRnb.js} +58 -12
- package/dist/tts-CjszLRnb.js.map +1 -0
- package/dist/widget.js +1 -1
- package/dist/widget.js.map +1 -1
- package/package.json +10 -10
- package/LICENSE +0 -21
- package/dist/alt-text-CgzNGvdT.js +0 -567
- package/dist/alt-text-CgzNGvdT.js.map +0 -1
- package/dist/auto-scan-pg-09o7A.js +0 -885
- package/dist/auto-scan-pg-09o7A.js.map +0 -1
- package/dist/focus-highlight-CjERyyUF.js +0 -93
- package/dist/focus-highlight-CjERyyUF.js.map +0 -1
- package/dist/index-qmiN2JAz.js.map +0 -1
- package/dist/text-simplify-CELklw5A.js +0 -223
- package/dist/text-simplify-CELklw5A.js.map +0 -1
- package/dist/tts-02b9iV0h.js.map +0 -1
|
@@ -1,885 +0,0 @@
|
|
|
1
|
-
let axe = null;
|
|
2
|
-
function createAutoScanModule(lang = "de") {
|
|
3
|
-
let enabled = false;
|
|
4
|
-
let styleEl = null;
|
|
5
|
-
let panelEl = null;
|
|
6
|
-
let lastResult = null;
|
|
7
|
-
let isScanning = false;
|
|
8
|
-
const STYLE_ID = "accessify-scan-styles";
|
|
9
|
-
const PANEL_CLASS = "accessify-scan-panel";
|
|
10
|
-
function getStyles() {
|
|
11
|
-
return `
|
|
12
|
-
.${PANEL_CLASS} {
|
|
13
|
-
position: fixed;
|
|
14
|
-
top: 50%;
|
|
15
|
-
left: 50%;
|
|
16
|
-
transform: translate(-50%, -50%);
|
|
17
|
-
z-index: 2147483646;
|
|
18
|
-
width: 560px;
|
|
19
|
-
max-width: 92vw;
|
|
20
|
-
max-height: 80vh;
|
|
21
|
-
background: #1a1a2e;
|
|
22
|
-
color: #f0f0f0;
|
|
23
|
-
border-radius: 14px;
|
|
24
|
-
box-shadow: 0 12px 48px rgba(0,0,0,0.5);
|
|
25
|
-
font-family: system-ui, -apple-system, sans-serif;
|
|
26
|
-
font-size: 14px;
|
|
27
|
-
line-height: 1.5;
|
|
28
|
-
display: flex;
|
|
29
|
-
flex-direction: column;
|
|
30
|
-
animation: accessify-scan-fade-in 0.25s ease;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.${PANEL_CLASS}-backdrop {
|
|
34
|
-
position: fixed;
|
|
35
|
-
inset: 0;
|
|
36
|
-
z-index: 2147483645;
|
|
37
|
-
background: rgba(0,0,0,0.4);
|
|
38
|
-
animation: accessify-scan-fade-in 0.2s ease;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.${PANEL_CLASS}-header {
|
|
42
|
-
display: flex;
|
|
43
|
-
justify-content: space-between;
|
|
44
|
-
align-items: center;
|
|
45
|
-
padding: 16px 20px;
|
|
46
|
-
border-bottom: 1px solid rgba(255,255,255,0.08);
|
|
47
|
-
flex-shrink: 0;
|
|
48
|
-
}
|
|
49
|
-
.${PANEL_CLASS}-header h2 {
|
|
50
|
-
margin: 0;
|
|
51
|
-
font-size: 16px;
|
|
52
|
-
font-weight: 700;
|
|
53
|
-
color: #f0f0f0;
|
|
54
|
-
}
|
|
55
|
-
.${PANEL_CLASS}-close {
|
|
56
|
-
display: inline-flex;
|
|
57
|
-
align-items: center;
|
|
58
|
-
justify-content: center;
|
|
59
|
-
width: 28px;
|
|
60
|
-
height: 28px;
|
|
61
|
-
padding: 0;
|
|
62
|
-
border: none;
|
|
63
|
-
border-radius: 6px;
|
|
64
|
-
background: transparent;
|
|
65
|
-
color: #888;
|
|
66
|
-
font-size: 18px;
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
}
|
|
69
|
-
.${PANEL_CLASS}-close:hover { color: #fff; background: rgba(255,255,255,0.1); }
|
|
70
|
-
.${PANEL_CLASS}-close:focus-visible { outline: 2px solid #4ea8de; outline-offset: 1px; }
|
|
71
|
-
|
|
72
|
-
.${PANEL_CLASS}-body {
|
|
73
|
-
flex: 1;
|
|
74
|
-
overflow-y: auto;
|
|
75
|
-
padding: 16px 20px;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.${PANEL_CLASS}-score {
|
|
79
|
-
display: flex;
|
|
80
|
-
align-items: center;
|
|
81
|
-
gap: 12px;
|
|
82
|
-
padding: 14px 16px;
|
|
83
|
-
background: rgba(255,255,255,0.04);
|
|
84
|
-
border-radius: 10px;
|
|
85
|
-
margin-bottom: 16px;
|
|
86
|
-
}
|
|
87
|
-
.${PANEL_CLASS}-score-ring {
|
|
88
|
-
position: relative;
|
|
89
|
-
width: 56px;
|
|
90
|
-
height: 56px;
|
|
91
|
-
flex-shrink: 0;
|
|
92
|
-
}
|
|
93
|
-
.${PANEL_CLASS}-score-ring svg {
|
|
94
|
-
transform: rotate(-90deg);
|
|
95
|
-
}
|
|
96
|
-
.${PANEL_CLASS}-score-ring .score-text {
|
|
97
|
-
position: absolute;
|
|
98
|
-
inset: 0;
|
|
99
|
-
display: flex;
|
|
100
|
-
align-items: center;
|
|
101
|
-
justify-content: center;
|
|
102
|
-
font-size: 16px;
|
|
103
|
-
font-weight: 700;
|
|
104
|
-
}
|
|
105
|
-
.${PANEL_CLASS}-score-details {
|
|
106
|
-
font-size: 13px;
|
|
107
|
-
color: #aaa;
|
|
108
|
-
}
|
|
109
|
-
.${PANEL_CLASS}-score-details strong {
|
|
110
|
-
color: #f0f0f0;
|
|
111
|
-
font-weight: 600;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.${PANEL_CLASS}-group {
|
|
115
|
-
margin-bottom: 14px;
|
|
116
|
-
}
|
|
117
|
-
.${PANEL_CLASS}-group-header {
|
|
118
|
-
display: flex;
|
|
119
|
-
align-items: center;
|
|
120
|
-
gap: 8px;
|
|
121
|
-
padding: 8px 12px;
|
|
122
|
-
border-radius: 8px;
|
|
123
|
-
font-size: 13px;
|
|
124
|
-
font-weight: 600;
|
|
125
|
-
margin-bottom: 6px;
|
|
126
|
-
cursor: pointer;
|
|
127
|
-
user-select: none;
|
|
128
|
-
}
|
|
129
|
-
.${PANEL_CLASS}-group-header:hover {
|
|
130
|
-
opacity: 0.9;
|
|
131
|
-
}
|
|
132
|
-
.${PANEL_CLASS}-group-header .count {
|
|
133
|
-
display: inline-flex;
|
|
134
|
-
align-items: center;
|
|
135
|
-
justify-content: center;
|
|
136
|
-
min-width: 20px;
|
|
137
|
-
height: 20px;
|
|
138
|
-
padding: 0 6px;
|
|
139
|
-
border-radius: 10px;
|
|
140
|
-
font-size: 11px;
|
|
141
|
-
font-weight: 700;
|
|
142
|
-
}
|
|
143
|
-
.${PANEL_CLASS}-group[data-impact="critical"] .${PANEL_CLASS}-group-header {
|
|
144
|
-
background: rgba(220,53,69,0.12);
|
|
145
|
-
color: #f0a0a8;
|
|
146
|
-
}
|
|
147
|
-
.${PANEL_CLASS}-group[data-impact="critical"] .count {
|
|
148
|
-
background: rgba(220,53,69,0.3);
|
|
149
|
-
}
|
|
150
|
-
.${PANEL_CLASS}-group[data-impact="serious"] .${PANEL_CLASS}-group-header {
|
|
151
|
-
background: rgba(255,152,0,0.12);
|
|
152
|
-
color: #ffcc80;
|
|
153
|
-
}
|
|
154
|
-
.${PANEL_CLASS}-group[data-impact="serious"] .count {
|
|
155
|
-
background: rgba(255,152,0,0.3);
|
|
156
|
-
}
|
|
157
|
-
.${PANEL_CLASS}-group[data-impact="moderate"] .${PANEL_CLASS}-group-header {
|
|
158
|
-
background: rgba(255,193,7,0.12);
|
|
159
|
-
color: #ffd54f;
|
|
160
|
-
}
|
|
161
|
-
.${PANEL_CLASS}-group[data-impact="moderate"] .count {
|
|
162
|
-
background: rgba(255,193,7,0.3);
|
|
163
|
-
}
|
|
164
|
-
.${PANEL_CLASS}-group[data-impact="minor"] .${PANEL_CLASS}-group-header {
|
|
165
|
-
background: rgba(78,168,222,0.12);
|
|
166
|
-
color: #81d4fa;
|
|
167
|
-
}
|
|
168
|
-
.${PANEL_CLASS}-group[data-impact="minor"] .count {
|
|
169
|
-
background: rgba(78,168,222,0.3);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
.${PANEL_CLASS}-violation {
|
|
173
|
-
padding: 10px 14px;
|
|
174
|
-
margin-bottom: 4px;
|
|
175
|
-
background: rgba(255,255,255,0.03);
|
|
176
|
-
border-radius: 6px;
|
|
177
|
-
border-left: 3px solid rgba(255,255,255,0.1);
|
|
178
|
-
}
|
|
179
|
-
.${PANEL_CLASS}-violation-desc {
|
|
180
|
-
font-size: 13px;
|
|
181
|
-
margin-bottom: 4px;
|
|
182
|
-
}
|
|
183
|
-
.${PANEL_CLASS}-violation-meta {
|
|
184
|
-
display: flex;
|
|
185
|
-
flex-wrap: wrap;
|
|
186
|
-
gap: 8px;
|
|
187
|
-
font-size: 11px;
|
|
188
|
-
color: #888;
|
|
189
|
-
}
|
|
190
|
-
.${PANEL_CLASS}-violation-meta a {
|
|
191
|
-
color: #4ea8de;
|
|
192
|
-
text-decoration: none;
|
|
193
|
-
}
|
|
194
|
-
.${PANEL_CLASS}-violation-meta a:hover { text-decoration: underline; }
|
|
195
|
-
.${PANEL_CLASS}-violation-meta a:focus-visible {
|
|
196
|
-
outline: 2px solid #4ea8de;
|
|
197
|
-
outline-offset: 1px;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
.${PANEL_CLASS}-footer {
|
|
201
|
-
display: flex;
|
|
202
|
-
justify-content: space-between;
|
|
203
|
-
align-items: center;
|
|
204
|
-
padding: 12px 20px;
|
|
205
|
-
border-top: 1px solid rgba(255,255,255,0.08);
|
|
206
|
-
flex-shrink: 0;
|
|
207
|
-
gap: 8px;
|
|
208
|
-
flex-wrap: wrap;
|
|
209
|
-
}
|
|
210
|
-
.${PANEL_CLASS}-footer button {
|
|
211
|
-
padding: 7px 16px;
|
|
212
|
-
border: 1px solid rgba(255,255,255,0.15);
|
|
213
|
-
border-radius: 7px;
|
|
214
|
-
background: rgba(255,255,255,0.08);
|
|
215
|
-
color: #f0f0f0;
|
|
216
|
-
font-size: 12px;
|
|
217
|
-
font-weight: 500;
|
|
218
|
-
cursor: pointer;
|
|
219
|
-
transition: background 0.15s ease;
|
|
220
|
-
white-space: nowrap;
|
|
221
|
-
}
|
|
222
|
-
.${PANEL_CLASS}-footer button:hover { background: rgba(255,255,255,0.18); }
|
|
223
|
-
.${PANEL_CLASS}-footer button:focus-visible { outline: 2px solid #4ea8de; outline-offset: 1px; }
|
|
224
|
-
.${PANEL_CLASS}-footer button.primary {
|
|
225
|
-
background: rgba(78,168,222,0.2);
|
|
226
|
-
color: #4ea8de;
|
|
227
|
-
border-color: rgba(78,168,222,0.3);
|
|
228
|
-
}
|
|
229
|
-
.${PANEL_CLASS}-footer button.primary:hover { background: rgba(78,168,222,0.35); }
|
|
230
|
-
.${PANEL_CLASS}-footer button.fix {
|
|
231
|
-
background: rgba(42,157,143,0.2);
|
|
232
|
-
color: #2a9d8f;
|
|
233
|
-
border-color: rgba(42,157,143,0.3);
|
|
234
|
-
}
|
|
235
|
-
.${PANEL_CLASS}-footer button.fix:hover { background: rgba(42,157,143,0.35); }
|
|
236
|
-
|
|
237
|
-
.${PANEL_CLASS}-spinner {
|
|
238
|
-
display: flex;
|
|
239
|
-
flex-direction: column;
|
|
240
|
-
align-items: center;
|
|
241
|
-
gap: 14px;
|
|
242
|
-
padding: 40px 20px;
|
|
243
|
-
color: #aaa;
|
|
244
|
-
font-size: 14px;
|
|
245
|
-
}
|
|
246
|
-
.${PANEL_CLASS}-spinner::before {
|
|
247
|
-
content: '';
|
|
248
|
-
width: 28px;
|
|
249
|
-
height: 28px;
|
|
250
|
-
border: 3px solid rgba(78,168,222,0.2);
|
|
251
|
-
border-top-color: #4ea8de;
|
|
252
|
-
border-radius: 50%;
|
|
253
|
-
animation: accessify-scan-spin 0.7s linear infinite;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
.${PANEL_CLASS}-empty {
|
|
257
|
-
text-align: center;
|
|
258
|
-
padding: 32px 20px;
|
|
259
|
-
color: #2a9d8f;
|
|
260
|
-
font-size: 15px;
|
|
261
|
-
font-weight: 600;
|
|
262
|
-
}
|
|
263
|
-
.${PANEL_CLASS}-empty .checkmark {
|
|
264
|
-
display: block;
|
|
265
|
-
font-size: 40px;
|
|
266
|
-
margin-bottom: 8px;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
.${PANEL_CLASS}-fix-report {
|
|
270
|
-
padding: 12px 14px;
|
|
271
|
-
margin: 12px 0;
|
|
272
|
-
background: rgba(42,157,143,0.1);
|
|
273
|
-
border: 1px solid rgba(42,157,143,0.25);
|
|
274
|
-
border-radius: 8px;
|
|
275
|
-
font-size: 13px;
|
|
276
|
-
color: #81cec5;
|
|
277
|
-
}
|
|
278
|
-
.${PANEL_CLASS}-fix-report strong { color: #2a9d8f; }
|
|
279
|
-
|
|
280
|
-
@keyframes accessify-scan-fade-in {
|
|
281
|
-
from { opacity: 0; }
|
|
282
|
-
to { opacity: 1; }
|
|
283
|
-
}
|
|
284
|
-
@keyframes accessify-scan-spin {
|
|
285
|
-
to { transform: rotate(360deg); }
|
|
286
|
-
}
|
|
287
|
-
`;
|
|
288
|
-
}
|
|
289
|
-
function injectStyles() {
|
|
290
|
-
if (document.getElementById(STYLE_ID)) return;
|
|
291
|
-
styleEl = document.createElement("style");
|
|
292
|
-
styleEl.id = STYLE_ID;
|
|
293
|
-
styleEl.textContent = getStyles();
|
|
294
|
-
document.head.appendChild(styleEl);
|
|
295
|
-
}
|
|
296
|
-
function removeStyles() {
|
|
297
|
-
styleEl?.remove();
|
|
298
|
-
styleEl = null;
|
|
299
|
-
document.getElementById(STYLE_ID)?.remove();
|
|
300
|
-
}
|
|
301
|
-
async function loadAxe() {
|
|
302
|
-
if (axe) return;
|
|
303
|
-
if (window.axe) {
|
|
304
|
-
axe = window.axe;
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
return new Promise((resolve, reject) => {
|
|
308
|
-
const script = document.createElement("script");
|
|
309
|
-
script.src = "https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.10.2/axe.min.js";
|
|
310
|
-
script.crossOrigin = "anonymous";
|
|
311
|
-
script.onload = () => {
|
|
312
|
-
axe = window.axe;
|
|
313
|
-
if (!axe) {
|
|
314
|
-
reject(new Error("axe-core loaded but not available on window"));
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
resolve();
|
|
318
|
-
};
|
|
319
|
-
script.onerror = () => reject(new Error("Failed to load axe-core"));
|
|
320
|
-
document.head.appendChild(script);
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
async function runScan() {
|
|
324
|
-
await loadAxe();
|
|
325
|
-
const results = await axe.run(document, {
|
|
326
|
-
exclude: ["#accessify-root"],
|
|
327
|
-
runOnly: {
|
|
328
|
-
type: "tag",
|
|
329
|
-
values: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "best-practice"]
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
const violations = results.violations.map((v) => ({
|
|
333
|
-
id: v.id,
|
|
334
|
-
impact: v.impact || "minor",
|
|
335
|
-
description: v.description,
|
|
336
|
-
helpUrl: v.helpUrl,
|
|
337
|
-
nodes: v.nodes.length,
|
|
338
|
-
wcagCriteria: extractWcagTags(v.tags)
|
|
339
|
-
}));
|
|
340
|
-
const scanResult = {
|
|
341
|
-
violations,
|
|
342
|
-
passes: results.passes.length,
|
|
343
|
-
count: results.passes.length + results.violations.length,
|
|
344
|
-
timestamp: Date.now()
|
|
345
|
-
};
|
|
346
|
-
lastResult = scanResult;
|
|
347
|
-
return scanResult;
|
|
348
|
-
}
|
|
349
|
-
function extractWcagTags(tags) {
|
|
350
|
-
return tags.filter(
|
|
351
|
-
(t) => /^wcag\d/.test(t) || t.startsWith("best-practice")
|
|
352
|
-
);
|
|
353
|
-
}
|
|
354
|
-
function showPanel() {
|
|
355
|
-
removePanel();
|
|
356
|
-
injectStyles();
|
|
357
|
-
const backdrop = document.createElement("div");
|
|
358
|
-
backdrop.className = `${PANEL_CLASS}-backdrop`;
|
|
359
|
-
backdrop.addEventListener("click", () => removePanel());
|
|
360
|
-
document.body.appendChild(backdrop);
|
|
361
|
-
const panel = document.createElement("div");
|
|
362
|
-
panel.className = PANEL_CLASS;
|
|
363
|
-
panel.setAttribute("role", "dialog");
|
|
364
|
-
panel.setAttribute("aria-label", lang.startsWith("de") ? "WCAG-Prüfergebnisse" : "WCAG Scan Results");
|
|
365
|
-
panel.setAttribute("aria-modal", "true");
|
|
366
|
-
const header = document.createElement("div");
|
|
367
|
-
header.className = `${PANEL_CLASS}-header`;
|
|
368
|
-
const title = document.createElement("h2");
|
|
369
|
-
title.textContent = lang.startsWith("de") ? "WCAG-Prüfung" : "WCAG Accessibility Scan";
|
|
370
|
-
const closeBtn = document.createElement("button");
|
|
371
|
-
closeBtn.className = `${PANEL_CLASS}-close`;
|
|
372
|
-
closeBtn.setAttribute("aria-label", lang.startsWith("de") ? "Schließen" : "Close");
|
|
373
|
-
closeBtn.innerHTML = "×";
|
|
374
|
-
closeBtn.addEventListener("click", () => removePanel());
|
|
375
|
-
header.appendChild(title);
|
|
376
|
-
header.appendChild(closeBtn);
|
|
377
|
-
panel.appendChild(header);
|
|
378
|
-
const body = document.createElement("div");
|
|
379
|
-
body.className = `${PANEL_CLASS}-body`;
|
|
380
|
-
panel.appendChild(body);
|
|
381
|
-
document.body.appendChild(panel);
|
|
382
|
-
panelEl = panel;
|
|
383
|
-
showLoading(body);
|
|
384
|
-
performScan(body, panel);
|
|
385
|
-
const handleEsc = (e) => {
|
|
386
|
-
if (e.key === "Escape") {
|
|
387
|
-
removePanel();
|
|
388
|
-
document.removeEventListener("keydown", handleEsc);
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
document.addEventListener("keydown", handleEsc);
|
|
392
|
-
}
|
|
393
|
-
function showLoading(body) {
|
|
394
|
-
body.innerHTML = "";
|
|
395
|
-
const spinner = document.createElement("div");
|
|
396
|
-
spinner.className = `${PANEL_CLASS}-spinner`;
|
|
397
|
-
const text = document.createElement("span");
|
|
398
|
-
text.textContent = lang.startsWith("de") ? "Seite wird auf Barrierefreiheit geprüft..." : "Scanning page for accessibility issues...";
|
|
399
|
-
spinner.appendChild(text);
|
|
400
|
-
const hint = document.createElement("span");
|
|
401
|
-
hint.style.fontSize = "12px";
|
|
402
|
-
hint.style.color = "#666";
|
|
403
|
-
hint.textContent = lang.startsWith("de") ? "axe-core wird geladen und analysiert die Seite" : "Loading axe-core and analyzing the page";
|
|
404
|
-
spinner.appendChild(hint);
|
|
405
|
-
body.appendChild(spinner);
|
|
406
|
-
}
|
|
407
|
-
async function performScan(body, panel) {
|
|
408
|
-
isScanning = true;
|
|
409
|
-
try {
|
|
410
|
-
const result = await runScan();
|
|
411
|
-
isScanning = false;
|
|
412
|
-
renderResults(body, panel, result);
|
|
413
|
-
} catch (err) {
|
|
414
|
-
isScanning = false;
|
|
415
|
-
body.innerHTML = "";
|
|
416
|
-
const errorEl = document.createElement("div");
|
|
417
|
-
errorEl.style.cssText = "padding: 20px; text-align: center; color: #f0a0a8;";
|
|
418
|
-
errorEl.textContent = lang.startsWith("de") ? `Fehler beim Scannen: ${err.message}` : `Scan error: ${err.message}`;
|
|
419
|
-
body.appendChild(errorEl);
|
|
420
|
-
addFooter(panel, null);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
function renderResults(body, panel, result) {
|
|
424
|
-
body.innerHTML = "";
|
|
425
|
-
if (result.violations.length === 0) {
|
|
426
|
-
const empty = document.createElement("div");
|
|
427
|
-
empty.className = `${PANEL_CLASS}-empty`;
|
|
428
|
-
empty.innerHTML = `
|
|
429
|
-
<span class="checkmark" aria-hidden="true">✓</span>
|
|
430
|
-
${lang.startsWith("de") ? "Keine Probleme gefunden!" : "No issues found!"}
|
|
431
|
-
`;
|
|
432
|
-
body.appendChild(empty);
|
|
433
|
-
renderScore(body, result);
|
|
434
|
-
addFooter(panel, result);
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
renderScore(body, result);
|
|
438
|
-
const groups = {
|
|
439
|
-
critical: [],
|
|
440
|
-
serious: [],
|
|
441
|
-
moderate: [],
|
|
442
|
-
minor: []
|
|
443
|
-
};
|
|
444
|
-
result.violations.forEach((v) => {
|
|
445
|
-
const impact = v.impact || "minor";
|
|
446
|
-
if (groups[impact]) {
|
|
447
|
-
groups[impact].push(v);
|
|
448
|
-
} else {
|
|
449
|
-
groups.minor.push(v);
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
const impactLabels = {
|
|
453
|
-
critical: { de: "Kritisch", en: "Critical" },
|
|
454
|
-
serious: { de: "Schwerwiegend", en: "Serious" },
|
|
455
|
-
moderate: { de: "Mittel", en: "Moderate" },
|
|
456
|
-
minor: { de: "Gering", en: "Minor" }
|
|
457
|
-
};
|
|
458
|
-
for (const [impact, violations] of Object.entries(groups)) {
|
|
459
|
-
if (violations.length === 0) continue;
|
|
460
|
-
const group = document.createElement("div");
|
|
461
|
-
group.className = `${PANEL_CLASS}-group`;
|
|
462
|
-
group.setAttribute("data-impact", impact);
|
|
463
|
-
const groupHeader = document.createElement("div");
|
|
464
|
-
groupHeader.className = `${PANEL_CLASS}-group-header`;
|
|
465
|
-
const chevron = document.createElement("span");
|
|
466
|
-
chevron.textContent = "▼";
|
|
467
|
-
chevron.style.fontSize = "10px";
|
|
468
|
-
chevron.style.transition = "transform 0.15s ease";
|
|
469
|
-
const label = document.createElement("span");
|
|
470
|
-
const resolvedLang = lang.startsWith("de") ? "de" : "en";
|
|
471
|
-
label.textContent = impactLabels[impact]?.[resolvedLang] || impact;
|
|
472
|
-
const count = document.createElement("span");
|
|
473
|
-
count.className = "count";
|
|
474
|
-
count.textContent = String(violations.length);
|
|
475
|
-
groupHeader.appendChild(chevron);
|
|
476
|
-
groupHeader.appendChild(label);
|
|
477
|
-
groupHeader.appendChild(count);
|
|
478
|
-
const groupBody = document.createElement("div");
|
|
479
|
-
let collapsed = false;
|
|
480
|
-
groupHeader.addEventListener("click", () => {
|
|
481
|
-
collapsed = !collapsed;
|
|
482
|
-
groupBody.style.display = collapsed ? "none" : "block";
|
|
483
|
-
chevron.style.transform = collapsed ? "rotate(-90deg)" : "rotate(0)";
|
|
484
|
-
});
|
|
485
|
-
violations.forEach((v) => {
|
|
486
|
-
const item = document.createElement("div");
|
|
487
|
-
item.className = `${PANEL_CLASS}-violation`;
|
|
488
|
-
const desc = document.createElement("div");
|
|
489
|
-
desc.className = `${PANEL_CLASS}-violation-desc`;
|
|
490
|
-
desc.textContent = v.description;
|
|
491
|
-
const meta = document.createElement("div");
|
|
492
|
-
meta.className = `${PANEL_CLASS}-violation-meta`;
|
|
493
|
-
const nodeCount = document.createElement("span");
|
|
494
|
-
nodeCount.textContent = lang.startsWith("de") ? `${v.nodes} ${v.nodes === 1 ? "Element" : "Elemente"}` : `${v.nodes} ${v.nodes === 1 ? "element" : "elements"}`;
|
|
495
|
-
meta.appendChild(nodeCount);
|
|
496
|
-
if (v.wcagCriteria.length > 0) {
|
|
497
|
-
const criteria = document.createElement("span");
|
|
498
|
-
criteria.textContent = v.wcagCriteria.join(", ");
|
|
499
|
-
meta.appendChild(criteria);
|
|
500
|
-
}
|
|
501
|
-
const learnMore = document.createElement("a");
|
|
502
|
-
learnMore.href = v.helpUrl;
|
|
503
|
-
learnMore.target = "_blank";
|
|
504
|
-
learnMore.rel = "noopener noreferrer";
|
|
505
|
-
learnMore.textContent = lang.startsWith("de") ? "Mehr erfahren" : "Learn more";
|
|
506
|
-
meta.appendChild(learnMore);
|
|
507
|
-
item.appendChild(desc);
|
|
508
|
-
item.appendChild(meta);
|
|
509
|
-
groupBody.appendChild(item);
|
|
510
|
-
});
|
|
511
|
-
group.appendChild(groupHeader);
|
|
512
|
-
group.appendChild(groupBody);
|
|
513
|
-
body.appendChild(group);
|
|
514
|
-
}
|
|
515
|
-
addFooter(panel, result);
|
|
516
|
-
}
|
|
517
|
-
function renderScore(body, result) {
|
|
518
|
-
const scoreBlock = document.createElement("div");
|
|
519
|
-
scoreBlock.className = `${PANEL_CLASS}-score`;
|
|
520
|
-
const total = result.count;
|
|
521
|
-
const passed = result.passes;
|
|
522
|
-
const percentage = total > 0 ? Math.round(passed / total * 100) : 100;
|
|
523
|
-
let color = "#2a9d8f";
|
|
524
|
-
if (percentage < 60) color = "#e63946";
|
|
525
|
-
else if (percentage < 80) color = "#f77f00";
|
|
526
|
-
else if (percentage < 95) color = "#ffd166";
|
|
527
|
-
const ring = document.createElement("div");
|
|
528
|
-
ring.className = `${PANEL_CLASS}-score-ring`;
|
|
529
|
-
const circumference = 2 * Math.PI * 22;
|
|
530
|
-
const offset = circumference - percentage / 100 * circumference;
|
|
531
|
-
ring.innerHTML = `
|
|
532
|
-
<svg width="56" height="56" viewBox="0 0 56 56" aria-hidden="true">
|
|
533
|
-
<circle cx="28" cy="28" r="22" fill="none" stroke="rgba(255,255,255,0.08)" stroke-width="4" />
|
|
534
|
-
<circle cx="28" cy="28" r="22" fill="none" stroke="${color}" stroke-width="4"
|
|
535
|
-
stroke-dasharray="${circumference}" stroke-dashoffset="${offset}" stroke-linecap="round" />
|
|
536
|
-
</svg>
|
|
537
|
-
<div class="score-text" style="color:${color}">${percentage}%</div>
|
|
538
|
-
`;
|
|
539
|
-
const details = document.createElement("div");
|
|
540
|
-
details.className = `${PANEL_CLASS}-score-details`;
|
|
541
|
-
details.innerHTML = lang.startsWith("de") ? `<strong>${passed}</strong> von <strong>${total}</strong> Prüfungen bestanden<br>${result.violations.length} ${result.violations.length === 1 ? "Problem" : "Probleme"} gefunden` : `<strong>${passed}</strong> of <strong>${total}</strong> checks passed<br>${result.violations.length} ${result.violations.length === 1 ? "issue" : "issues"} found`;
|
|
542
|
-
scoreBlock.appendChild(ring);
|
|
543
|
-
scoreBlock.appendChild(details);
|
|
544
|
-
body.insertBefore(scoreBlock, body.firstChild);
|
|
545
|
-
}
|
|
546
|
-
function addFooter(panel, result) {
|
|
547
|
-
panel.querySelector(`.${PANEL_CLASS}-footer`)?.remove();
|
|
548
|
-
const footer = document.createElement("div");
|
|
549
|
-
footer.className = `${PANEL_CLASS}-footer`;
|
|
550
|
-
const leftGroup = document.createElement("div");
|
|
551
|
-
leftGroup.style.display = "flex";
|
|
552
|
-
leftGroup.style.gap = "6px";
|
|
553
|
-
const rescanBtn = document.createElement("button");
|
|
554
|
-
rescanBtn.classList.add("primary");
|
|
555
|
-
rescanBtn.textContent = lang.startsWith("de") ? "Erneut prüfen" : "Rescan";
|
|
556
|
-
rescanBtn.addEventListener("click", () => {
|
|
557
|
-
const body = panel.querySelector(`.${PANEL_CLASS}-body`);
|
|
558
|
-
if (body) {
|
|
559
|
-
showLoading(body);
|
|
560
|
-
performScan(body, panel);
|
|
561
|
-
}
|
|
562
|
-
});
|
|
563
|
-
leftGroup.appendChild(rescanBtn);
|
|
564
|
-
if (result && result.violations.length > 0) {
|
|
565
|
-
const fixableCount = countFixableIssues(result.violations);
|
|
566
|
-
if (fixableCount > 0) {
|
|
567
|
-
const fixBtn = document.createElement("button");
|
|
568
|
-
fixBtn.classList.add("fix");
|
|
569
|
-
fixBtn.textContent = lang.startsWith("de") ? `${fixableCount} automatisch beheben` : `Auto-fix ${fixableCount} ${fixableCount === 1 ? "issue" : "issues"}`;
|
|
570
|
-
fixBtn.addEventListener("click", () => {
|
|
571
|
-
const report = applyAutoFixes(result.violations);
|
|
572
|
-
const body = panel.querySelector(`.${PANEL_CLASS}-body`);
|
|
573
|
-
if (body) {
|
|
574
|
-
showFixReport(body, report);
|
|
575
|
-
}
|
|
576
|
-
});
|
|
577
|
-
leftGroup.appendChild(fixBtn);
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
const rightGroup = document.createElement("div");
|
|
581
|
-
rightGroup.style.display = "flex";
|
|
582
|
-
rightGroup.style.gap = "6px";
|
|
583
|
-
if (result) {
|
|
584
|
-
const exportBtn = document.createElement("button");
|
|
585
|
-
exportBtn.textContent = lang.startsWith("de") ? "JSON exportieren" : "Export JSON";
|
|
586
|
-
exportBtn.addEventListener("click", () => {
|
|
587
|
-
exportResultsAsJson(result);
|
|
588
|
-
});
|
|
589
|
-
rightGroup.appendChild(exportBtn);
|
|
590
|
-
}
|
|
591
|
-
const closeBtn = document.createElement("button");
|
|
592
|
-
closeBtn.textContent = lang.startsWith("de") ? "Schließen" : "Close";
|
|
593
|
-
closeBtn.addEventListener("click", () => removePanel());
|
|
594
|
-
rightGroup.appendChild(closeBtn);
|
|
595
|
-
footer.appendChild(leftGroup);
|
|
596
|
-
footer.appendChild(rightGroup);
|
|
597
|
-
panel.appendChild(footer);
|
|
598
|
-
}
|
|
599
|
-
const FIXABLE_RULES = {
|
|
600
|
-
"html-has-lang": {
|
|
601
|
-
label: "Added lang attribute to <html>",
|
|
602
|
-
labelDe: "lang-Attribut zu <html> hinzugefügt",
|
|
603
|
-
fix: () => fixMissingLang()
|
|
604
|
-
},
|
|
605
|
-
"document-title": {
|
|
606
|
-
label: "Added page title",
|
|
607
|
-
labelDe: "Seitentitel hinzugefügt",
|
|
608
|
-
fix: () => fixMissingTitle()
|
|
609
|
-
},
|
|
610
|
-
bypass: {
|
|
611
|
-
label: "Added skip-to-content link",
|
|
612
|
-
labelDe: "Überspringen-Link hinzugefügt",
|
|
613
|
-
fix: () => fixMissingSkipLink()
|
|
614
|
-
},
|
|
615
|
-
"link-name": {
|
|
616
|
-
label: "Added aria-labels to empty links",
|
|
617
|
-
labelDe: "aria-label zu leeren Links hinzugefügt",
|
|
618
|
-
fix: () => fixEmptyLinks()
|
|
619
|
-
},
|
|
620
|
-
"button-name": {
|
|
621
|
-
label: "Added aria-labels to empty buttons",
|
|
622
|
-
labelDe: "aria-label zu leeren Buttons hinzugefügt",
|
|
623
|
-
fix: () => fixEmptyButtons()
|
|
624
|
-
},
|
|
625
|
-
"focus-order-semantics": {
|
|
626
|
-
label: "Added focus indicators CSS",
|
|
627
|
-
labelDe: "CSS-Fokus-Indikatoren hinzugefügt",
|
|
628
|
-
fix: () => fixMissingFocusIndicators()
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
function countFixableIssues(violations) {
|
|
632
|
-
return violations.filter((v) => FIXABLE_RULES[v.id]).length;
|
|
633
|
-
}
|
|
634
|
-
function applyAutoFixes(violations) {
|
|
635
|
-
const report = { fixed: [], skipped: [] };
|
|
636
|
-
const resolvedLang = lang.startsWith("de") ? "de" : "en";
|
|
637
|
-
violations.forEach((v) => {
|
|
638
|
-
const rule = FIXABLE_RULES[v.id];
|
|
639
|
-
if (!rule) return;
|
|
640
|
-
try {
|
|
641
|
-
const success = rule.fix();
|
|
642
|
-
if (success) {
|
|
643
|
-
report.fixed.push(resolvedLang === "de" ? rule.labelDe : rule.label);
|
|
644
|
-
} else {
|
|
645
|
-
report.skipped.push(
|
|
646
|
-
resolvedLang === "de" ? rule.labelDe : rule.label
|
|
647
|
-
);
|
|
648
|
-
}
|
|
649
|
-
} catch {
|
|
650
|
-
report.skipped.push(resolvedLang === "de" ? rule.labelDe : rule.label);
|
|
651
|
-
}
|
|
652
|
-
});
|
|
653
|
-
return report;
|
|
654
|
-
}
|
|
655
|
-
function showFixReport(body, report) {
|
|
656
|
-
body.querySelectorAll(`.${PANEL_CLASS}-fix-report`).forEach((el2) => el2.remove());
|
|
657
|
-
const el = document.createElement("div");
|
|
658
|
-
el.className = `${PANEL_CLASS}-fix-report`;
|
|
659
|
-
el.setAttribute("role", "status");
|
|
660
|
-
el.setAttribute("aria-live", "polite");
|
|
661
|
-
let html = "";
|
|
662
|
-
if (report.fixed.length > 0) {
|
|
663
|
-
html += `<strong>${lang.startsWith("de") ? "Behoben:" : "Fixed:"}</strong><br>`;
|
|
664
|
-
html += report.fixed.map((f) => `✓ ${f}`).join("<br>");
|
|
665
|
-
}
|
|
666
|
-
if (report.skipped.length > 0) {
|
|
667
|
-
if (html) html += "<br><br>";
|
|
668
|
-
html += `<strong>${lang.startsWith("de") ? "Übersprungen:" : "Skipped:"}</strong><br>`;
|
|
669
|
-
html += report.skipped.map((s) => `• ${s}`).join("<br>");
|
|
670
|
-
}
|
|
671
|
-
if (report.fixed.length === 0 && report.skipped.length === 0) {
|
|
672
|
-
html = lang.startsWith("de") ? "Keine automatisch behebbaren Probleme gefunden." : "No auto-fixable issues found.";
|
|
673
|
-
}
|
|
674
|
-
el.innerHTML = html;
|
|
675
|
-
body.insertBefore(el, body.firstChild);
|
|
676
|
-
}
|
|
677
|
-
function fixMissingLang() {
|
|
678
|
-
const html = document.documentElement;
|
|
679
|
-
if (html.hasAttribute("lang") && html.lang.trim() !== "") return false;
|
|
680
|
-
const detectedLang = detectContentLanguage();
|
|
681
|
-
html.setAttribute("lang", detectedLang);
|
|
682
|
-
return true;
|
|
683
|
-
}
|
|
684
|
-
function detectContentLanguage() {
|
|
685
|
-
const metaLang = document.querySelector(
|
|
686
|
-
'meta[http-equiv="content-language"]'
|
|
687
|
-
);
|
|
688
|
-
if (metaLang?.content) return metaLang.content;
|
|
689
|
-
const ogLocale = document.querySelector(
|
|
690
|
-
'meta[property="og:locale"]'
|
|
691
|
-
);
|
|
692
|
-
if (ogLocale?.content) return ogLocale.content.replace("_", "-");
|
|
693
|
-
const bodyText = (document.body.innerText || "").toLowerCase().slice(0, 2e3);
|
|
694
|
-
const germanIndicators = ["und", "der", "die", "das", "ist", "nicht", "ein", "eine", "mit", "auf"];
|
|
695
|
-
const englishIndicators = ["the", "and", "is", "are", "for", "not", "with", "this", "that", "was"];
|
|
696
|
-
let germanScore = 0;
|
|
697
|
-
let englishScore = 0;
|
|
698
|
-
germanIndicators.forEach((w) => {
|
|
699
|
-
const regex = new RegExp(`\\b${w}\\b`, "gi");
|
|
700
|
-
germanScore += (bodyText.match(regex) || []).length;
|
|
701
|
-
});
|
|
702
|
-
englishIndicators.forEach((w) => {
|
|
703
|
-
const regex = new RegExp(`\\b${w}\\b`, "gi");
|
|
704
|
-
englishScore += (bodyText.match(regex) || []).length;
|
|
705
|
-
});
|
|
706
|
-
return germanScore > englishScore ? "de" : "en";
|
|
707
|
-
}
|
|
708
|
-
function fixMissingTitle() {
|
|
709
|
-
let titleEl = document.querySelector("title");
|
|
710
|
-
if (titleEl && titleEl.textContent?.trim()) return false;
|
|
711
|
-
const h1 = document.querySelector("h1");
|
|
712
|
-
const titleText = h1?.textContent?.trim() || window.location.hostname || "Untitled Page";
|
|
713
|
-
if (!titleEl) {
|
|
714
|
-
titleEl = document.createElement("title");
|
|
715
|
-
document.head.appendChild(titleEl);
|
|
716
|
-
}
|
|
717
|
-
titleEl.textContent = titleText;
|
|
718
|
-
return true;
|
|
719
|
-
}
|
|
720
|
-
function fixMissingSkipLink() {
|
|
721
|
-
const existing = document.querySelector(
|
|
722
|
-
'a[href="#main"], a[href="#content"], a[href="#main-content"], .skip-link, .skip-to-content'
|
|
723
|
-
);
|
|
724
|
-
if (existing) return false;
|
|
725
|
-
const main = document.querySelector("main") || document.getElementById("main") || document.getElementById("content") || document.getElementById("main-content");
|
|
726
|
-
if (!main) {
|
|
727
|
-
const firstH = document.querySelector("h1, h2");
|
|
728
|
-
if (firstH && !firstH.id) {
|
|
729
|
-
firstH.id = "accessify-main-content";
|
|
730
|
-
}
|
|
731
|
-
}
|
|
732
|
-
const targetId = main?.id || (main ? main.id = "accessify-main-content" : "accessify-main-content");
|
|
733
|
-
const skipLink = document.createElement("a");
|
|
734
|
-
skipLink.href = `#${targetId}`;
|
|
735
|
-
skipLink.textContent = lang.startsWith("de") ? "Zum Inhalt springen" : "Skip to content";
|
|
736
|
-
skipLink.className = "accessify-skip-link";
|
|
737
|
-
Object.assign(skipLink.style, {
|
|
738
|
-
position: "absolute",
|
|
739
|
-
top: "-100px",
|
|
740
|
-
left: "0",
|
|
741
|
-
padding: "8px 16px",
|
|
742
|
-
background: "#1a1a2e",
|
|
743
|
-
color: "#4ea8de",
|
|
744
|
-
fontSize: "14px",
|
|
745
|
-
fontWeight: "600",
|
|
746
|
-
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
747
|
-
textDecoration: "none",
|
|
748
|
-
zIndex: "2147483647",
|
|
749
|
-
borderRadius: "0 0 8px 0",
|
|
750
|
-
transition: "top 0.2s ease"
|
|
751
|
-
});
|
|
752
|
-
skipLink.addEventListener("focus", () => {
|
|
753
|
-
skipLink.style.top = "0";
|
|
754
|
-
});
|
|
755
|
-
skipLink.addEventListener("blur", () => {
|
|
756
|
-
skipLink.style.top = "-100px";
|
|
757
|
-
});
|
|
758
|
-
document.body.insertBefore(skipLink, document.body.firstChild);
|
|
759
|
-
return true;
|
|
760
|
-
}
|
|
761
|
-
function fixEmptyLinks() {
|
|
762
|
-
const emptyLinks = document.querySelectorAll(
|
|
763
|
-
"a:not([aria-label]):not([aria-labelledby])"
|
|
764
|
-
);
|
|
765
|
-
let fixedCount = 0;
|
|
766
|
-
emptyLinks.forEach((link) => {
|
|
767
|
-
const text = (link.textContent || "").trim();
|
|
768
|
-
const img = link.querySelector("img[alt]");
|
|
769
|
-
if (text || img && img.alt) return;
|
|
770
|
-
const title = link.title?.trim();
|
|
771
|
-
const href = link.href;
|
|
772
|
-
const imgInLink = link.querySelector("img");
|
|
773
|
-
const ariaLabel = title || (imgInLink ? imgInLink.alt : "") || (href ? new URL(href, window.location.href).hostname : "") || "Link";
|
|
774
|
-
{
|
|
775
|
-
link.setAttribute("aria-label", ariaLabel);
|
|
776
|
-
fixedCount++;
|
|
777
|
-
}
|
|
778
|
-
});
|
|
779
|
-
return fixedCount > 0;
|
|
780
|
-
}
|
|
781
|
-
function fixEmptyButtons() {
|
|
782
|
-
const emptyButtons = document.querySelectorAll(
|
|
783
|
-
"button:not([aria-label]):not([aria-labelledby])"
|
|
784
|
-
);
|
|
785
|
-
let fixedCount = 0;
|
|
786
|
-
emptyButtons.forEach((btn) => {
|
|
787
|
-
const text = (btn.textContent || "").trim();
|
|
788
|
-
if (text) return;
|
|
789
|
-
const title = btn.title?.trim();
|
|
790
|
-
const img = btn.querySelector("img[alt]");
|
|
791
|
-
const svg = btn.querySelector("svg");
|
|
792
|
-
const ariaLabel = title || (img ? img.alt : "") || (svg ? deriveNameFromSvg(svg) : "") || deriveNameFromClass(btn.className) || "Button";
|
|
793
|
-
btn.setAttribute("aria-label", ariaLabel);
|
|
794
|
-
fixedCount++;
|
|
795
|
-
});
|
|
796
|
-
return fixedCount > 0;
|
|
797
|
-
}
|
|
798
|
-
function fixMissingFocusIndicators() {
|
|
799
|
-
const FOCUS_STYLE_ID = "accessify-focus-fix";
|
|
800
|
-
if (document.getElementById(FOCUS_STYLE_ID)) return false;
|
|
801
|
-
const style = document.createElement("style");
|
|
802
|
-
style.id = FOCUS_STYLE_ID;
|
|
803
|
-
style.textContent = `
|
|
804
|
-
*:focus-visible {
|
|
805
|
-
outline: 3px solid #4ea8de !important;
|
|
806
|
-
outline-offset: 2px !important;
|
|
807
|
-
}
|
|
808
|
-
`;
|
|
809
|
-
document.head.appendChild(style);
|
|
810
|
-
return true;
|
|
811
|
-
}
|
|
812
|
-
function deriveNameFromSvg(svg) {
|
|
813
|
-
const svgTitle = svg.querySelector("title");
|
|
814
|
-
if (svgTitle?.textContent?.trim()) return svgTitle.textContent.trim();
|
|
815
|
-
const ariaLabel = svg.getAttribute("aria-label");
|
|
816
|
-
if (ariaLabel?.trim()) return ariaLabel.trim();
|
|
817
|
-
return "";
|
|
818
|
-
}
|
|
819
|
-
function deriveNameFromClass(className) {
|
|
820
|
-
if (!className) return "";
|
|
821
|
-
const words = className.replace(/[_-]/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").split(/\s+/).filter(
|
|
822
|
-
(w) => w.length > 2 && !["btn", "button", "icon", "svg", "img", "cls", "mod"].includes(
|
|
823
|
-
w.toLowerCase()
|
|
824
|
-
)
|
|
825
|
-
);
|
|
826
|
-
if (words.length > 0) {
|
|
827
|
-
return words.slice(0, 3).join(" ");
|
|
828
|
-
}
|
|
829
|
-
return "";
|
|
830
|
-
}
|
|
831
|
-
function exportResultsAsJson(result) {
|
|
832
|
-
const exportData = {
|
|
833
|
-
...result,
|
|
834
|
-
url: window.location.href,
|
|
835
|
-
generatedBy: "Accessify WCAG Scanner",
|
|
836
|
-
exportedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
837
|
-
};
|
|
838
|
-
const json = JSON.stringify(exportData, null, 2);
|
|
839
|
-
const blob = new Blob([json], { type: "application/json" });
|
|
840
|
-
const url = URL.createObjectURL(blob);
|
|
841
|
-
const a = document.createElement("a");
|
|
842
|
-
a.href = url;
|
|
843
|
-
a.download = `accessify-scan-${Date.now()}.json`;
|
|
844
|
-
a.click();
|
|
845
|
-
URL.revokeObjectURL(url);
|
|
846
|
-
}
|
|
847
|
-
function removePanel() {
|
|
848
|
-
panelEl?.remove();
|
|
849
|
-
panelEl = null;
|
|
850
|
-
document.querySelector(`.${PANEL_CLASS}-backdrop`)?.remove();
|
|
851
|
-
}
|
|
852
|
-
function activate() {
|
|
853
|
-
if (enabled) return;
|
|
854
|
-
enabled = true;
|
|
855
|
-
showPanel();
|
|
856
|
-
}
|
|
857
|
-
function deactivate() {
|
|
858
|
-
enabled = false;
|
|
859
|
-
removePanel();
|
|
860
|
-
removeStyles();
|
|
861
|
-
}
|
|
862
|
-
return {
|
|
863
|
-
id: "auto-scan",
|
|
864
|
-
name: () => lang.startsWith("de") ? "WCAG-Prüfung" : "WCAG Scan",
|
|
865
|
-
description: lang.startsWith("de") ? "Seite auf Barrierefreiheit prüfen" : "Scan page for accessibility issues",
|
|
866
|
-
icon: "scan",
|
|
867
|
-
category: "ai",
|
|
868
|
-
activate,
|
|
869
|
-
deactivate,
|
|
870
|
-
getState: () => ({
|
|
871
|
-
id: "auto-scan",
|
|
872
|
-
enabled,
|
|
873
|
-
value: lastResult ? {
|
|
874
|
-
violations: lastResult.violations.length,
|
|
875
|
-
passes: lastResult.passes,
|
|
876
|
-
total: lastResult.count,
|
|
877
|
-
timestamp: lastResult.timestamp
|
|
878
|
-
} : null
|
|
879
|
-
})
|
|
880
|
-
};
|
|
881
|
-
}
|
|
882
|
-
export {
|
|
883
|
-
createAutoScanModule as default
|
|
884
|
-
};
|
|
885
|
-
//# sourceMappingURL=auto-scan-pg-09o7A.js.map
|