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.
@@ -0,0 +1,632 @@
1
+ function createTextSimplifyModule(aiService, lang = "de") {
2
+ let enabled = false;
3
+ let level = "einfache";
4
+ let savedParagraphs = [];
5
+ let abortController = null;
6
+ let overlayEl = null;
7
+ let skippedBlocks = 0;
8
+ let resizeObserver = null;
9
+ let mutationObserver = null;
10
+ const preReplaceDimensions = /* @__PURE__ */ new Map();
11
+ const STORAGE_KEY = "accessify-text-simplify";
12
+ const SIMPLIFIED_ATTR = "data-accessify-simplified";
13
+ const ORIGINAL_ATTR = "data-accessify-original";
14
+ const BLOCK_HASH_ATTR = "data-accessify-block-hash";
15
+ const CLIENT_CACHE_DB = "accessify-simplify-cache";
16
+ const CLIENT_CACHE_STORE = "blocks";
17
+ const CLIENT_CACHE_VERSION = 1;
18
+ function openClientCache() {
19
+ return new Promise((resolve, reject) => {
20
+ const req = indexedDB.open(CLIENT_CACHE_DB, CLIENT_CACHE_VERSION);
21
+ req.onupgradeneeded = () => {
22
+ const db = req.result;
23
+ if (!db.objectStoreNames.contains(CLIENT_CACHE_STORE)) {
24
+ db.createObjectStore(CLIENT_CACHE_STORE);
25
+ }
26
+ };
27
+ req.onsuccess = () => resolve(req.result);
28
+ req.onerror = () => reject(req.error);
29
+ });
30
+ }
31
+ async function getClientCached(key) {
32
+ try {
33
+ const db = await openClientCache();
34
+ return new Promise((resolve) => {
35
+ const tx = db.transaction(CLIENT_CACHE_STORE, "readonly");
36
+ const store = tx.objectStore(CLIENT_CACHE_STORE);
37
+ const req = store.get(key);
38
+ req.onsuccess = () => resolve(req.result ?? null);
39
+ req.onerror = () => resolve(null);
40
+ });
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+ async function setClientCached(key, value) {
46
+ try {
47
+ const db = await openClientCache();
48
+ const tx = db.transaction(CLIENT_CACHE_STORE, "readwrite");
49
+ tx.objectStore(CLIENT_CACHE_STORE).put(value, key);
50
+ } catch {
51
+ }
52
+ }
53
+ function clientCacheKey(blockHash) {
54
+ const pageUrl = window.location.origin + window.location.pathname;
55
+ return `${pageUrl}:simplify:${level}:${blockHash}`;
56
+ }
57
+ function getConfig() {
58
+ const script = document.querySelector("script[data-site-key]");
59
+ const siteKey = script?.getAttribute("data-site-key") || window.Accessify?.config?.siteKey || "";
60
+ const proxyUrl = script?.getAttribute("data-proxy-url") || window.Accessify?.config?.proxyUrl || "";
61
+ return { siteKey: siteKey || void 0, proxyUrl: proxyUrl || void 0 };
62
+ }
63
+ function getTextElements() {
64
+ const selectors = "p, li, td, th, blockquote, figcaption, .hero-subtitle, h1, h2, h3, h4, h5, h6";
65
+ const elements = [];
66
+ const seen = /* @__PURE__ */ new Set();
67
+ document.querySelectorAll(selectors).forEach((el) => {
68
+ const htmlEl = el;
69
+ if (htmlEl.closest("#accessify-root")) return;
70
+ if (htmlEl.offsetParent === null && htmlEl.style.display !== "fixed") return;
71
+ const text = htmlEl.textContent?.trim() || "";
72
+ if (text.length < 20) return;
73
+ if (seen.has(htmlEl)) return;
74
+ let dominated = false;
75
+ for (const s of seen) {
76
+ if (s.contains(htmlEl)) {
77
+ dominated = true;
78
+ break;
79
+ }
80
+ }
81
+ if (dominated) return;
82
+ seen.add(htmlEl);
83
+ elements.push(htmlEl);
84
+ });
85
+ return elements;
86
+ }
87
+ function hashText(text) {
88
+ const normalized = text.replace(/\s+/g, " ").trim().toLowerCase();
89
+ let hash = 5381;
90
+ for (let i = 0; i < normalized.length; i++) {
91
+ hash = (hash << 5) + hash + normalized.charCodeAt(i) & 2147483647;
92
+ }
93
+ return hash.toString(36);
94
+ }
95
+ function getLeafTextNodes(root) {
96
+ const textNodes = [];
97
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
98
+ let node;
99
+ while (node = walker.nextNode()) {
100
+ const trimmed = node.nodeValue?.trim();
101
+ if (trimmed && trimmed.length > 0) {
102
+ textNodes.push(node);
103
+ }
104
+ }
105
+ return textNodes;
106
+ }
107
+ function replaceLeafTextNodes(el, simplifiedText) {
108
+ const textNodes = getLeafTextNodes(el);
109
+ if (textNodes.length === 0) return;
110
+ if (textNodes.length === 1) {
111
+ textNodes[0].nodeValue = simplifiedText;
112
+ return;
113
+ }
114
+ const sentences = simplifiedText.match(/[^.!?]+[.!?]*\s*/g) || [simplifiedText];
115
+ const totalOriginalLen = textNodes.reduce((sum, n) => sum + (n.nodeValue?.trim().length || 0), 0);
116
+ if (totalOriginalLen === 0) {
117
+ textNodes[0].nodeValue = simplifiedText;
118
+ for (let i = 1; i < textNodes.length; i++) {
119
+ textNodes[i].nodeValue = "";
120
+ }
121
+ return;
122
+ }
123
+ let sentenceIndex = 0;
124
+ for (let i = 0; i < textNodes.length; i++) {
125
+ const nodeWeight = (textNodes[i].nodeValue?.trim().length || 0) / totalOriginalLen;
126
+ const sentenceCount = Math.max(1, Math.round(nodeWeight * sentences.length));
127
+ const chunk = sentences.slice(sentenceIndex, sentenceIndex + sentenceCount).join("");
128
+ textNodes[i].nodeValue = chunk || "";
129
+ sentenceIndex += sentenceCount;
130
+ }
131
+ if (sentenceIndex < sentences.length) {
132
+ const lastNode = textNodes[textNodes.length - 1];
133
+ lastNode.nodeValue = (lastNode.nodeValue || "") + sentences.slice(sentenceIndex).join("");
134
+ }
135
+ }
136
+ function measureElement(el) {
137
+ return { scrollHeight: el.scrollHeight, clientHeight: el.clientHeight };
138
+ }
139
+ function findClippingAncestor(el) {
140
+ let current = el;
141
+ while (current && current !== document.body) {
142
+ const style = getComputedStyle(current);
143
+ const overflow = style.overflow + " " + style.overflowY;
144
+ const hasHiddenOverflow = overflow.includes("hidden") || overflow.includes("clip");
145
+ const hasFixedHeight = style.maxHeight !== "none" || style.height !== "auto" && style.height !== "" && !style.height.includes("%");
146
+ if (hasHiddenOverflow && hasFixedHeight) {
147
+ return current;
148
+ }
149
+ current = current.parentElement;
150
+ }
151
+ return null;
152
+ }
153
+ function checkLayoutSafety(el) {
154
+ const patches = [];
155
+ const after = measureElement(el);
156
+ const isElementOverflowing = after.scrollHeight > after.clientHeight + 2;
157
+ if (!isElementOverflowing) {
158
+ const clipAncestor2 = findClippingAncestor(el);
159
+ if (!clipAncestor2) return { safe: true, patches: [] };
160
+ const ancestorAfter = measureElement(clipAncestor2);
161
+ if (ancestorAfter.scrollHeight <= ancestorAfter.clientHeight + 2) {
162
+ return { safe: true, patches: [] };
163
+ }
164
+ return tryAncestorPatches(clipAncestor2, patches);
165
+ }
166
+ const clipAncestor = findClippingAncestor(el);
167
+ if (!clipAncestor) {
168
+ return { safe: true, patches: [] };
169
+ }
170
+ return tryAncestorPatches(clipAncestor, patches);
171
+ }
172
+ function tryAncestorPatches(ancestor, patches) {
173
+ const style = getComputedStyle(ancestor);
174
+ if (style.maxHeight !== "none") {
175
+ patches.push({
176
+ el: ancestor,
177
+ property: "maxHeight",
178
+ originalValue: ancestor.style.maxHeight
179
+ });
180
+ ancestor.style.maxHeight = "none";
181
+ }
182
+ if (style.overflow.includes("hidden") || style.overflowY.includes("hidden")) {
183
+ patches.push({
184
+ el: ancestor,
185
+ property: "overflow",
186
+ originalValue: ancestor.style.overflow
187
+ });
188
+ ancestor.style.overflow = "visible";
189
+ }
190
+ const afterPatch = measureElement(ancestor);
191
+ if (afterPatch.scrollHeight <= afterPatch.clientHeight + 2) {
192
+ return { safe: true, patches };
193
+ }
194
+ revertPatches(patches);
195
+ return { safe: false, patches: [] };
196
+ }
197
+ function revertPatches(patches) {
198
+ for (const patch of patches) {
199
+ patch.el.style[patch.property] = patch.originalValue;
200
+ }
201
+ }
202
+ function setupResizeObserver() {
203
+ if (resizeObserver) return;
204
+ resizeObserver = new ResizeObserver((entries) => {
205
+ for (const entry of entries) {
206
+ const el = entry.target;
207
+ if (!el.hasAttribute(SIMPLIFIED_ATTR)) continue;
208
+ const saved = savedParagraphs.find((sp) => sp.el === el);
209
+ if (!saved) continue;
210
+ const clipAncestor = findClippingAncestor(el);
211
+ if (clipAncestor) {
212
+ const dims = measureElement(clipAncestor);
213
+ if (dims.scrollHeight > dims.clientHeight + 2) {
214
+ console.warn(
215
+ "[Accessify] ResizeObserver detected clipping after external layout change, reverting block:",
216
+ el
217
+ );
218
+ revertSingleBlock(saved);
219
+ skippedBlocks++;
220
+ }
221
+ }
222
+ }
223
+ });
224
+ }
225
+ function setupMutationObserver() {
226
+ if (mutationObserver) return;
227
+ mutationObserver = new MutationObserver((mutations) => {
228
+ for (const mutation of mutations) {
229
+ for (const removed of mutation.removedNodes) {
230
+ if (!(removed instanceof HTMLElement)) continue;
231
+ const idx = savedParagraphs.findIndex((sp) => sp.el === removed || removed.contains(sp.el));
232
+ if (idx !== -1) {
233
+ const saved = savedParagraphs[idx];
234
+ resizeObserver?.unobserve(saved.el);
235
+ saved.el.removeAttribute(SIMPLIFIED_ATTR);
236
+ saved.el.removeAttribute(ORIGINAL_ATTR);
237
+ saved.el.removeAttribute(BLOCK_HASH_ATTR);
238
+ revertPatches(saved.ancestorPatches);
239
+ savedParagraphs.splice(idx, 1);
240
+ }
241
+ }
242
+ if (mutation.type === "characterData" || mutation.type === "childList") {
243
+ const target = mutation.target instanceof HTMLElement ? mutation.target : mutation.target.parentElement;
244
+ if (!target) continue;
245
+ const simplifiedEl = target.closest(`[${SIMPLIFIED_ATTR}]`);
246
+ if (simplifiedEl) {
247
+ const saved = savedParagraphs.find((sp) => sp.el === simplifiedEl);
248
+ if (saved && !simplifiedEl.hasAttribute("data-accessify-replacing")) {
249
+ console.warn(
250
+ "[Accessify] External mutation detected on simplified block, cleaning up tracking:",
251
+ simplifiedEl
252
+ );
253
+ resizeObserver?.unobserve(saved.el);
254
+ saved.el.removeAttribute(SIMPLIFIED_ATTR);
255
+ saved.el.removeAttribute(ORIGINAL_ATTR);
256
+ saved.el.removeAttribute(BLOCK_HASH_ATTR);
257
+ revertPatches(saved.ancestorPatches);
258
+ savedParagraphs = savedParagraphs.filter((sp) => sp.el !== simplifiedEl);
259
+ }
260
+ }
261
+ }
262
+ }
263
+ });
264
+ mutationObserver.observe(document.body, {
265
+ childList: true,
266
+ subtree: true,
267
+ characterData: true
268
+ });
269
+ }
270
+ function disconnectObservers() {
271
+ if (resizeObserver) {
272
+ resizeObserver.disconnect();
273
+ resizeObserver = null;
274
+ }
275
+ if (mutationObserver) {
276
+ mutationObserver.disconnect();
277
+ mutationObserver = null;
278
+ }
279
+ preReplaceDimensions.clear();
280
+ }
281
+ function safeReplace(el, simplifiedText, blockHash) {
282
+ const originalHtml = el.innerHTML;
283
+ el.setAttribute("data-accessify-replacing", "true");
284
+ replaceLeafTextNodes(el, simplifiedText);
285
+ const { safe, patches } = checkLayoutSafety(el);
286
+ if (!safe) {
287
+ el.innerHTML = originalHtml;
288
+ el.removeAttribute("data-accessify-replacing");
289
+ console.warn(
290
+ "[Accessify] Block skipped — layout clipping detected after replacement:",
291
+ el.textContent?.slice(0, 60)
292
+ );
293
+ skippedBlocks++;
294
+ return false;
295
+ }
296
+ el.removeAttribute("data-accessify-replacing");
297
+ el.setAttribute(SIMPLIFIED_ATTR, "true");
298
+ el.setAttribute(ORIGINAL_ATTR, originalHtml);
299
+ if (blockHash) {
300
+ el.setAttribute(BLOCK_HASH_ATTR, blockHash);
301
+ }
302
+ savedParagraphs.push({ el, originalHtml, ancestorPatches: patches });
303
+ resizeObserver?.observe(el);
304
+ return true;
305
+ }
306
+ function revertSingleBlock(saved) {
307
+ saved.el.innerHTML = saved.originalHtml;
308
+ saved.el.removeAttribute(SIMPLIFIED_ATTR);
309
+ saved.el.removeAttribute(ORIGINAL_ATTR);
310
+ saved.el.removeAttribute(BLOCK_HASH_ATTR);
311
+ revertPatches(saved.ancestorPatches);
312
+ resizeObserver?.unobserve(saved.el);
313
+ savedParagraphs = savedParagraphs.filter((sp) => sp.el !== saved.el);
314
+ }
315
+ async function fetchManifest(siteKey, proxyUrl) {
316
+ const base = proxyUrl || "https://accessify-api.accessify.workers.dev";
317
+ const pageUrl = encodeURIComponent(window.location.origin + window.location.pathname);
318
+ const url = `${base}/v1/manifest?siteKey=${siteKey}&url=${pageUrl}&feature=simplify&variant=${level}`;
319
+ try {
320
+ const res = await fetch(url);
321
+ if (!res.ok) return null;
322
+ const data = await res.json();
323
+ if (!data.blocks?.length) return null;
324
+ return data;
325
+ } catch {
326
+ return null;
327
+ }
328
+ }
329
+ function applyManifestBlocks(manifest, elements) {
330
+ const applied = [];
331
+ const remaining = [];
332
+ const byHash = /* @__PURE__ */ new Map();
333
+ for (const block of manifest.blocks) {
334
+ byHash.set(block.blockHash, block);
335
+ }
336
+ for (const el of elements) {
337
+ const text = el.textContent?.trim() || "";
338
+ const elHash = hashText(text);
339
+ const cached = byHash.get(elHash);
340
+ if (cached?.result) {
341
+ const success = safeReplace(el, cached.result, elHash);
342
+ if (success) {
343
+ applied.push(el);
344
+ } else {
345
+ remaining.push(el);
346
+ }
347
+ } else {
348
+ remaining.push(el);
349
+ }
350
+ }
351
+ return { applied, remaining };
352
+ }
353
+ function persistToManifest(siteKey, blockHash, originalText, simplifiedText, proxyUrl) {
354
+ const base = proxyUrl || "https://accessify-api.accessify.workers.dev";
355
+ const pageUrl = window.location.origin + window.location.pathname;
356
+ fetch(`${base}/v1/cache/persist`, {
357
+ method: "POST",
358
+ headers: { "Content-Type": "application/json" },
359
+ body: JSON.stringify({
360
+ siteKey,
361
+ url: pageUrl,
362
+ feature: "simplify",
363
+ variant: level,
364
+ blockHash,
365
+ originalText,
366
+ result: simplifiedText
367
+ })
368
+ }).catch((err) => {
369
+ console.warn("[Accessify] Failed to persist live simplification:", err);
370
+ });
371
+ }
372
+ function markLoading(el) {
373
+ el.style.opacity = "0.5";
374
+ el.style.transition = "opacity 0.3s ease";
375
+ }
376
+ function clearLoading(el) {
377
+ el.style.opacity = "";
378
+ el.style.transition = "";
379
+ }
380
+ function showProgress(current, total, skipped = 0) {
381
+ if (!overlayEl) {
382
+ overlayEl = document.createElement("div");
383
+ overlayEl.setAttribute("role", "status");
384
+ overlayEl.setAttribute("aria-live", "polite");
385
+ Object.assign(overlayEl.style, {
386
+ position: "fixed",
387
+ bottom: "80px",
388
+ right: "24px",
389
+ zIndex: "2147483645",
390
+ padding: "10px 18px",
391
+ background: "#1a1a2e",
392
+ color: "#4ea8de",
393
+ borderRadius: "10px",
394
+ boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
395
+ fontFamily: "system-ui, -apple-system, sans-serif",
396
+ fontSize: "13px",
397
+ fontWeight: "600",
398
+ display: "flex",
399
+ alignItems: "center",
400
+ gap: "8px"
401
+ });
402
+ document.body.appendChild(overlayEl);
403
+ }
404
+ const pct = Math.round(current / total * 100);
405
+ const skippedNote = skipped > 0 ? lang.startsWith("de") ? ` (${skipped} übersprungen)` : ` (${skipped} skipped)` : "";
406
+ const label = lang.startsWith("de") ? `Wird vereinfacht... ${current}/${total} (${pct}%)${skippedNote}` : `Simplifying... ${current}/${total} (${pct}%)${skippedNote}`;
407
+ overlayEl.innerHTML = `<span style="display:inline-block;width:14px;height:14px;border:2px solid rgba(78,168,222,0.3);border-top-color:#4ea8de;border-radius:50%;animation:accessify-autospin 0.6s linear infinite"></span> ${label}`;
408
+ if (!document.getElementById("accessify-autospin-style")) {
409
+ const style = document.createElement("style");
410
+ style.id = "accessify-autospin-style";
411
+ style.textContent = "@keyframes accessify-autospin { to { transform: rotate(360deg); } }";
412
+ document.head.appendChild(style);
413
+ }
414
+ }
415
+ function showDone(count, fromCache) {
416
+ if (overlayEl) {
417
+ const cacheNote = fromCache > 0 ? lang.startsWith("de") ? ` (${fromCache} aus Cache)` : ` (${fromCache} from cache)` : "";
418
+ const skippedNote = skippedBlocks > 0 ? lang.startsWith("de") ? `, ${skippedBlocks} übersprungen` : `, ${skippedBlocks} skipped` : "";
419
+ const label = lang.startsWith("de") ? `${count} Textabschnitte vereinfacht${cacheNote}${skippedNote}` : `${count} text sections simplified${cacheNote}${skippedNote}`;
420
+ overlayEl.innerHTML = `<span style="color:#22c55e">&#x2713;</span> ${label}`;
421
+ overlayEl.style.color = "#22c55e";
422
+ setTimeout(() => removeProgress(), 3e3);
423
+ }
424
+ }
425
+ function showError(msg) {
426
+ if (overlayEl) {
427
+ overlayEl.innerHTML = `<span style="color:#ef4444">&#x2715;</span> ${msg}`;
428
+ overlayEl.style.color = "#ef4444";
429
+ setTimeout(() => removeProgress(), 5e3);
430
+ }
431
+ }
432
+ function removeProgress() {
433
+ overlayEl?.remove();
434
+ overlayEl = null;
435
+ document.getElementById("accessify-autospin-style")?.remove();
436
+ }
437
+ async function simplifyPage() {
438
+ const elements = getTextElements();
439
+ if (elements.length === 0) return;
440
+ abortController = new AbortController();
441
+ savedParagraphs = [];
442
+ skippedBlocks = 0;
443
+ setupResizeObserver();
444
+ setupMutationObserver();
445
+ const { siteKey, proxyUrl } = getConfig();
446
+ let fromCache = 0;
447
+ let remaining = elements;
448
+ if (siteKey) {
449
+ showProgress(0, elements.length);
450
+ const manifest = await fetchManifest(siteKey, proxyUrl);
451
+ if (manifest?.blocks?.length) {
452
+ const result = applyManifestBlocks(manifest, elements);
453
+ fromCache = result.applied.length;
454
+ remaining = result.remaining;
455
+ for (const block of manifest.blocks) {
456
+ if (block.result) {
457
+ setClientCached(clientCacheKey(block.blockHash), block.result);
458
+ }
459
+ }
460
+ if (remaining.length === 0) {
461
+ showDone(fromCache, fromCache);
462
+ return;
463
+ }
464
+ }
465
+ }
466
+ {
467
+ const stillRemaining = [];
468
+ for (const el of remaining) {
469
+ const text = el.textContent?.trim() || "";
470
+ if (text.length < 20) {
471
+ stillRemaining.push(el);
472
+ continue;
473
+ }
474
+ const blockHash = hashText(text);
475
+ const cached = await getClientCached(clientCacheKey(blockHash));
476
+ if (cached) {
477
+ const success = safeReplace(el, cached, blockHash);
478
+ if (success) {
479
+ fromCache++;
480
+ } else {
481
+ stillRemaining.push(el);
482
+ }
483
+ } else {
484
+ stillRemaining.push(el);
485
+ }
486
+ }
487
+ remaining = stillRemaining;
488
+ if (remaining.length === 0) {
489
+ showDone(fromCache, fromCache);
490
+ return;
491
+ }
492
+ }
493
+ if (!aiService && remaining.length > 0) {
494
+ if (fromCache > 0) {
495
+ showDone(fromCache, fromCache);
496
+ } else {
497
+ showProgress(0, 1);
498
+ showError(lang.startsWith("de") ? "Kein API-Key konfiguriert" : "No API key configured");
499
+ }
500
+ return;
501
+ }
502
+ for (const el of remaining) {
503
+ markLoading(el);
504
+ }
505
+ const totalElements = elements.length;
506
+ let completed = fromCache;
507
+ let totalSimplified = fromCache;
508
+ showProgress(completed, totalElements, skippedBlocks);
509
+ for (const el of remaining) {
510
+ if (abortController.signal.aborted) break;
511
+ const text = el.textContent?.trim() || "";
512
+ if (text.length < 20) {
513
+ clearLoading(el);
514
+ completed++;
515
+ showProgress(completed, totalElements, skippedBlocks);
516
+ continue;
517
+ }
518
+ const blockHash = hashText(text);
519
+ try {
520
+ const simplified = await aiService.simplifyText(text, level, lang);
521
+ if (abortController?.signal.aborted) return;
522
+ if (simplified && simplified !== text) {
523
+ const success = safeReplace(el, simplified, blockHash);
524
+ if (success) {
525
+ totalSimplified++;
526
+ setClientCached(clientCacheKey(blockHash), simplified);
527
+ if (siteKey) {
528
+ persistToManifest(siteKey, blockHash, text, simplified, proxyUrl);
529
+ }
530
+ }
531
+ }
532
+ } catch (err) {
533
+ if (err?.message?.includes("429")) {
534
+ await new Promise((r) => setTimeout(r, 8e3));
535
+ try {
536
+ const retry = await aiService.simplifyText(text, level, lang);
537
+ if (abortController?.signal.aborted) return;
538
+ if (retry && retry !== text) {
539
+ const success = safeReplace(el, retry, blockHash);
540
+ if (success) {
541
+ totalSimplified++;
542
+ setClientCached(clientCacheKey(blockHash), retry);
543
+ if (siteKey) {
544
+ persistToManifest(siteKey, blockHash, text, retry, proxyUrl);
545
+ }
546
+ }
547
+ }
548
+ } catch {
549
+ }
550
+ } else {
551
+ console.warn("[Accessify] Failed to simplify:", err);
552
+ }
553
+ } finally {
554
+ clearLoading(el);
555
+ completed++;
556
+ if (!abortController?.signal.aborted) {
557
+ showProgress(completed, totalElements, skippedBlocks);
558
+ await new Promise((r) => setTimeout(r, 1200));
559
+ }
560
+ }
561
+ }
562
+ if (!abortController?.signal.aborted) {
563
+ showDone(totalSimplified, fromCache);
564
+ }
565
+ }
566
+ function restorePage() {
567
+ disconnectObservers();
568
+ for (const { el, originalHtml, ancestorPatches } of savedParagraphs) {
569
+ el.innerHTML = originalHtml;
570
+ el.removeAttribute(ORIGINAL_ATTR);
571
+ el.removeAttribute(SIMPLIFIED_ATTR);
572
+ el.removeAttribute(BLOCK_HASH_ATTR);
573
+ el.removeAttribute("data-accessify-replacing");
574
+ clearLoading(el);
575
+ revertPatches(ancestorPatches);
576
+ }
577
+ savedParagraphs = [];
578
+ skippedBlocks = 0;
579
+ }
580
+ function loadPreferences() {
581
+ try {
582
+ const saved = localStorage.getItem(STORAGE_KEY);
583
+ if (saved) {
584
+ const parsed = JSON.parse(saved);
585
+ if (parsed.level === "einfache" || parsed.level === "leichte") {
586
+ level = parsed.level;
587
+ }
588
+ }
589
+ } catch {
590
+ }
591
+ }
592
+ function savePreferences() {
593
+ localStorage.setItem(STORAGE_KEY, JSON.stringify({ level }));
594
+ }
595
+ function activate() {
596
+ if (enabled) return;
597
+ enabled = true;
598
+ loadPreferences();
599
+ simplifyPage();
600
+ }
601
+ function deactivate() {
602
+ enabled = false;
603
+ abortController?.abort();
604
+ abortController = null;
605
+ restorePage();
606
+ removeProgress();
607
+ }
608
+ return {
609
+ id: "text-simplify",
610
+ name: () => lang.startsWith("de") ? "Text vereinfachen" : "Simplify Text",
611
+ description: lang.startsWith("de") ? "Text in Einfache Sprache umwandeln" : "Simplify text for easier understanding",
612
+ icon: "simplify-text",
613
+ category: "ai",
614
+ activate,
615
+ deactivate,
616
+ getState: () => ({
617
+ id: "text-simplify",
618
+ enabled,
619
+ value: { level }
620
+ }),
621
+ setState: (newState) => {
622
+ if (newState.level && (newState.level === "einfache" || newState.level === "leichte")) {
623
+ level = newState.level;
624
+ savePreferences();
625
+ }
626
+ }
627
+ };
628
+ }
629
+ export {
630
+ createTextSimplifyModule as default
631
+ };
632
+ //# sourceMappingURL=text-simplify-C9gzE3t0.js.map