This commit is contained in:
overcuriousity
2025-07-31 22:16:52 +02:00
parent 680a2c311d
commit 224f717ba8
3 changed files with 179 additions and 123 deletions

View File

@@ -215,6 +215,9 @@ const domainAgnosticSoftware = data['domain-agnostic-software'] || [];
// SIMPLIFIED AI QUERY INTERFACE - CONSOLIDATED & MAINTAINABLE
// ===================================================================
// Enhanced AI Interface JavaScript - Fix for text rendering issues in AIQueryInterface.astro
// This code replaces the existing <script> section in AIQueryInterface.astro
class AIQueryInterface {
constructor() {
this.currentMode = 'workflow';
@@ -368,9 +371,7 @@ class AIQueryInterface {
}
}
// ===================================================================
// INPUT HANDLING & SMART PROMPTING
// ===================================================================
// [Previous methods remain the same until displayResults...]
handleInputChange() {
this.updateCharacterCount();
@@ -578,9 +579,7 @@ class AIQueryInterface {
}
}
// ===================================================================
// QUEUE MONITORING
// ===================================================================
// [Queue monitoring methods remain the same...]
startQueueMonitoring(taskId) {
if (this.elements.queueStatus) {
@@ -712,7 +711,7 @@ class AIQueryInterface {
}
// ===================================================================
// RESULTS DISPLAY
// RESULTS DISPLAY - ENHANCED with proper text formatting
// ===================================================================
displayResults(recommendation, originalQuery) {
@@ -757,7 +756,6 @@ class AIQueryInterface {
${this.renderBackgroundKnowledge(recommendation.background_knowledge)}
${this.renderWorkflowPhases(toolsByPhase, phaseOrder, phaseNames)}
${this.renderWorkflowSuggestion(recommendation.workflow_suggestion)}
${this.renderAdditionalNotes(recommendation.additional_notes)}
</div>
`;
@@ -789,6 +787,7 @@ class AIQueryInterface {
`;
}
// ENHANCED: Fixed text rendering to prevent markdown/list interpretation
renderContextualAnalysis(recommendation, mode) {
let html = '';
@@ -799,7 +798,7 @@ class AIQueryInterface {
<h4 style="margin: 0 0 1rem 0; color: var(--color-primary);">
${mode === 'workflow' ? 'Szenario-Analyse' : 'Problem-Analyse'}
</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(analysisField)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(analysisField)}</div>
</div>
`;
}
@@ -810,7 +809,7 @@ class AIQueryInterface {
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">
${mode === 'workflow' ? 'Untersuchungsansatz' : 'Lösungsansatz'}
</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.investigation_approach)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.investigation_approach)}</div>
</div>
`;
}
@@ -821,7 +820,7 @@ class AIQueryInterface {
<h4 style="margin: 0 0 1rem 0; color: var(--color-warning);">
${mode === 'workflow' ? 'Kritische Überlegungen' : 'Wichtige Voraussetzungen'}
</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.critical_considerations)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.critical_considerations)}</div>
</div>
`;
}
@@ -841,9 +840,9 @@ class AIQueryInterface {
</button>
<span class="badge" style="background-color: var(--color-concept); color: white; font-size: 0.625rem;">Hintergrundwissen</span>
</div>
<p style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary);">
${this.escapeHtml(concept.relevance)}
</p>
<div style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary); white-space: pre-wrap; word-wrap: break-word;">
${this.sanitizeText(concept.relevance)}
</div>
</div>
`).join('');
@@ -898,8 +897,8 @@ class AIQueryInterface {
</span>
</div>
<div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic;">
"${this.escapeHtml(tool.recommendation.justification)}"
<div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
"${this.sanitizeText(tool.recommendation.justification)}"
</div>
<div style="font-size: 0.75rem; color: var(--color-text-secondary);">
@@ -949,11 +948,11 @@ class AIQueryInterface {
<div style="margin-bottom: 1.5rem;">
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-accent);">Warum diese Methode?</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.detailed_explanation)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.detailed_explanation)}</div>
${recommendation.implementation_approach ? `
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-primary);">Anwendungsansatz</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.implementation_approach)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.implementation_approach)}</div>
` : ''}
</div>
@@ -973,7 +972,7 @@ class AIQueryInterface {
<div style="background-color: var(--color-oss-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-accent);">
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-accent); font-size: 0.875rem;">✓ Vorteile</h5>
<ul style="margin: 0; padding-left: 1rem;">
${pros.map(pro => `<li style="margin-bottom: 0.25rem;">${this.escapeHtml(pro)}</li>`).join('')}
${pros.map(pro => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(pro)}</li>`).join('')}
</ul>
</div>
` : ''}
@@ -981,7 +980,7 @@ class AIQueryInterface {
<div style="background-color: var(--color-hosted-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-warning);">
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-warning); font-size: 0.875rem;">✗ Nachteile</h5>
<ul style="margin: 0; padding-left: 1rem;">
${cons.map(con => `<li style="margin-bottom: 0.25rem;">${this.escapeHtml(con)}</li>`).join('')}
${cons.map(con => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(con)}</li>`).join('')}
</ul>
</div>
` : ''}
@@ -1006,7 +1005,7 @@ class AIQueryInterface {
return `
<div style="background-color: var(--color-bg-secondary); padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem;">
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-text-secondary); font-size: 0.875rem;">Alternative Ansätze</h5>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(alternatives)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(alternatives)}</div>
</div>
`;
}
@@ -1017,18 +1016,7 @@ class AIQueryInterface {
return `
<div class="card" style="margin-top: 2rem; border-left: 4px solid var(--color-accent);">
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">Workflow-Empfehlung</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(suggestion)}</p>
</div>
`;
}
renderAdditionalNotes(notes) {
if (!notes) return '';
return `
<div class="card" style="margin-top: 1rem; background-color: var(--color-warning); color: white;">
<h4 style="margin: 0 0 1rem 0;">Wichtige Hinweise</h4>
<p style="margin: 0; line-height: 1.6; color: white;">${this.escapeHtml(notes)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(suggestion)}</div>
</div>
`;
}
@@ -1039,7 +1027,7 @@ class AIQueryInterface {
return `
<div class="card" style="margin-top: 2rem; background-color: var(--color-bg-secondary); border-left: 4px solid var(--color-text-secondary);">
<h4 style="margin: 0 0 1rem 0; color: var(--color-text-secondary);">Zusätzliche Überlegungen</h4>
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(considerations)}</p>
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(considerations)}</div>
</div>
`;
}
@@ -1065,9 +1053,37 @@ class AIQueryInterface {
}
// ===================================================================
// UTILITY METHODS
// ENHANCED UTILITY METHODS with proper text sanitization
// ===================================================================
// CRITICAL: Sanitize text to prevent markdown interpretation
sanitizeText(text) {
if (typeof text !== 'string') return '';
// Remove/escape potential markdown and HTML
return text
// Remove markdown headers
.replace(/^#{1,6}\s+/gm, '')
// Remove markdown lists (bullet points and numbered)
.replace(/^\s*[-*+]\s+/gm, '')
.replace(/^\s*\d+\.\s+/gm, '')
// Remove markdown bold/italic
.replace(/\*\*(.+?)\*\*/g, '$1')
.replace(/\*(.+?)\*/g, '$1')
.replace(/__(.+?)__/g, '$1')
.replace(/_(.+?)_/g, '$1')
// Remove markdown links
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
// Remove code blocks
.replace(/```[\s\S]*?```/g, '[CODE BLOCK]')
.replace(/`([^`]+)`/g, '$1')
// Remove HTML tags
.replace(/<[^>]+>/g, '')
// Clean up excessive whitespace but preserve paragraphs
.replace(/\n\s*\n\s*\n/g, '\n\n')
.trim();
}
isToolHosted(tool) {
return tool.projectUrl !== undefined &&
tool.projectUrl !== null &&