@neuroequality/neuroadapt-ai
Version:
AI-powered accessibility personalization for neurodivergent users
236 lines (234 loc) • 7.73 kB
JavaScript
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