UNPKG

@neuroequality/neuroadapt-ai

Version:

AI-powered accessibility personalization for neurodivergent users

236 lines (234 loc) 7.73 kB
import { EventEmitter as p } from "eventemitter3"; class d extends p { constructor(t = {}) { super(), this.processingQueue = [], this.activeProcessing = /* @__PURE__ */ new Map(), this.adaptationCache = /* @__PURE__ */ new Map(), this.config = { chunkSize: t.chunkSize || 500, // characters processingDelay: t.processingDelay || 100, // ms enableRealTimeAnalysis: t.enableRealTimeAnalysis ?? !0, adaptationThreshold: t.adaptationThreshold || 0.7, maxConcurrentChunks: t.maxConcurrentChunks || 3, retryAttempts: t.retryAttempts || 2 }, this.processingStats = this.createEmptyStats(), this.startProcessingLoop(); } /** * Process content with user preferences */ async processContent(t, e, n) { const s = Date.now(), i = this.generateContentId(t), r = this.adaptationCache.get(i); if (r) return r; try { const a = await this.adaptContent(t, e, n), o = this.detectAppliedAdaptations(t, a, e), c = { id: i, originalContent: t, adaptedContent: a, adaptations: o, confidence: this.calculateConfidence(o, e), processingTime: Date.now() - s, metadata: { preferences: e, context: n, timestamp: Date.now() } }; if (this.adaptationCache.set(i, c), this.adaptationCache.size > 100) { const h = this.adaptationCache.keys().next().value; this.adaptationCache.delete(h); } return this.emit("content-processed", c), c; } catch (a) { const o = a instanceof Error ? a : new Error(String(a)); throw this.emit("error", o), o; } } /** * Process streaming content chunks */ async processStreamChunks(t, e, n) { let s = "", i = 0; const r = Date.now(); try { for await (const a of t) if (a.type === "token") { if (s += a.content, this.shouldProcessBuffer(s)) { const o = await this.processChunk( s, i++, e, n ); this.emit("chunk-processed", o), s = ""; } } else if (a.type === "done") { if (s.trim()) { const c = await this.processChunk( s, i++, e, n ); this.emit("chunk-processed", c); } const o = { ...this.processingStats, totalProcessingTime: Date.now() - r }; this.emit("processing-complete", o); break; } else if (a.type === "error") throw new Error(`Stream error: ${a.content}`); } catch (a) { const o = a instanceof Error ? a : new Error(String(a)); throw this.emit("error", o), o; } } /** * Add content to processing queue */ queueContent(t, e, n) { const s = this.generateContentId(t), i = { id: s, content: t, preferences: e, context: n, timestamp: Date.now(), retries: 0 }; return this.processingQueue.push(i), s; } /** * Get processing statistics */ getProcessingStats() { return { ...this.processingStats }; } /** * Clear adaptation cache */ clearCache() { this.adaptationCache.clear(); } /** * Get cache information */ getCacheInfo() { return { size: this.adaptationCache.size, keys: Array.from(this.adaptationCache.keys()) }; } /** * Stop processing and clean up */ destroy() { this.processingQueue = [], this.activeProcessing.clear(), this.adaptationCache.clear(), this.removeAllListeners(); } // Private methods generateContentId(t) { let e = 0; for (let n = 0; n < t.length; n++) { const s = t.charCodeAt(n); e = (e << 5) - e + s, e = e & e; } return `content_${Math.abs(e)}_${Date.now()}`; } async adaptContent(t, e, n) { let s = t; return e.highContrast && (s = this.applyHighContrastAdaptation(s)), e.motionReduction && (s = this.applyMotionReductionAdaptation(s)), typeof e.fontSize == "number" && e.fontSize !== 1 && (s = this.applyFontSizeAdaptation(s, e.fontSize)), typeof e.chunkSize == "number" && e.chunkSize < 4 && (s = await this.applyContentChunking(s, e.chunkSize)), e.simplifyLanguage && (s = await this.applyLanguageSimplification(s)), s; } applyHighContrastAdaptation(t) { return t.replace( /<(p|div|span|h[1-6])([^>]*)>/gi, '<$1$2 data-high-contrast="true">' ); } applyMotionReductionAdaptation(t) { return t.replace(/autoplay/gi, "data-autoplay-disabled").replace(/animation-/gi, "data-animation-disabled-").replace(/<video([^>]*)\s+autoplay/gi, "<video$1 data-motion-reduced"); } applyFontSizeAdaptation(t, e) { const n = Math.round(e * 100); return t.replace( /<(p|div|span|h[1-6])([^>]*)>/gi, `<$1$2 style="font-size: ${n}%">` ); } async applyContentChunking(t, e) { const n = t.split(/[.!?]+/).filter((i) => i.trim()), s = []; for (let i = 0; i < n.length; i += e) { const r = n.slice(i, i + e).join(". "); s.push(`<div class="content-chunk">${r}</div>`); } return s.join(` <div class="chunk-break"></div> `); } async applyLanguageSimplification(t) { return t.replace(/utilize/gi, "use").replace(/demonstrate/gi, "show").replace(/accomplish/gi, "do").replace(/nevertheless/gi, "but").replace(/consequently/gi, "so"); } detectAppliedAdaptations(t, e, n) { const s = []; return e.includes("data-high-contrast") && s.push("High contrast styling applied"), e.includes("data-motion-reduced") && s.push("Motion reduction applied"), e.includes("font-size:") && s.push("Font size adjustment applied"), e.includes("content-chunk") && s.push("Content chunking applied"), t !== e && s.length === 0 && s.push("Language simplification applied"), s; } calculateConfidence(t, e) { const n = Object.keys(e).length, s = t.length; return Math.min(s / Math.max(n, 1), 1); } shouldProcessBuffer(t) { return t.length >= this.config.chunkSize || /[.!?]\s/.test(t) || t.includes(` `); } async processChunk(t, e, n, s) { const i = await this.adaptContent(t, n, s), r = this.detectAppliedAdaptations(t, i, n); return this.processingStats.processedChunks++, this.processingStats.totalAdaptations += r.length, { id: `chunk_${e}`, chunkIndex: e, content: i, adaptations: r, confidence: this.calculateConfidence(r, n), timestamp: Date.now() }; } startProcessingLoop() { setInterval(() => { this.processQueue(); }, this.config.processingDelay); } async processQueue() { if (this.processingQueue.length === 0 || this.activeProcessing.size >= this.config.maxConcurrentChunks) return; const t = this.processingQueue.shift(); if (!t) return; const e = this.processQueueItem(t); this.activeProcessing.set(t.id, e); try { await e; } finally { this.activeProcessing.delete(t.id); } } async processQueueItem(t) { try { const e = await this.processContent(t.content, t.preferences, t.context); this.processingStats.totalChunks++; } catch (e) { this.processingStats.failedChunks++, t.retries < this.config.retryAttempts ? (t.retries++, this.processingQueue.push(t)) : this.emit("error", e instanceof Error ? e : new Error(String(e))); } } createEmptyStats() { return { totalChunks: 0, processedChunks: 0, failedChunks: 0, totalAdaptations: 0, averageConfidence: 0, totalProcessingTime: 0, suggestedImprovements: [] }; } } export { d as C }; //# sourceMappingURL=content-adapter-CwBp76TE.js.map